From 22a9bbd20431315a6f13eb38bb1584235f0efa17 Mon Sep 17 00:00:00 2001 From: "S. Elliott Johnson" Date: Fri, 28 Jan 2022 16:35:49 -0700 Subject: [PATCH 01/48] feat: Added python venv to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0b4eb24 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +generate/.venv \ No newline at end of file From 88dd46ec9cd00a023e9d454b6daef84d5893c7c2 Mon Sep 17 00:00:00 2001 From: "S. Elliott Johnson" Date: Fri, 28 Jan 2022 17:52:07 -0700 Subject: [PATCH 02/48] feat: Added config and sensible default values --- generate/holidays.py | 558 ++++++++++++++++++++++++++++++++++ generate/script_generatior.py | 68 +++++ 2 files changed, 626 insertions(+) create mode 100644 generate/holidays.py create mode 100644 generate/script_generatior.py diff --git a/generate/holidays.py b/generate/holidays.py new file mode 100644 index 0000000..82bcf61 --- /dev/null +++ b/generate/holidays.py @@ -0,0 +1,558 @@ +from dataclasses import dataclass +from datetime import datetime + + +@dataclass(frozen=True) +class Holiday: + holiday_type: str + holiday_date: datetime.date + holiday_name: str + + +default_holidays: list[Holiday] = [ + Holiday("New Year's Day", datetime.fromisoformat( + '2012-01-02'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2012-01-02'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2012-01-16'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2012-01-16'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2012-02-20'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2012-05-28'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2012-05-28'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2012-07-04'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2012-07-04'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2012-09-03'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2012-09-03'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2012-10-08'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2012-11-12'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2012-11-22'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2012-11-22'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2012-11-23'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2012-12-24'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2012-12-25'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2012-12-25'), 'US Public Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2013-01-01'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2013-01-01'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2013-01-21'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2013-01-21'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2013-02-18'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2013-05-27'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2013-05-27'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2013-07-04'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2013-07-04'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2013-09-02'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2013-09-02'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2013-10-14'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2013-11-11'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2013-11-28'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2013-11-28'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2013-11-29'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2013-12-24'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2013-12-25'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2013-12-25'), 'US Public Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2014-01-01'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2014-01-01'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2014-01-20'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2014-01-20'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2014-02-17'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2014-05-26'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2014-05-26'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2014-07-04'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2014-07-04'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2014-09-01'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2014-09-01'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2014-10-13'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2014-11-11'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2014-11-27'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2014-11-28'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2014-12-24'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2014-12-25'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2014-12-25'), 'US Public Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2015-01-01'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2015-01-01'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2015-01-19'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2015-01-19'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2015-02-16'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2015-05-25'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2015-05-25'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2015-07-03'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2015-07-03'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2015-09-07'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2015-09-07'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2015-10-12'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2015-11-11'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2015-11-26'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2015-11-26'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2015-11-27'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2015-12-24'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2015-12-25'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2015-12-25'), 'US Public Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2016-01-01'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2016-01-01'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2016-01-18'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2016-01-18'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2016-02-15'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2016-05-30'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2016-05-30'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2016-07-04'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2016-07-04'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2016-09-05'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2016-09-05'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2016-10-10'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2016-11-11'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2016-11-24'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2016-11-24'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2016-11-25'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2016-12-23'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2016-12-26'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2016-12-26'), 'US Public Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2017-01-02'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2017-01-02'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2017-01-16'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2017-01-16'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2017-02-20'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2017-05-29'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2017-05-29'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2017-07-04'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2017-07-04'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2017-09-04'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2017-09-04'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2017-10-09'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2017-11-10'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2017-11-23'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2017-11-23'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2017-11-24'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2017-12-25'), 'Company Holiday'), + # This Christmas is weird. For my company, + # Christmas Eve pushes Christmas to the 26th, but + # for the government, Christmas still falls on the + # 25th. + Holiday('Christmas Day', datetime.fromisoformat( + '2017-12-25'), 'US Public Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2017-12-26'), 'Company Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2018-01-01'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2018-01-01'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2018-01-15'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2018-01-15'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2018-02-19'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2018-05-28'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2018-05-28'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2018-07-04'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2018-07-04'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2018-09-03'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2018-09-03'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2018-10-08'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2018-11-12'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2018-11-22'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2018-11-22'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2018-11-23'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2018-12-24'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2018-12-25'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2018-12-25'), 'US Public Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2019-01-01'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2019-01-01'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2019-01-21'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2019-01-21'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2019-02-18'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2019-05-27'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2019-05-27'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2019-07-04'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2019-07-04'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2019-09-02'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2019-09-02'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2019-10-14'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2019-11-11'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2019-11-28'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2019-11-28'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2019-11-29'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2019-12-24'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2019-12-25'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2019-12-25'), 'US Public Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2020-01-01'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2020-01-01'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2020-01-20'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2020-01-20'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2020-02-17'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2020-05-25'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2020-05-25'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2020-07-03'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2020-07-03'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2020-09-07'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2020-09-07'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2020-10-12'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2020-11-11'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2020-11-26'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2020-11-26'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2020-11-27'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2020-12-24'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2020-12-25'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2020-12-25'), 'US Public Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2021-01-01'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2021-01-01'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2021-01-18'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2021-01-18'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2021-02-15'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2021-05-31'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2021-05-31'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2021-07-05'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2021-07-05'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2021-09-06'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2021-09-06'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2021-10-11'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2021-11-11'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2021-11-25'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2021-11-26'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2021-12-23'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2021-12-24'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2021-12-24'), 'US Public Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2021-12-31'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2021-12-31'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2022-01-17'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2022-01-17'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2022-02-21'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2022-05-30'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2022-05-30'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2022-07-04'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2022-07-04'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2022-09-05'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2022-09-05'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2022-10-10'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2022-11-11'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2022-11-24'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2022-11-24'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2022-11-25'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2022-12-23'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2022-12-26'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2022-12-26'), 'US Public Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2023-01-02'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2023-01-02'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2023-01-16'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2023-01-16'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2023-02-20'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2023-05-29'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2023-05-29'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2023-07-04'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2023-07-04'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2023-09-04'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2023-09-04'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2023-10-09'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2023-11-10'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2023-11-23'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2023-11-23'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2023-11-24'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2023-12-25'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2023-12-25'), 'US Public Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2023-12-26'), 'Company Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2024-01-01'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2024-01-01'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2024-01-15'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2024-01-15'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2024-02-19'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2024-05-27'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2024-05-27'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2024-07-04'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2024-07-04'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2024-09-02'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2024-09-02'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2024-10-14'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2024-11-11'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2024-11-28'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2024-11-28'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2024-11-29'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2024-12-24'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2024-12-25'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2024-12-25'), 'US Public Holiday'), + + Holiday("New Year's Day", datetime.fromisoformat( + '2025-01-01'), 'Company Holiday'), + Holiday("New Year's Day", datetime.fromisoformat( + '2025-01-01'), 'US Public Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2025-01-20'), 'Company Holiday'), + Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( + '2025-01-20'), 'US Public Holiday'), + Holiday("Presidents' Day", datetime.fromisoformat( + '2025-02-17'), 'US Public Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2025-05-26'), 'Company Holiday'), + Holiday('Memorial Day', datetime.fromisoformat( + '2025-05-26'), 'US Public Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2025-07-04'), 'Company Holiday'), + Holiday('Independence Day', datetime.fromisoformat( + '2025-07-04'), 'US Public Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2025-09-01'), 'Company Holiday'), + Holiday('Labor Day', datetime.fromisoformat( + '2025-09-01'), 'US Public Holiday'), + Holiday('Columbus Day', datetime.fromisoformat( + '2025-10-13'), 'US Public Holiday'), + Holiday('Veterans Day', datetime.fromisoformat( + '2025-11-11'), 'US Public Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2025-11-27'), 'Company Holiday'), + Holiday('Thanksgiving Day', datetime.fromisoformat( + '2025-11-27'), 'US Public Holiday'), + Holiday('Friday After Thanksgiving', datetime.fromisoformat( + '2025-11-28'), 'Company Holiday'), + Holiday('Christmas Eve', datetime.fromisoformat( + '2025-12-24'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2025-12-25'), 'Company Holiday'), + Holiday('Christmas Day', datetime.fromisoformat( + '2025-12-25'), 'US Public Holiday'), +] diff --git a/generate/script_generatior.py b/generate/script_generatior.py new file mode 100644 index 0000000..a4ac48d --- /dev/null +++ b/generate/script_generatior.py @@ -0,0 +1,68 @@ +from dataclasses import dataclass +from datetime import datetime +from enum import Enum, auto +from holidays import default_holidays, Holiday + + +# class ScriptGenerator(): +# def __init__(self, ): + + +class Language(Enum): + TSQL = auto() + + +@dataclass(frozen=True) +class DateRange: + start_date: datetime.date = datetime.fromisoformat('2000-01-01').date() + num_years: int = 100 + + def __post_init__(self): + assert self.num_years > 0, 'num_years must be greater than 0.' + + +@dataclass(frozen=True) +class FiscalConfig: + fiscal_month_start_day: int = 1 + fiscal_year_start_month: int = 1 + fiscal_month_end_matches_calendar: bool = True + fiscal_quarter_end_matches_calendar: bool = True + fiscal_year_end_matches_calendar: bool = True + + def __post_init__(self): + assert 1 <= self.fiscal_month_start_day <= 28, 'fiscal_month_start_day must be between 1 and 28.' + assert 1 <= self.fiscal_year_start_month <= 12, 'fiscal_year_start_month must be between 1 and 12.' + + +@dataclass(frozen=True) +class HolidayConfig: + generate_holidays: bool = True + holiday_types: tuple[str] = ("Company Holiday", "US Public Holiday") + holiday_types_for_business_days: tuple[str] = ("Company Holiday") + holidays: list[Holiday] = default_holidays + + def __post_init__(self): + if self.generate_holidays: + assert all((holiday.holiday_type in self.holiday_types for holiday in self.holidays) + ), 'found a holiday in holidays whose holiday_type does not exist in holiday_types' + assert all(holiday_type in self.holiday_types for holiday_type in self.holiday_types_for_business_days), 'found a holiday type in holiday_types_for_business_days that is not present in holiday_types' + + +@dataclass(frozen=True) +class TableNameConfig: + dim_date_schema_name: str = "dbo" + dim_date_table_name: str = "DimDate" + holiday_types_schema_name: str = "integration" + holiday_types_table_name: str = "manual_HolidayTypes" + holidays_schema_name: str = "integration" + holidays_table_name: str = "manual_Holidays" + + +@dataclass +class ScriptGeneratorConfig: + language: Language = Language.TSQL + date_range: DateRange = DateRange() + fiscal_config: FiscalConfig = FiscalConfig() + time_zone: str = "Mountain Standard Time" + table_name_config: TableNameConfig = TableNameConfig() + holiday_config: HolidayConfig = HolidayConfig() From b0191dec69d05842e0a0560e0bcdea8dc8139911 Mon Sep 17 00:00:00 2001 From: "S. Elliott Johnson" Date: Fri, 28 Jan 2022 20:06:37 -0700 Subject: [PATCH 03/48] feat: Stubbed out TSQL generator --- generate/script_generatior.py | 23 ++++++++++++---------- generate/script_generator_factory.py | 17 ++++++++++++++++ generate/tsql_generator/tsql_generator.py | 24 +++++++++++++++++++++++ 3 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 generate/script_generator_factory.py create mode 100644 generate/tsql_generator/tsql_generator.py diff --git a/generate/script_generatior.py b/generate/script_generatior.py index a4ac48d..24846d2 100644 --- a/generate/script_generatior.py +++ b/generate/script_generatior.py @@ -1,15 +1,8 @@ from dataclasses import dataclass from datetime import datetime -from enum import Enum, auto from holidays import default_holidays, Holiday - - -# class ScriptGenerator(): -# def __init__(self, ): - - -class Language(Enum): - TSQL = auto() +from abc import ABC, abstractmethod +from pathlib import Path @dataclass(frozen=True) @@ -60,9 +53,19 @@ class TableNameConfig: @dataclass class ScriptGeneratorConfig: - language: Language = Language.TSQL + outdir_base: Path = Path('../output') date_range: DateRange = DateRange() fiscal_config: FiscalConfig = FiscalConfig() time_zone: str = "Mountain Standard Time" table_name_config: TableNameConfig = TableNameConfig() holiday_config: HolidayConfig = HolidayConfig() + + +class ScriptGenerator(ABC): + @abstractmethod + def __init__(self, config: ScriptGeneratorConfig = ScriptGeneratorConfig()): + pass + + @abstractmethod + def generate_scripts(self) -> None: + pass diff --git a/generate/script_generator_factory.py b/generate/script_generator_factory.py new file mode 100644 index 0000000..67a62d0 --- /dev/null +++ b/generate/script_generator_factory.py @@ -0,0 +1,17 @@ +from enum import Enum, auto + + +class Language(Enum): + TSQL = auto() + + +class ScriptGeneratorFactory(): + def __init__(self, language: Language): + self.script_generators = { + Language.TSQL: '' + } + + generator = self.script_generators.get(language) + if generator is None: + raise NotImplementedError( + 'The provided language does not have an implemented ScriptGenerator.') diff --git a/generate/tsql_generator/tsql_generator.py b/generate/tsql_generator/tsql_generator.py new file mode 100644 index 0000000..cdcbc1a --- /dev/null +++ b/generate/tsql_generator/tsql_generator.py @@ -0,0 +1,24 @@ +from script_generatior import ScriptGenerator, ScriptGeneratorConfig + + +class TSQLGenerator(ScriptGenerator): + def __init__(self, config: ScriptGeneratorConfig): + self._config = config + + def generate_scripts(self) -> None: + self._generate_setup_scripts() + self._generate_build_scripts() + self._generate_refresh_procs() + self._generate_table_constraints() + + def _generate_setup_scripts(self) -> None: + raise NotImplementedError() + + def _generate_build_scripts(self) -> None: + raise NotImplementedError() + + def _generate_refresh_procs(self) -> None: + raise NotImplementedError() + + def _generate_table_constraints(self) -> None: + raise NotImplementedError() From 63ecd4ffc6becaa21be4292694450c465a571596 Mon Sep 17 00:00:00 2001 From: "S. Elliott Johnson" Date: Sat, 29 Jan 2022 02:33:04 -0700 Subject: [PATCH 04/48] feat: Added column definitions --- generate/columns.py | 362 ++++++++++++++++++++++++++++++++++ generate/script_generatior.py | 73 ++++++- 2 files changed, 433 insertions(+), 2 deletions(-) create mode 100644 generate/columns.py diff --git a/generate/columns.py b/generate/columns.py new file mode 100644 index 0000000..a87701d --- /dev/null +++ b/generate/columns.py @@ -0,0 +1,362 @@ +from dataclasses import dataclass + + +@dataclass(frozen=True) +class Column: + name: str + include: bool + sort_index: int + + +@dataclass(frozen=True) +class DimDateColumns: + date_key = Column('DateKey', True, 0) + the_date = Column('TheDate', True, 1) + iso_date_name = Column('ISODateName', True, 2) + american_date_name = Column('AmericanDateName', True, 3) + day_of_week_name = Column('DayOfWeekName', True, 4) + day_of_week_abbrev = Column('DayOfWeekAbbrev', True, 5) + month_name = Column('MonthName', True, 6) + month_abbrev = Column('MonthAbbrev', True, 7) + year_week_name = Column('YearWeekName', True, 8) + year_month_name = Column('YearMonthName', True, 9) + month_year_name = Column('MonthYearName', True, 10) + year_quarter_name = Column('YearQuarterName', True, 11) + year = Column('Year', True, 12) + year_week = Column('YearWeek', True, 13) + iso_year_week_code = Column('ISOYearWeekCode', True, 14) + year_month = Column('YearMonth', True, 15) + year_quarter = Column('YearQuarter', True, 16) + day_of_week_starting_monday = Column('DayOfWeekStartingMonday', True, 17) + day_of_week = Column('DayOfWeek', True, 18) + day_of_month = Column('DayOfMonth', True, 19) + day_of_quarter = Column('DayOfQuarter', True, 20) + day_of_year = Column('DayOfYear', True, 21) + week_of_quarter = Column('WeekOfQuarter', True, 22) + week_of_year = Column('WeekOfYear', True, 23) + iso_week_of_year = Column('ISOWeekOfYear', True, 24) + month = Column('Month', True, 25) + month_of_quarter = Column('MonthOfQuarter', True, 26) + quarter = Column('Quarter', True, 27) + days_in_month = Column('DaysInMonth', True, 28) + days_in_quarter = Column('DaysInQuarter', True, 29) + days_in_year = Column('DaysInYear', True, 30) + day_offset_from_today = Column('DayOffsetFromToday', True, 31) + month_offset_from_today = Column('MonthOffsetFromToday', True, 32) + quarter_offset_from_today = Column('QuarterOffsetFromToday', True, 33) + year_offset_from_today = Column('YearOffsetFromToday', True, 34) + today_flag = Column('TodayFlag', True, 35) + current_week_starting_monday_flag = Column, 36( + 'CurrentWeekStartingMondayFlag', True, 37) + current_week_flag = Column('CurrentWeekFlag', True, 38) + prior_week_flag = Column('PriorWeekFlag', True, 39) + next_week_flag = Column('NextWeekFlag', True, 40) + current_month_flag = Column('CurrentMonthFlag', True, 41) + prior_month_flag = Column('PriorMonthFlag', True, 42) + next_month_flag = Column('NextMonthFlag', True, 43) + current_quarter_flag = Column('CurrentQuarterFlag', True, 44) + prior_quarter_flag = Column('PriorQuarterFlag', True, 45) + next_quarter_flag = Column('NextQuarterFlag', True, 46) + current_year_flag = Column('CurrentYearFlag', True, 47) + prior_year_flag = Column('PriorYearFlag', True, 48) + next_year_flag = Column('NextYearFlag', True, 49) + weekday_flag = Column('WeekdayFlag', True, 50) + business_day_flag = Column('BusinessDayFlag', True, 51) + company_holiday_flag = Column('CompanyHolidayFlag', True, 52) + us_public_holiday_flag = Column('USPublicHolidayFlag', True, 53) + first_day_of_month_flag = Column('FirstDayOfMonthFlag', True, 54) + last_day_of_month_flag = Column('LastDayOfMonthFlag', True, 55) + first_day_of_quarter_flag = Column('FirstDayOfQuarterFlag', True, 56) + last_day_of_quarter_flag = Column('LastDayOfQuarterFlag', True, 57) + first_day_of_year_flag = Column('FirstDayOfYearFlag', True, 58) + last_day_of_year_flag = Column('LastDayOfYearFlag', True, 59) + fraction_of_week = Column('FractionOfWeek', True, 60) + fraction_of_month = Column('FractionOfMonth', True, 61) + fraction_of_quarter = Column('FractionOfQuarter', True, 62) + fraction_of_year_ = Column('FractionOfYear', True, 63) + prior_day = Column('PriorDay', True, 64) + next_day = Column('NextDay', True, 65) + same_day_prior_week = Column('SameDayPriorWeek', True, 66) + same_day_prior_month = Column('SameDayPriorMonth', True, 67) + same_day_prior_quarter = Column('SameDayPriorQuarter', True, 68) + same_day_prior_year = Column('SameDayPriorYear', True, 69) + same_day_next_week = Column('SameDayNextWeek', True, 70) + same_day_next_month = Column('SameDayNextMonth', True, 71) + same_day_next_quarter = Column('SameDayNextQuarter', True, 72) + same_day_next_year = Column('SameDayNextYear', True, 73) + current_week_start = Column('CurrentWeekStart', True, 74) + current_week_end = Column('CurrentWeekEnd', True, 75) + current_month_start = Column('CurrentMonthStart', True, 76) + current_month_end = Column('CurrentMonthEnd', True, 77) + current_quarter_start = Column('CurrentQuarterStart', True, 78) + current_quarter_end = Column('CurrentQuarterEnd', True, 79) + current_year_start = Column('CurrentYearStart', True, 80) + current_year_end = Column('CurrentYearEnd', True, 81) + prior_week_start = Column('PriorWeekStart', True, 82) + prior_week_end = Column('PriorWeekEnd', True, 83) + prior_month_start = Column('PriorMonthStart', True, 84) + prior_month_end = Column('PriorMonthEnd', True, 85) + prior_quarter_start = Column('PriorQuarterStart', True, 86) + prior_quarter_end = Column('PriorQuarterEnd', True, 87) + prior_year_start = Column('PriorYearStart', True, 88) + prior_year_end = Column('PriorYearEnd', True, 89) + next_week_start = Column('NextWeekStart', True, 90) + next_week_end = Column('NextWeekEnd', True, 91) + next_month_start = Column('NextMonthStart', True, 92) + next_month_end = Column('NextMonthEnd', True, 93) + next_quarter_start = Column('NextQuarterStart', True, 94) + next_quarter_end = Column('NextQuarterEnd', True, 95) + next_year_start = Column('NextYearStart', True, 96) + next_year_end = Column('NextYearEnd', True, 97) + weekly_burnup_starting_monday = Column( + 'WeeklyBurnupStartingMonday', True, 98) + weekly_burnup = Column('WeeklyBurnup', True, 99) + monthly_burnup = Column('MonthlyBurnup', True, 100) + quarterly_burnup = Column('QuarterlyBurnup', True, 101) + yearly_burnup = Column('YearlyBurnup', True, 102) + fiscal_month_name = Column('FiscalMonthName', True, 103) + fiscal_month_abbrev = Column('FiscalMonthAbbrev', True, 104) + fiscal_year_name = Column('FiscalYearWeekName', True, 105) + fiscal_year_month_name = Column('FiscalYearMonthName', True, 106) + fiscal_month_year_name = Column('FiscalMonthYearName', True, 107) + fiscal_year_quarter_name = Column('FiscalYearQuarterName', True, 108) + fiscal_year = Column('FiscalYear', True, 109) + fiscal_year_week = Column('FiscalYearWeek', True, 110) + fiscal_year_month = Column('FiscalYearMonth', True, 111) + fiscal_year_quarter = Column('FiscalYearQuarter', True, 112) + fiscal_day_of_month = Column('FiscalDayOfMonth', True, 113) + fiscal_day_of_quarter = Column('FiscalDayOfQuarter', True, 114) + fiscal_day_of_year = Column('FiscalDayOfYear', True, 115) + fiscal_week_of_quarter = Column('FiscalWeekOfQuarter', True, 116) + fiscal_week_of_year = Column('FiscalWeekOfYear', True, 117) + fiscal_month = Column('FiscalMonth', True, 118) + fiscal_month_of_quarter = Column('FiscalMonthOfQuarter', True, 119) + fiscal_quarter = Column('FiscalQuarter', True, 120) + fiscal_days_in_month = Column('FiscalDaysInMonth', True, 121) + fiscal_days_in_quarter = Column('FiscalDaysInQuarter', True, 122) + fiscal_days_in_year = Column('FiscalDaysInYear', True, 123) + fiscal_current_month_flag = Column('FiscalCurrentMonthFlag', True, 124) + fiscal_prior_month_flag = Column('FiscalPriorMonthFlag', True, 125) + fiscal_next_month_flag = Column('FiscalNextMonthFlag', True, 126) + fiscal_current_quarter_flag = Column('FiscalCurrentQuarterFlag', True, 127) + fiscal_prior_quarter_flag = Column('FiscalPriorQuarterFlag', True, 128) + fiscal_next_quarter_flag = Column('FiscalNextQuarterFlag', True, 129) + fiscal_current_year_flag = Column('FiscalCurrentYearFlag', True, 130) + fiscal_prior_year_flag = Column('FiscalPriorYearFlag', True, 131) + fiscal_next_year_flag = Column('FiscalNextYearFlag', True, 132) + fiscal_first_day_of_month_flag = Column( + 'FiscalFirstDayOfMonthFlag', True, 133) + fiscal_last_day_of_month_flag = Column( + 'FiscalLastDayOfMonthFlag', True, 134) + fiscal_first_day_of_quarter_flag = Column, 135( + 'FiscalFirstDayOfQuarterFlag', True, 136) + fiscal_last_day_of_quarter_flag = Column, 137( + 'FiscalLastDayOfQuarterFlag', True, 138) + fiscal_first_day_of_year_flag = Column( + 'FiscalFirstDayOfYearFlag', True, 139) + fiscal_last_day_of_year_flag = Column('FiscalLastDayOfYearFlag', True, 140) + fiscal_fraction_of_month = Column('FiscalFractionOfMonth', True, 141) + fiscal_fraction_of_quarter = Column('FiscalFractionOfQuarter', True, 142) + fiscal_fraction_of_year = Column('FiscalFractionOfYear', True, 143) + fiscal_current_month_start = Column('FiscalCurrentMonthStart', True, 144) + fiscal_current_month_end = Column('FiscalCurrentMonthEnd', True, 145) + fiscal_current_quarter_start = Column( + 'FiscalCurrentQuarterStart', True, 146) + fiscal_current_quarter_end = Column('FiscalCurrentQuarterEnd', True, 147) + fiscal_current_year_start = Column('FiscalCurrentYearStart', True, 148) + fiscal_current_year_end = Column('FiscalCurrentYearEnd', True, 149) + fiscal_prior_month_start = Column('FiscalPriorMonthStart', True, 150) + fiscal_prior_month_end = Column('FiscalPriorMonthEnd', True, 151) + fiscal_prior_quarter_start = Column('FiscalPriorQuarterStart', True, 152) + fiscal_prior_quarter_end = Column('FiscalPriorQuarterEnd', True, 153) + fiscal_prior_year_start = Column('FiscalPriorYearStart', True, 154) + fiscal_prior_year_end = Column('FiscalPriorYearEnd', True, 155) + fiscal_next_month_start = Column('FiscalNextMonthStart', True, 156) + fiscal_next_month_end = Column('FiscalNextMonthEnd', True, 157) + fiscal_next_quarter_start = Column('FiscalNextQuarterStart', True, 158) + fiscal_next_quarter_end = Column('FiscalNextQuarterEnd', True, 159) + fiscal_next_year_start = Column('FiscalNextYearStart', True, 160) + fiscal_next_year_end = Column('FiscalNextYearEnd', True, 161) + fiscal_monthly_burnup = Column('FiscalMonthlyBurnup', True, 162) + fiscal_quarterly_burnup = Column('FiscalQuarterlyBurnup', True, 163) + fiscal_yearly_burnup = Column('FiscalYearlyBurnup', True, 164) + company_holiday_name = Column('CompanyHolidayName', True, 165) + us_public_holiday_name = Column('USPublicHolidayName', True, 166) + + +@dataclass(frozen=True) +class DimFiscalMonthColumns: + month_start_key = Column('MonthStartKey', True, 0) + month_end_key = Column('MonthEndKey', True, 1) + month_start_date = Column('MonthStartDate', True, 2) + month_end_date = Column('MonthEndDate', True, 3) + month_start_iso_date_name = Column('MonthStartISODateName', True, 4) + month_end_iso_date_name = Column('MonthEndISODateName', True, 5) + month_start_american_date_name = Column( + 'MonthStartAmericanDateName', True, 6) + month_end_american_date_name = Column('MonthEndAmericanDateName', True, 7) + month_name = Column('MonthName', True, 8) + month_abbrev = Column('MonthAbbrev', True, 9) + month_start_year_week_name = Column('MonthStartYearWeekName', True, 10) + month_end_year_week_name = Column('MonthEndYearWeekName', True, 11) + year_month_name = Column('YearMonthName', True, 12) + month_year_name = Column('MonthYearName', True, 13) + year_quarter_name = Column('YearQuarterName', True, 14) + year = Column('Year', True, 15) + month_start_year_week = Column('MonthStartYearWeek', True, 16) + month_end_year_week = Column('MonthEndYearWeek', True, 17) + year_month = Column('YearMonth', True, 18) + year_quarter = Column('YearQuarter', True, 19) + month_start_day_of_quarter = Column('MonthStartDayOfQuarter', True, 20) + month_end_day_of_quarter = Column('MonthEndDayOfQuarter', True, 21) + month_start_day_of_year = Column('MonthStartDayOfYear', True, 22) + month_end_day_of_year = Column('MonthEndDayOfYear', True, 23) + month_start_week_of_quarter = Column('MonthStartWeekOfQuarter', True, 24) + month_end_week_of_quarter = Column('MonthEndWeekOfQuarter', True, 25) + month_start_week_of_year = Column('MonthStartWeekOfYear', True, 26) + month_end_week_of_year = Column('MonthEndWeekOfYear', True, 27) + month_of_quarter = Column('MonthOfQuarter', True, 28) + quarter = Column('Quarter', True, 29) + days_in_month = Column('DaysInMonth', True, 30) + days_in_quarter = Column('DaysInQuarter', True, 31) + days_in_year = Column('DaysInYear', True, 32) + current_month_flag = Column('CurrentMonthFlag', True, 33) + prior_month_flag = Column('PriorMonthFlag', True, 34) + next_month_flag = Column('NextMonthFlag', True, 35) + current_quarter_flag = Column('CurrentQuarterFlag', True, 36) + prior_quarter_flag = Column('PriorQuarterFlag', True, 37) + next_quarter_flag = Column('NextQuarterFlag', True, 38) + current_year_flag = Column('CurrentYearFlag', True, 39) + prior_year_flag = Column('PriorYearFlag', True, 40) + next_year_flag = Column('NextYearFlag', True, 41) + first_day_of_month_flag = Column('FirstDayOfMonthFlag', True, 42) + last_day_of_month_flag = Column('LastDayOfMonthFlag', True, 43) + first_day_of_quarter_flag = Column('FirstDayOfQuarterFlag', True, 44) + last_day_of_quarter_flag = Column('LastDayOfQuarterFlag', True, 45) + first_day_of_year_flag = Column('FirstDayOfYearFlag', True, 46) + last_day_of_year_flag = Column('LastDayOfYearFlag', True, 47) + month_start_fraction_of_quarter = Column( + 'MonthStartFractionOfQuarter', True, 48) + month_end_fraction_of_quarter = Column( + 'MonthEndFractionOfQuarter', True, 49) + month_start_fraction_of_year = Column('MonthStartFractionOfYear', True, 50) + month_end_fraction_of_year = Column('MonthEndFractionOfYear', True, 51) + month_start_current_quarter_start = Column( + 'MonthStartCurrentQuarterStart', True, 52) + month_start_current_quarter_end = Column( + 'MonthStartCurrentQuarterEnd', True, 53) + month_start_current_year_start = Column( + 'MonthStartCurrentYearStart', True, 54) + month_start_current_year_end = Column('MonthStartCurrentYearEnd', True, 55) + month_start_prior_month_start = Column( + 'MonthStartPriorMonthStart', True, 56) + month_start_prior_month_end = Column('MonthStartPriorMonthEnd', True, 57) + month_start_prior_quarter_start = Column( + 'MonthStartPriorQuarterStart', True, 58) + month_start_prior_quarter_end = Column( + 'MonthStartPriorQuarterEnd', True, 59) + month_start_prior_year_start = Column('MonthStartPriorYearStart', True, 60) + month_start_prior_year_end = Column('MonthStartPriorYearEnd', True, 61) + month_start_next_month_start = Column('MonthStartNextMonthStart', True, 62) + month_start_next_month_end = Column('MonthStartNextMonthEnd', True, 63) + month_start_next_quarter_start = Column( + 'MonthStartNextQuarterStart', True, 64) + month_start_next_quarter_end = Column('MonthStartNextQuarterEnd', True, 65) + month_start_next_year_start = Column('MonthStartNextYearStart', True, 66) + month_start_next_year_end = Column('MonthStartNextYearEnd', True, 67) + month_start_quarterly_burnup = Column( + 'MonthStartQuarterlyBurnup', True, 68) + month_end_quarterly_burnup = Column('MonthEndQuarterlyBurnup', True, 69) + month_start_yearly_burnup = Column('MonthStartYearlyBurnup', True, 70) + month_end_yearly_burnup = Column('MonthEndYearlyBurnup', True, 71) + company_holidays_in_month = Column('CompanyHolidaysInMonth', True, 72) + us_public_holidays_in_month = Column('USPublicHolidaysInMonth', True, 73) + + +@dataclass(frozen=True) +class DimCalendarMonthColumns: + month_start_key = Column('MonthStartKey', True, 0) + month_end_key = Column('MonthEndKey', True, 1) + month_start_date = Column('MonthStartDate', True, 2) + month_end_date = Column('MonthEndDate', True, 3) + month_start_iso_date_name = Column('MonthStartISODateName', True, 4) + month_end_iso_date_name = Column('MonthEndISODateName', True, 5) + month_start_american_date_name = Column( + 'MonthStartAmericanDateName', True, 6) + month_end_american_date_name = Column('MonthEndAmericanDateName', True, 7) + month_name = Column('MonthName', True, 8) + month_abbrev = Column('MonthAbbrev', True, 9) + month_start_year_week_name = Column('MonthStartYearWeekName', True, 10) + month_end_year_week_name = Column('MonthEndYearWeekName', True, 11) + year_month_name = Column('YearMonthName', True, 12) + month_year_name = Column('MonthYearName', True, 13) + year_quarter_name = Column('YearQuarterName', True, 14) + year = Column('Year', True, 15) + month_start_year_week = Column('MonthStartYearWeek', True, 16) + month_end_year_week = Column('MonthEndYearWeek', True, 17) + year_month = Column('YearMonth', True, 18) + year_quarter = Column('YearQuarter', True, 19) + month_start_day_of_quarter = Column('MonthStartDayOfQuarter', True, 20) + month_end_day_of_quarter = Column('MonthEndDayOfQuarter', True, 21) + month_start_day_of_year = Column('MonthStartDayOfYear', True, 22) + month_end_day_of_year = Column('MonthEndDayOfYear', True, 23) + month_start_week_of_quarter = Column('MonthStartWeekOfQuarter', True, 24) + month_end_week_of_quarter = Column('MonthEndWeekOfQuarter', True, 25) + month_start_week_of_year = Column('MonthStartWeekOfYear', True, 26) + month_end_week_of_year = Column('MonthEndWeekOfYear', True, 27) + month_of_quarter = Column('MonthOfQuarter', True, 28) + quarter = Column('Quarter', True, 29) + days_in_month = Column('DaysInMonth', True, 30) + days_in_quarter = Column('DaysInQuarter', True, 31) + days_in_year = Column('DaysInYear', True, 32) + current_month_flag = Column('CurrentMonthFlag', True, 33) + prior_month_flag = Column('PriorMonthFlag', True, 34) + next_month_flag = Column('NextMonthFlag', True, 35) + current_quarter_flag = Column('CurrentQuarterFlag', True, 36) + prior_quarter_flag = Column('PriorQuarterFlag', True, 37) + next_quarter_flag = Column('NextQuarterFlag', True, 38) + current_year_flag = Column('CurrentYearFlag', True, 39) + prior_year_flag = Column('PriorYearFlag', True, 40) + next_year_flag = Column('NextYearFlag', True, 41) + first_day_of_month_flag = Column('FirstDayOfMonthFlag', True, 42) + last_day_of_month_flag = Column('LastDayOfMonthFlag', True, 43) + first_day_of_quarter_flag = Column('FirstDayOfQuarterFlag', True, 44) + last_day_of_quarter_flag = Column('LastDayOfQuarterFlag', True, 45) + first_day_of_year_flag = Column('FirstDayOfYearFlag', True, 46) + last_day_of_year_flag = Column('LastDayOfYearFlag', True, 47) + month_start_fraction_of_quarter = Column( + 'MonthStartFractionOfQuarter', True, 48) + month_end_fraction_of_quarter = Column( + 'MonthEndFractionOfQuarter', True, 49) + month_start_fraction_of_year = Column('MonthStartFractionOfYear', True, 50) + month_end_fraction_of_year = Column('MonthEndFractionOfYear', True, 51) + month_start_current_quarter_start = Column( + 'MonthStartCurrentQuarterStart', True, 52) + month_start_current_quarter_end = Column( + 'MonthStartCurrentQuarterEnd', True, 53) + month_start_current_year_start = Column( + 'MonthStartCurrentYearStart', True, 54) + month_start_current_year_end = Column('MonthStartCurrentYearEnd', True, 55) + month_start_prior_month_start = Column( + 'MonthStartPriorMonthStart', True, 56) + month_start_prior_month_end = Column('MonthStartPriorMonthEnd', True, 57) + month_start_prior_quarter_start = Column( + 'MonthStartPriorQuarterStart', True, 58) + month_start_prior_quarter_end = Column( + 'MonthStartPriorQuarterEnd', True, 59) + month_start_prior_year_start = Column('MonthStartPriorYearStart', True, 60) + month_start_prior_year_end = Column('MonthStartPriorYearEnd', True, 61) + month_start_next_month_start = Column('MonthStartNextMonthStart', True, 62) + month_start_next_month_end = Column('MonthStartNextMonthEnd', True, 63) + month_start_next_quarter_start = Column( + 'MonthStartNextQuarterStart', True, 64) + month_start_next_quarter_end = Column('MonthStartNextQuarterEnd', True, 65) + month_start_next_year_start = Column('MonthStartNextYearStart', True, 66) + month_start_next_year_end = Column('MonthStartNextYearEnd', True, 67) + month_start_quarterly_burnup = Column( + 'MonthStartQuarterlyBurnup', True, 68) + month_end_quarterly_burnup = Column('MonthEndQuarterlyBurnup', True, 69) + month_start_yearly_burnup = Column('MonthStartYearlyBurnup', True, 70) + month_end_yearly_burnup = Column('MonthEndYearlyBurnup', True, 71) + company_holidays_in_month = Column('CompanyHolidaysInMonth', True, 72) + us_public_holidays_in_month = Column('USPublicHolidaysInMonth', True, 73) diff --git a/generate/script_generatior.py b/generate/script_generatior.py index 24846d2..1423ebf 100644 --- a/generate/script_generatior.py +++ b/generate/script_generatior.py @@ -1,5 +1,7 @@ -from dataclasses import dataclass +from dataclasses import asdict, dataclass from datetime import datetime +from typing import Callable +from columns import Column, DimCalendarMonthColumns, DimDateColumns, DimFiscalMonthColumns from holidays import default_holidays, Holiday from abc import ABC, abstractmethod from pathlib import Path @@ -38,19 +40,86 @@ def __post_init__(self): if self.generate_holidays: assert all((holiday.holiday_type in self.holiday_types for holiday in self.holidays) ), 'found a holiday in holidays whose holiday_type does not exist in holiday_types' - assert all(holiday_type in self.holiday_types for holiday_type in self.holiday_types_for_business_days), 'found a holiday type in holiday_types_for_business_days that is not present in holiday_types' + assert all(holiday_type in self.holiday_types for holiday_type in self.holiday_types_for_business_days), 'found a holiday type in holiday_types_for_business_days that is not present in holiday_types.' @dataclass(frozen=True) class TableNameConfig: dim_date_schema_name: str = "dbo" dim_date_table_name: str = "DimDate" + dim_calendar_month_schema_name: str = 'dbo' + dim_calendar_month_table_name: str = 'DimCalendarMonth' + dim_fiscal_month_schema_name: str = 'dbo' + dim_fiscal_month_table_name: str = 'DimFiscalMonth' holiday_types_schema_name: str = "integration" holiday_types_table_name: str = "manual_HolidayTypes" holidays_schema_name: str = "integration" holidays_table_name: str = "manual_Holidays" +@dataclass(frozen=True) +class DimDateColumnConfig: + columns: DimDateColumns = DimDateColumns() + column_name_factory: Callable[[str], str] = None + + def __post_init__(self): + col_dict = asdict(self.columns) + sort_keys = [v['sort_index'] + for v in col_dict.values()] + distinct_sort_keys = set(sort_keys) + assert len(sort_keys) == len( + distinct_sort_keys), 'there was a duplicate sort key in the column definitions for DimDateColumnConfig.' + + if self.column_name_factory is not None: + new_cols: dict[str, Column] = {} + for k, v in col_dict.values(): + new_cols[k] = Column(self.column_name_factory( + v['name']), v['include'], v['sort_index']) + self.columns = DimCalendarMonthColumns(**new_cols) + + +@dataclass(frozen=True) +class DimFiscalMonthColumnConfig: + columns: DimFiscalMonthColumns = DimFiscalMonthColumns() + column_name_factory: Callable[[str], str] = None + + def __post_init__(self): + col_dict = asdict(self.columns) + sort_keys = [v['sort_index'] + for v in col_dict.values()] + distinct_sort_keys = set(sort_keys) + assert len(sort_keys) == len( + distinct_sort_keys), 'there was a duplicate sort key in the column definitions for DimFiscalMonthColumnConfig.' + + if self.column_name_factory is not None: + new_cols: dict[str, Column] = {} + for k, v in col_dict.values(): + new_cols[k] = Column(self.column_name_factory( + v['name']), v['include'], v['sort_index']) + self.columns = DimCalendarMonthColumns(**new_cols) + + +@dataclass(frozen=True) +class DimCalendarMonthColumnConfig: + columns: DimCalendarMonthColumns = DimCalendarMonthColumns() + column_name_factory: Callable[[str], str] = None + + def __post_init__(self): + col_dict = asdict(self.columns) + sort_keys = [v['sort_index'] + for v in col_dict.values()] + distinct_sort_keys = set(sort_keys) + assert len(sort_keys) == len( + distinct_sort_keys), 'there was a duplicate sort key in the column definitions for DimCalendarMonthColumnConfig.' + + if self.column_name_factory is not None: + new_cols: dict[str, Column] = {} + for k, v in col_dict.values(): + new_cols[k] = Column(self.column_name_factory( + v['name']), v['include'], v['sort_index']) + self.columns = DimCalendarMonthColumns(**new_cols) + + @dataclass class ScriptGeneratorConfig: outdir_base: Path = Path('../output') From 7e2a266d5900ee5ed244a142c4a6504c574949b6 Mon Sep 17 00:00:00 2001 From: "S. Elliott Johnson" Date: Sat, 29 Jan 2022 03:22:38 -0700 Subject: [PATCH 05/48] feat: Added better holiday config --- generate/holidays.py | 906 ++++++++++++++-------------------- generate/script_generatior.py | 61 ++- 2 files changed, 392 insertions(+), 575 deletions(-) diff --git a/generate/holidays.py b/generate/holidays.py index 82bcf61..b344fa5 100644 --- a/generate/holidays.py +++ b/generate/holidays.py @@ -2,557 +2,365 @@ from datetime import datetime +@dataclass(frozen=True) +class HolidayType: + name: str + generated_column_prefix: str + included_in_business_day_calc: bool + + @dataclass(frozen=True) class Holiday: - holiday_type: str - holiday_date: datetime.date holiday_name: str + holiday_date: datetime.date + + +@dataclass(frozen=True) +class HolidayCalendar: + holiday_type: HolidayType + holidays: list[Holiday] + + +default_company_holidays: HolidayCalendar = HolidayCalendar( + HolidayType('Company Holiday', 'Company', True), + [ + Holiday('New Year''s Day', datetime.fromisoformat('2012-01-02')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2012-01-16')), + Holiday('Memorial Day', datetime.fromisoformat('2012-05-28')), + Holiday('Independence Day', datetime.fromisoformat('2012-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2012-09-03')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2012-11-22')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2012-11-23')), + Holiday('Christmas Eve', datetime.fromisoformat('2012-12-24')), + Holiday('Christmas Day', datetime.fromisoformat('2012-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2013-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2013-01-21')), + Holiday('Memorial Day', datetime.fromisoformat('2013-05-27')), + Holiday('Independence Day', datetime.fromisoformat('2013-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2013-09-02')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2013-11-28')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2013-11-29')), + Holiday('Christmas Eve', datetime.fromisoformat('2013-12-24')), + Holiday('Christmas Day', datetime.fromisoformat('2013-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2014-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2014-01-20')), + Holiday('Memorial Day', datetime.fromisoformat('2014-05-26')), + Holiday('Independence Day', datetime.fromisoformat('2014-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2014-09-01')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2014-11-28')), + Holiday('Christmas Eve', datetime.fromisoformat('2014-12-24')), + Holiday('Christmas Day', datetime.fromisoformat('2014-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2015-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2015-01-19')), + Holiday('Memorial Day', datetime.fromisoformat('2015-05-25')), + Holiday('Independence Day', datetime.fromisoformat('2015-07-03')), + Holiday('Labor Day', datetime.fromisoformat('2015-09-07')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2015-11-26')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2015-11-27')), + Holiday('Christmas Eve', datetime.fromisoformat('2015-12-24')), + Holiday('Christmas Day', datetime.fromisoformat('2015-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2016-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2016-01-18')), + Holiday('Memorial Day', datetime.fromisoformat('2016-05-30')), + Holiday('Independence Day', datetime.fromisoformat('2016-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2016-09-05')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2016-11-24')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2016-11-25')), + Holiday('Christmas Eve', datetime.fromisoformat('2016-12-23')), + Holiday('Christmas Day', datetime.fromisoformat('2016-12-26')), + + Holiday('New Year''s Day', datetime.fromisoformat('2017-01-02')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2017-01-16')), + Holiday('Memorial Day', datetime.fromisoformat('2017-05-29')), + Holiday('Independence Day', datetime.fromisoformat('2017-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2017-09-04')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2017-11-23')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2017-11-24')), + Holiday('Christmas Eve', datetime.fromisoformat('2017-12-25')), + Holiday('Christmas Day', datetime.fromisoformat('2017-12-26')), + + Holiday('New Year''s Day', datetime.fromisoformat('2018-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2018-01-15')), + Holiday('Memorial Day', datetime.fromisoformat('2018-05-28')), + Holiday('Independence Day', datetime.fromisoformat('2018-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2018-09-03')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2018-11-22')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2018-11-23')), + Holiday('Christmas Eve', datetime.fromisoformat('2018-12-24')), + Holiday('Christmas Day', datetime.fromisoformat('2018-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2019-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2019-01-21')), + Holiday('Memorial Day', datetime.fromisoformat('2019-05-27')), + Holiday('Independence Day', datetime.fromisoformat('2019-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2019-09-02')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2019-11-28')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2019-11-29')), + Holiday('Christmas Eve', datetime.fromisoformat('2019-12-24')), + Holiday('Christmas Day', datetime.fromisoformat('2019-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2020-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2020-01-20')), + Holiday('Memorial Day', datetime.fromisoformat('2020-05-25')), + Holiday('Independence Day', datetime.fromisoformat('2020-07-03')), + Holiday('Labor Day', datetime.fromisoformat('2020-09-07')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2020-11-26')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2020-11-27')), + Holiday('Christmas Eve', datetime.fromisoformat('2020-12-24')), + Holiday('Christmas Day', datetime.fromisoformat('2020-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2021-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2021-01-18')), + Holiday('Memorial Day', datetime.fromisoformat('2021-05-31')), + Holiday('Independence Day', datetime.fromisoformat('2021-07-05')), + Holiday('Labor Day', datetime.fromisoformat('2021-09-06')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2021-11-26')), + Holiday('Christmas Eve', datetime.fromisoformat('2021-12-23')), + Holiday('Christmas Day', datetime.fromisoformat('2021-12-24')), + + Holiday('New Year''s Day', datetime.fromisoformat('2021-12-31')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2022-01-17')), + Holiday('Memorial Day', datetime.fromisoformat('2022-05-30')), + Holiday('Independence Day', datetime.fromisoformat('2022-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2022-09-05')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2022-11-24')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2022-11-25')), + Holiday('Christmas Eve', datetime.fromisoformat('2022-12-23')), + Holiday('Christmas Day', datetime.fromisoformat('2022-12-26')), + + Holiday('New Year''s Day', datetime.fromisoformat('2023-01-02')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2023-01-16')), + Holiday('Memorial Day', datetime.fromisoformat('2023-05-29')), + Holiday('Independence Day', datetime.fromisoformat('2023-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2023-09-04')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2023-11-23')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2023-11-24')), + Holiday('Christmas Eve', datetime.fromisoformat('2023-12-25')), + Holiday('Christmas Day', datetime.fromisoformat('2023-12-26')), + + Holiday('New Year''s Day', datetime.fromisoformat('2024-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2024-01-15')), + Holiday('Memorial Day', datetime.fromisoformat('2024-05-27')), + Holiday('Independence Day', datetime.fromisoformat('2024-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2024-09-02')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2024-11-28')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2024-11-29')), + Holiday('Christmas Eve', datetime.fromisoformat('2024-12-24')), + Holiday('Christmas Day', datetime.fromisoformat('2024-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2025-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2025-01-20')), + Holiday('Memorial Day', datetime.fromisoformat('2025-05-26')), + Holiday('Independence Day', datetime.fromisoformat('2025-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2025-09-01')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2025-11-27')), + Holiday('Friday After Thanksgiving', + datetime.fromisoformat('2025-11-28')), + Holiday('Christmas Eve', datetime.fromisoformat('2025-12-24')), + Holiday('Christmas Day', datetime.fromisoformat('2025-12-25')), + ] +) + +default_us_public_holidays: HolidayCalendar = HolidayCalendar( + HolidayType('US Public Holiday', 'USPublic', False), + [ + Holiday('New Year''s Day', datetime.fromisoformat('2012-01-02')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2012-01-16')), + Holiday('Presidents'' Day', datetime.fromisoformat('2012-02-20')), + Holiday('Memorial Day', datetime.fromisoformat('2012-05-28')), + Holiday('Independence Day', datetime.fromisoformat('2012-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2012-09-03')), + Holiday('Columbus Day', datetime.fromisoformat('2012-10-08')), + Holiday('Veterans Day', datetime.fromisoformat('2012-11-12')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2012-11-22')), + Holiday('Christmas Day', datetime.fromisoformat('2012-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2013-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2013-01-21')), + Holiday('Presidents'' Day', datetime.fromisoformat('2013-02-18')), + Holiday('Memorial Day', datetime.fromisoformat('2013-05-27')), + Holiday('Independence Day', datetime.fromisoformat('2013-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2013-09-02')), + Holiday('Columbus Day', datetime.fromisoformat('2013-10-14')), + Holiday('Veterans Day', datetime.fromisoformat('2013-11-11')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2013-11-28')), + Holiday('Christmas Day', datetime.fromisoformat('2013-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2014-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2014-01-20')), + Holiday('Presidents'' Day', datetime.fromisoformat('2014-02-17')), + Holiday('Memorial Day', datetime.fromisoformat('2014-05-26')), + Holiday('Independence Day', datetime.fromisoformat('2014-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2014-09-01')), + Holiday('Columbus Day', datetime.fromisoformat('2014-10-13')), + Holiday('Veterans Day', datetime.fromisoformat('2014-11-11')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2014-11-27')), + Holiday('Christmas Day', datetime.fromisoformat('2014-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2015-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2015-01-19')), + Holiday('Presidents'' Day', datetime.fromisoformat('2015-02-16')), + Holiday('Memorial Day', datetime.fromisoformat('2015-05-25')), + Holiday('Independence Day', datetime.fromisoformat('2015-07-03')), + Holiday('Labor Day', datetime.fromisoformat('2015-09-07')), + Holiday('Columbus Day', datetime.fromisoformat('2015-10-12')), + Holiday('Veterans Day', datetime.fromisoformat('2015-11-11')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2015-11-26')), + Holiday('Christmas Day', datetime.fromisoformat('2015-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2016-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2016-01-18')), + Holiday('Presidents'' Day', datetime.fromisoformat('2016-02-15')), + Holiday('Memorial Day', datetime.fromisoformat('2016-05-30')), + Holiday('Independence Day', datetime.fromisoformat('2016-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2016-09-05')), + Holiday('Columbus Day', datetime.fromisoformat('2016-10-10')), + Holiday('Veterans Day', datetime.fromisoformat('2016-11-11')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2016-11-24')), + Holiday('Christmas Day', datetime.fromisoformat('2016-12-26')), + + Holiday('New Year''s Day', datetime.fromisoformat('2017-01-02')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2017-01-16')), + Holiday('Presidents'' Day', datetime.fromisoformat('2017-02-20')), + Holiday('Memorial Day', datetime.fromisoformat('2017-05-29')), + Holiday('Independence Day', datetime.fromisoformat('2017-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2017-09-04')), + Holiday('Columbus Day', datetime.fromisoformat('2017-10-09')), + Holiday('Veterans Day', datetime.fromisoformat('2017-11-10')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2017-11-23')), + Holiday('Christmas Day', datetime.fromisoformat('2017-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2018-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2018-01-15')), + Holiday('Presidents'' Day', datetime.fromisoformat('2018-02-19')), + Holiday('Memorial Day', datetime.fromisoformat('2018-05-28')), + Holiday('Independence Day', datetime.fromisoformat('2018-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2018-09-03')), + Holiday('Columbus Day', datetime.fromisoformat('2018-10-08')), + Holiday('Veterans Day', datetime.fromisoformat('2018-11-12')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2018-11-22')), + Holiday('Christmas Day', datetime.fromisoformat('2018-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2019-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2019-01-21')), + Holiday('Presidents'' Day', datetime.fromisoformat('2019-02-18')), + Holiday('Memorial Day', datetime.fromisoformat('2019-05-27')), + Holiday('Independence Day', datetime.fromisoformat('2019-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2019-09-02')), + Holiday('Columbus Day', datetime.fromisoformat('2019-10-14')), + Holiday('Veterans Day', datetime.fromisoformat('2019-11-11')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2019-11-28')), + Holiday('Christmas Day', datetime.fromisoformat('2019-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2020-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2020-01-20')), + Holiday('Presidents'' Day', datetime.fromisoformat('2020-02-17')), + Holiday('Memorial Day', datetime.fromisoformat('2020-05-25')), + Holiday('Independence Day', datetime.fromisoformat('2020-07-03')), + Holiday('Labor Day', datetime.fromisoformat('2020-09-07')), + Holiday('Columbus Day', datetime.fromisoformat('2020-10-12')), + Holiday('Veterans Day', datetime.fromisoformat('2020-11-11')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2020-11-26')), + Holiday('Christmas Day', datetime.fromisoformat('2020-12-25')), + + Holiday('New Year''s Day', datetime.fromisoformat('2021-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2021-01-18')), + Holiday('Presidents'' Day', datetime.fromisoformat('2021-02-15')), + Holiday('Memorial Day', datetime.fromisoformat('2021-05-31')), + Holiday('Independence Day', datetime.fromisoformat('2021-07-05')), + Holiday('Labor Day', datetime.fromisoformat('2021-09-06')), + Holiday('Columbus Day', datetime.fromisoformat('2021-10-11')), + Holiday('Veterans Day', datetime.fromisoformat('2021-11-11')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2021-11-25')), + Holiday('Christmas Day', datetime.fromisoformat('2021-12-24')), + + Holiday('New Year''s Day', datetime.fromisoformat('2021-12-31')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2022-01-17')), + Holiday('Presidents'' Day', datetime.fromisoformat('2022-02-21')), + Holiday('Memorial Day', datetime.fromisoformat('2022-05-30')), + Holiday('Independence Day', datetime.fromisoformat('2022-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2022-09-05')), + Holiday('Columbus Day', datetime.fromisoformat('2022-10-10')), + Holiday('Veterans Day', datetime.fromisoformat('2022-11-11')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2022-11-24')), + Holiday('Christmas Day', datetime.fromisoformat('2022-12-26')), + + Holiday('New Year''s Day', datetime.fromisoformat('2023-01-02')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2023-01-16')), + Holiday('Presidents'' Day', datetime.fromisoformat('2023-02-20')), + Holiday('Memorial Day', datetime.fromisoformat('2023-05-29')), + Holiday('Independence Day', datetime.fromisoformat('2023-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2023-09-04')), + Holiday('Columbus Day', datetime.fromisoformat('2023-10-09')), + Holiday('Veterans Day', datetime.fromisoformat('2023-11-10')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2023-11-23')), + Holiday('Christmas Day', datetime.fromisoformat('2023-12-25')), + Holiday('New Year''s Day', datetime.fromisoformat('2024-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2024-01-15')), + Holiday('Presidents'' Day', datetime.fromisoformat('2024-02-19')), + Holiday('Memorial Day', datetime.fromisoformat('2024-05-27')), + Holiday('Independence Day', datetime.fromisoformat('2024-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2024-09-02')), + Holiday('Columbus Day', datetime.fromisoformat('2024-10-14')), + Holiday('Veterans Day', datetime.fromisoformat('2024-11-11')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2024-11-28')), + Holiday('Christmas Day', datetime.fromisoformat('2024-12-25')), -default_holidays: list[Holiday] = [ - Holiday("New Year's Day", datetime.fromisoformat( - '2012-01-02'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2012-01-02'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2012-01-16'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2012-01-16'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2012-02-20'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2012-05-28'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2012-05-28'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2012-07-04'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2012-07-04'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2012-09-03'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2012-09-03'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2012-10-08'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2012-11-12'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2012-11-22'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2012-11-22'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2012-11-23'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2012-12-24'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2012-12-25'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2012-12-25'), 'US Public Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2013-01-01'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2013-01-01'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2013-01-21'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2013-01-21'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2013-02-18'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2013-05-27'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2013-05-27'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2013-07-04'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2013-07-04'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2013-09-02'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2013-09-02'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2013-10-14'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2013-11-11'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2013-11-28'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2013-11-28'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2013-11-29'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2013-12-24'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2013-12-25'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2013-12-25'), 'US Public Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2014-01-01'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2014-01-01'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2014-01-20'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2014-01-20'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2014-02-17'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2014-05-26'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2014-05-26'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2014-07-04'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2014-07-04'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2014-09-01'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2014-09-01'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2014-10-13'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2014-11-11'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2014-11-27'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2014-11-28'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2014-12-24'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2014-12-25'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2014-12-25'), 'US Public Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2015-01-01'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2015-01-01'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2015-01-19'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2015-01-19'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2015-02-16'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2015-05-25'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2015-05-25'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2015-07-03'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2015-07-03'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2015-09-07'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2015-09-07'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2015-10-12'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2015-11-11'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2015-11-26'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2015-11-26'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2015-11-27'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2015-12-24'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2015-12-25'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2015-12-25'), 'US Public Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2016-01-01'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2016-01-01'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2016-01-18'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2016-01-18'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2016-02-15'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2016-05-30'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2016-05-30'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2016-07-04'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2016-07-04'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2016-09-05'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2016-09-05'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2016-10-10'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2016-11-11'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2016-11-24'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2016-11-24'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2016-11-25'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2016-12-23'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2016-12-26'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2016-12-26'), 'US Public Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2017-01-02'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2017-01-02'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2017-01-16'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2017-01-16'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2017-02-20'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2017-05-29'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2017-05-29'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2017-07-04'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2017-07-04'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2017-09-04'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2017-09-04'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2017-10-09'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2017-11-10'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2017-11-23'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2017-11-23'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2017-11-24'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2017-12-25'), 'Company Holiday'), - # This Christmas is weird. For my company, - # Christmas Eve pushes Christmas to the 26th, but - # for the government, Christmas still falls on the - # 25th. - Holiday('Christmas Day', datetime.fromisoformat( - '2017-12-25'), 'US Public Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2017-12-26'), 'Company Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2018-01-01'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2018-01-01'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2018-01-15'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2018-01-15'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2018-02-19'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2018-05-28'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2018-05-28'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2018-07-04'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2018-07-04'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2018-09-03'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2018-09-03'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2018-10-08'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2018-11-12'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2018-11-22'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2018-11-22'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2018-11-23'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2018-12-24'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2018-12-25'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2018-12-25'), 'US Public Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2019-01-01'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2019-01-01'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2019-01-21'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2019-01-21'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2019-02-18'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2019-05-27'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2019-05-27'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2019-07-04'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2019-07-04'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2019-09-02'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2019-09-02'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2019-10-14'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2019-11-11'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2019-11-28'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2019-11-28'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2019-11-29'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2019-12-24'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2019-12-25'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2019-12-25'), 'US Public Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2020-01-01'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2020-01-01'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2020-01-20'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2020-01-20'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2020-02-17'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2020-05-25'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2020-05-25'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2020-07-03'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2020-07-03'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2020-09-07'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2020-09-07'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2020-10-12'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2020-11-11'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2020-11-26'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2020-11-26'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2020-11-27'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2020-12-24'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2020-12-25'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2020-12-25'), 'US Public Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2021-01-01'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2021-01-01'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2021-01-18'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2021-01-18'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2021-02-15'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2021-05-31'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2021-05-31'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2021-07-05'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2021-07-05'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2021-09-06'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2021-09-06'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2021-10-11'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2021-11-11'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2021-11-25'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2021-11-26'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2021-12-23'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2021-12-24'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2021-12-24'), 'US Public Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2021-12-31'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2021-12-31'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2022-01-17'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2022-01-17'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2022-02-21'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2022-05-30'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2022-05-30'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2022-07-04'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2022-07-04'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2022-09-05'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2022-09-05'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2022-10-10'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2022-11-11'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2022-11-24'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2022-11-24'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2022-11-25'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2022-12-23'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2022-12-26'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2022-12-26'), 'US Public Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2023-01-02'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2023-01-02'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2023-01-16'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2023-01-16'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2023-02-20'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2023-05-29'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2023-05-29'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2023-07-04'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2023-07-04'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2023-09-04'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2023-09-04'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2023-10-09'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2023-11-10'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2023-11-23'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2023-11-23'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2023-11-24'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2023-12-25'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2023-12-25'), 'US Public Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2023-12-26'), 'Company Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2024-01-01'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2024-01-01'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2024-01-15'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2024-01-15'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2024-02-19'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2024-05-27'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2024-05-27'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2024-07-04'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2024-07-04'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2024-09-02'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2024-09-02'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2024-10-14'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2024-11-11'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2024-11-28'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2024-11-28'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2024-11-29'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2024-12-24'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2024-12-25'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2024-12-25'), 'US Public Holiday'), - - Holiday("New Year's Day", datetime.fromisoformat( - '2025-01-01'), 'Company Holiday'), - Holiday("New Year's Day", datetime.fromisoformat( - '2025-01-01'), 'US Public Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2025-01-20'), 'Company Holiday'), - Holiday('Martin Luther King, Jr. Day', datetime.fromisoformat( - '2025-01-20'), 'US Public Holiday'), - Holiday("Presidents' Day", datetime.fromisoformat( - '2025-02-17'), 'US Public Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2025-05-26'), 'Company Holiday'), - Holiday('Memorial Day', datetime.fromisoformat( - '2025-05-26'), 'US Public Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2025-07-04'), 'Company Holiday'), - Holiday('Independence Day', datetime.fromisoformat( - '2025-07-04'), 'US Public Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2025-09-01'), 'Company Holiday'), - Holiday('Labor Day', datetime.fromisoformat( - '2025-09-01'), 'US Public Holiday'), - Holiday('Columbus Day', datetime.fromisoformat( - '2025-10-13'), 'US Public Holiday'), - Holiday('Veterans Day', datetime.fromisoformat( - '2025-11-11'), 'US Public Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2025-11-27'), 'Company Holiday'), - Holiday('Thanksgiving Day', datetime.fromisoformat( - '2025-11-27'), 'US Public Holiday'), - Holiday('Friday After Thanksgiving', datetime.fromisoformat( - '2025-11-28'), 'Company Holiday'), - Holiday('Christmas Eve', datetime.fromisoformat( - '2025-12-24'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2025-12-25'), 'Company Holiday'), - Holiday('Christmas Day', datetime.fromisoformat( - '2025-12-25'), 'US Public Holiday'), -] + Holiday('New Year''s Day', datetime.fromisoformat('2025-01-01')), + Holiday('Martin Luther King, Jr. Day', + datetime.fromisoformat('2025-01-20')), + Holiday('Presidents'' Day', datetime.fromisoformat('2025-02-17')), + Holiday('Memorial Day', datetime.fromisoformat('2025-05-26')), + Holiday('Independence Day', datetime.fromisoformat('2025-07-04')), + Holiday('Labor Day', datetime.fromisoformat('2025-09-01')), + Holiday('Columbus Day', datetime.fromisoformat('2025-10-13')), + Holiday('Veterans Day', datetime.fromisoformat('2025-11-11')), + Holiday('Thanksgiving Day', datetime.fromisoformat('2025-11-27')), + Holiday('Christmas Day', datetime.fromisoformat('2025-12-25')), + ] +) diff --git a/generate/script_generatior.py b/generate/script_generatior.py index 1423ebf..e959f45 100644 --- a/generate/script_generatior.py +++ b/generate/script_generatior.py @@ -1,8 +1,8 @@ -from dataclasses import asdict, dataclass +from dataclasses import asdict, dataclass, field from datetime import datetime from typing import Callable from columns import Column, DimCalendarMonthColumns, DimDateColumns, DimFiscalMonthColumns -from holidays import default_holidays, Holiday +from holidays import HolidayCalendar, HolidayType, default_company_holidays, default_us_public_holidays from abc import ABC, abstractmethod from pathlib import Path @@ -32,33 +32,32 @@ def __post_init__(self): @dataclass(frozen=True) class HolidayConfig: generate_holidays: bool = True - holiday_types: tuple[str] = ("Company Holiday", "US Public Holiday") - holiday_types_for_business_days: tuple[str] = ("Company Holiday") - holidays: list[Holiday] = default_holidays + holiday_types_schema_name: str = 'integration' + holiday_types_table_name: str = 'manual_HolidayTypes' + holidays_schema_name: str = 'integration' + holidays_table_name: str = 'manual_Holidays' + holiday_calendars: list[HolidayCalendar] = [ + default_company_holidays, default_us_public_holidays] + holiday_types: list[HolidayType] = field(init=False) def __post_init__(self): if self.generate_holidays: - assert all((holiday.holiday_type in self.holiday_types for holiday in self.holidays) - ), 'found a holiday in holidays whose holiday_type does not exist in holiday_types' - assert all(holiday_type in self.holiday_types for holiday_type in self.holiday_types_for_business_days), 'found a holiday type in holiday_types_for_business_days that is not present in holiday_types.' + holiday_types = [ + cal.holiday_type for cal in self.holiday_calendars] + holiday_type_names = [t.name for t in holiday_types] + holiday_type_prefixes = [ + t.generated_column_prefix for t in holiday_types] + assert len(holiday_type_names) == len(set(holiday_type_names) + ), 'detected a duplicate HolidayType name in HolidayConfig.' + assert len(holiday_type_prefixes) == len(set(holiday_type_prefixes) + ), 'detected a duplicate HolidayTypePrefix in HolidayConfig.' + self.holiday_types = holiday_types @dataclass(frozen=True) -class TableNameConfig: - dim_date_schema_name: str = "dbo" - dim_date_table_name: str = "DimDate" - dim_calendar_month_schema_name: str = 'dbo' - dim_calendar_month_table_name: str = 'DimCalendarMonth' - dim_fiscal_month_schema_name: str = 'dbo' - dim_fiscal_month_table_name: str = 'DimFiscalMonth' - holiday_types_schema_name: str = "integration" - holiday_types_table_name: str = "manual_HolidayTypes" - holidays_schema_name: str = "integration" - holidays_table_name: str = "manual_Holidays" - - -@dataclass(frozen=True) -class DimDateColumnConfig: +class DimDateConfig: + table_schema: str = 'dbo' + table_name: str = 'DimDate' columns: DimDateColumns = DimDateColumns() column_name_factory: Callable[[str], str] = None @@ -79,7 +78,9 @@ def __post_init__(self): @dataclass(frozen=True) -class DimFiscalMonthColumnConfig: +class DimFiscalMonthConfig: + table_schema: str = 'dbo' + table_name: str = 'DimFiscalMonth' columns: DimFiscalMonthColumns = DimFiscalMonthColumns() column_name_factory: Callable[[str], str] = None @@ -100,7 +101,9 @@ def __post_init__(self): @dataclass(frozen=True) -class DimCalendarMonthColumnConfig: +class DimCalendarMonthConfig: + table_schema: str = 'dbo' + table_name: str = 'DimCalendarMonth' columns: DimCalendarMonthColumns = DimCalendarMonthColumns() column_name_factory: Callable[[str], str] = None @@ -126,8 +129,10 @@ class ScriptGeneratorConfig: date_range: DateRange = DateRange() fiscal_config: FiscalConfig = FiscalConfig() time_zone: str = "Mountain Standard Time" - table_name_config: TableNameConfig = TableNameConfig() holiday_config: HolidayConfig = HolidayConfig() + dim_date_config: DimDateConfig = DimDateConfig() + dim_fiscal_month_config: DimFiscalMonthConfig = DimFiscalMonthConfig() + dim_calendar_month_config: DimCalendarMonthConfig = DimCalendarMonthConfig() class ScriptGenerator(ABC): @@ -135,6 +140,10 @@ class ScriptGenerator(ABC): def __init__(self, config: ScriptGeneratorConfig = ScriptGeneratorConfig()): pass + @abstractmethod + def add_generator_specific_config(self, config: object) -> None: + pass + @abstractmethod def generate_scripts(self) -> None: pass From 3190f4dec69fbf2db705b05e6e2acf013672a65d Mon Sep 17 00:00:00 2001 From: "S. Elliott Johnson" Date: Sun, 30 Jan 2022 21:58:26 -0700 Subject: [PATCH 06/48] chore: Reorganized now that I've got a clearer structure in mind --- .gitignore | 2 +- generate/columns.py | 362 -- generate/holidays.py | 366 -- generate/script_generatior.py | 149 - generate/script_generator_factory.py | 17 - .../.venv/bin/Activate.ps1 | 241 + src/awesome-date-dimension/.venv/bin/activate | 66 + .../.venv/bin/activate.csh | 25 + .../.venv/bin/activate.fish | 64 + .../.venv/bin/easy_install | 8 + .../.venv/bin/easy_install-3.9 | 8 + src/awesome-date-dimension/.venv/bin/pip | 8 + src/awesome-date-dimension/.venv/bin/pip3 | 8 + src/awesome-date-dimension/.venv/bin/pip3.9 | 8 + src/awesome-date-dimension/.venv/bin/python | 1 + src/awesome-date-dimension/.venv/bin/python3 | 1 + .../.venv/bin/python3.9 | 1 + .../__pycache__/easy_install.cpython-39.pyc | Bin 0 -> 345 bytes .../python3.9/site-packages/easy_install.py | 5 + .../pip-20.3.4.dist-info/INSTALLER | 1 + .../pip-20.3.4.dist-info/LICENSE.txt | 20 + .../pip-20.3.4.dist-info/METADATA | 94 + .../site-packages/pip-20.3.4.dist-info/RECORD | 284 + .../pip-20.3.4.dist-info/REQUESTED | 0 .../site-packages/pip-20.3.4.dist-info/WHEEL | 6 + .../pip-20.3.4.dist-info/entry_points.txt | 5 + .../pip-20.3.4.dist-info/top_level.txt | 1 + .../python3.9/site-packages/pip/__init__.py | 18 + .../python3.9/site-packages/pip/__main__.py | 26 + .../pip/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 693 bytes .../pip/__pycache__/__main__.cpython-39.pyc | Bin 0 -> 537 bytes .../site-packages/pip/_internal/__init__.py | 17 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 742 bytes .../__pycache__/build_env.cpython-39.pyc | Bin 0 -> 7577 bytes .../__pycache__/cache.cpython-39.pyc | Bin 0 -> 9134 bytes .../__pycache__/configuration.cpython-39.pyc | Bin 0 -> 10877 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 14966 bytes .../__pycache__/locations.cpython-39.pyc | Bin 0 -> 4600 bytes .../_internal/__pycache__/main.cpython-39.pyc | Bin 0 -> 679 bytes .../__pycache__/pyproject.cpython-39.pyc | Bin 0 -> 3782 bytes .../self_outdated_check.cpython-39.pyc | Bin 0 -> 4613 bytes .../__pycache__/wheel_builder.cpython-39.pyc | Bin 0 -> 8655 bytes .../site-packages/pip/_internal/build_env.py | 242 + .../site-packages/pip/_internal/cache.py | 346 + .../pip/_internal/cli/__init__.py | 4 + .../cli/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 300 bytes .../__pycache__/autocompletion.cpython-39.pyc | Bin 0 -> 4979 bytes .../__pycache__/base_command.cpython-39.pyc | Bin 0 -> 6887 bytes .../cli/__pycache__/cmdoptions.cpython-39.pyc | Bin 0 -> 20816 bytes .../command_context.cpython-39.pyc | Bin 0 -> 1380 bytes .../cli/__pycache__/main.cpython-39.pyc | Bin 0 -> 1484 bytes .../__pycache__/main_parser.cpython-39.pyc | Bin 0 -> 2271 bytes .../cli/__pycache__/parser.cpython-39.pyc | Bin 0 -> 9373 bytes .../__pycache__/progress_bars.cpython-39.pyc | Bin 0 -> 7735 bytes .../__pycache__/req_command.cpython-39.pyc | Bin 0 -> 10586 bytes .../cli/__pycache__/spinners.cpython-39.pyc | Bin 0 -> 4829 bytes .../__pycache__/status_codes.cpython-39.pyc | Bin 0 -> 429 bytes .../pip/_internal/cli/autocompletion.py | 164 + .../pip/_internal/cli/base_command.py | 260 + .../pip/_internal/cli/cmdoptions.py | 971 +++ .../pip/_internal/cli/command_context.py | 36 + .../site-packages/pip/_internal/cli/main.py | 75 + .../pip/_internal/cli/main_parser.py | 96 + .../site-packages/pip/_internal/cli/parser.py | 285 + .../pip/_internal/cli/progress_bars.py | 280 + .../pip/_internal/cli/req_command.py | 436 ++ .../pip/_internal/cli/spinners.py | 173 + .../pip/_internal/cli/status_codes.py | 8 + .../pip/_internal/commands/__init__.py | 123 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 3000 bytes .../commands/__pycache__/cache.cpython-39.pyc | Bin 0 -> 5899 bytes .../commands/__pycache__/check.cpython-39.pyc | Bin 0 -> 1616 bytes .../__pycache__/completion.cpython-39.pyc | Bin 0 -> 3222 bytes .../__pycache__/configuration.cpython-39.pyc | Bin 0 -> 8172 bytes .../commands/__pycache__/debug.cpython-39.pyc | Bin 0 -> 7496 bytes .../__pycache__/download.cpython-39.pyc | Bin 0 -> 4004 bytes .../__pycache__/freeze.cpython-39.pyc | Bin 0 -> 3339 bytes .../commands/__pycache__/hash.cpython-39.pyc | Bin 0 -> 2183 bytes .../commands/__pycache__/help.cpython-39.pyc | Bin 0 -> 1409 bytes .../__pycache__/install.cpython-39.pyc | Bin 0 -> 17356 bytes .../commands/__pycache__/list.cpython-39.pyc | Bin 0 -> 9117 bytes .../__pycache__/search.cpython-39.pyc | Bin 0 -> 5131 bytes .../commands/__pycache__/show.cpython-39.pyc | Bin 0 -> 6458 bytes .../__pycache__/uninstall.cpython-39.pyc | Bin 0 -> 2994 bytes .../commands/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 5220 bytes .../pip/_internal/commands/cache.py | 234 + .../pip/_internal/commands/check.py | 51 + .../pip/_internal/commands/completion.py | 98 + .../pip/_internal/commands/configuration.py | 280 + .../pip/_internal/commands/debug.py | 251 + .../pip/_internal/commands/download.py | 143 + .../pip/_internal/commands/freeze.py | 116 + .../pip/_internal/commands/hash.py | 63 + .../pip/_internal/commands/help.py | 46 + .../pip/_internal/commands/install.py | 763 +++ .../pip/_internal/commands/list.py | 329 + .../pip/_internal/commands/search.py | 169 + .../pip/_internal/commands/show.py | 186 + .../pip/_internal/commands/uninstall.py | 95 + .../pip/_internal/commands/wheel.py | 198 + .../pip/_internal/configuration.py | 407 ++ .../pip/_internal/distributions/__init__.py | 24 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 876 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 1992 bytes .../__pycache__/installed.cpython-39.pyc | Bin 0 -> 1272 bytes .../__pycache__/sdist.cpython-39.pyc | Bin 0 -> 3551 bytes .../__pycache__/wheel.cpython-39.pyc | Bin 0 -> 1616 bytes .../pip/_internal/distributions/base.py | 46 + .../pip/_internal/distributions/installed.py | 25 + .../pip/_internal/distributions/sdist.py | 105 + .../pip/_internal/distributions/wheel.py | 37 + .../site-packages/pip/_internal/exceptions.py | 391 ++ .../pip/_internal/index/__init__.py | 2 + .../index/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 254 bytes .../__pycache__/collector.cpython-39.pyc | Bin 0 -> 17779 bytes .../__pycache__/package_finder.cpython-39.pyc | Bin 0 -> 26107 bytes .../pip/_internal/index/collector.py | 667 ++ .../pip/_internal/index/package_finder.py | 1015 +++ .../site-packages/pip/_internal/locations.py | 199 + .../site-packages/pip/_internal/main.py | 16 + .../pip/_internal/models/__init__.py | 2 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 288 bytes .../__pycache__/candidate.cpython-39.pyc | Bin 0 -> 1515 bytes .../__pycache__/direct_url.cpython-39.pyc | Bin 0 -> 6539 bytes .../__pycache__/format_control.cpython-39.pyc | Bin 0 -> 2773 bytes .../models/__pycache__/index.cpython-39.pyc | Bin 0 -> 1254 bytes .../models/__pycache__/link.cpython-39.pyc | Bin 0 -> 7184 bytes .../models/__pycache__/scheme.cpython-39.pyc | Bin 0 -> 976 bytes .../__pycache__/search_scope.cpython-39.pyc | Bin 0 -> 3469 bytes .../selection_prefs.cpython-39.pyc | Bin 0 -> 1686 bytes .../__pycache__/target_python.cpython-39.pyc | Bin 0 -> 3392 bytes .../models/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 3240 bytes .../pip/_internal/models/candidate.py | 39 + .../pip/_internal/models/direct_url.py | 243 + .../pip/_internal/models/format_control.py | 92 + .../pip/_internal/models/index.py | 34 + .../pip/_internal/models/link.py | 246 + .../pip/_internal/models/scheme.py | 31 + .../pip/_internal/models/search_scope.py | 135 + .../pip/_internal/models/selection_prefs.py | 50 + .../pip/_internal/models/target_python.py | 117 + .../pip/_internal/models/wheel.py | 78 + .../pip/_internal/network/__init__.py | 2 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 276 bytes .../network/__pycache__/auth.cpython-39.pyc | Bin 0 -> 7128 bytes .../network/__pycache__/cache.cpython-39.pyc | Bin 0 -> 2852 bytes .../__pycache__/download.cpython-39.pyc | Bin 0 -> 5303 bytes .../__pycache__/lazy_wheel.cpython-39.pyc | Bin 0 -> 8092 bytes .../__pycache__/session.cpython-39.pyc | Bin 0 -> 9537 bytes .../network/__pycache__/utils.cpython-39.pyc | Bin 0 -> 1429 bytes .../network/__pycache__/xmlrpc.cpython-39.pyc | Bin 0 -> 1891 bytes .../pip/_internal/network/auth.py | 310 + .../pip/_internal/network/cache.py | 79 + .../pip/_internal/network/download.py | 202 + .../pip/_internal/network/lazy_wheel.py | 231 + .../pip/_internal/network/session.py | 428 ++ .../pip/_internal/network/utils.py | 97 + .../pip/_internal/network/xmlrpc.py | 53 + .../pip/_internal/operations/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 224 bytes .../__pycache__/check.cpython-39.pyc | Bin 0 -> 3646 bytes .../__pycache__/freeze.cpython-39.pyc | Bin 0 -> 5966 bytes .../__pycache__/prepare.cpython-39.pyc | Bin 0 -> 13692 bytes .../_internal/operations/build/__init__.py | 0 .../build/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 230 bytes .../build/__pycache__/metadata.cpython-39.pyc | Bin 0 -> 1251 bytes .../metadata_legacy.cpython-39.pyc | Bin 0 -> 2027 bytes .../build/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 1368 bytes .../__pycache__/wheel_legacy.cpython-39.pyc | Bin 0 -> 2650 bytes .../_internal/operations/build/metadata.py | 38 + .../operations/build/metadata_legacy.py | 77 + .../pip/_internal/operations/build/wheel.py | 47 + .../operations/build/wheel_legacy.py | 113 + .../pip/_internal/operations/check.py | 155 + .../pip/_internal/operations/freeze.py | 277 + .../_internal/operations/install/__init__.py | 2 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 288 bytes .../editable_legacy.cpython-39.pyc | Bin 0 -> 1406 bytes .../install/__pycache__/legacy.cpython-39.pyc | Bin 0 -> 3296 bytes .../install/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 21280 bytes .../operations/install/editable_legacy.py | 52 + .../_internal/operations/install/legacy.py | 130 + .../pip/_internal/operations/install/wheel.py | 846 +++ .../pip/_internal/operations/prepare.py | 608 ++ .../site-packages/pip/_internal/pyproject.py | 196 + .../pip/_internal/req/__init__.py | 103 + .../req/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2525 bytes .../__pycache__/constructors.cpython-39.pyc | Bin 0 -> 11055 bytes .../req/__pycache__/req_file.cpython-39.pyc | Bin 0 -> 12741 bytes .../__pycache__/req_install.cpython-39.pyc | Bin 0 -> 21492 bytes .../req/__pycache__/req_set.cpython-39.pyc | Bin 0 -> 5844 bytes .../__pycache__/req_tracker.cpython-39.pyc | Bin 0 -> 4266 bytes .../__pycache__/req_uninstall.cpython-39.pyc | Bin 0 -> 17594 bytes .../pip/_internal/req/constructors.py | 476 ++ .../pip/_internal/req/req_file.py | 574 ++ .../pip/_internal/req/req_install.py | 915 +++ .../pip/_internal/req/req_set.py | 204 + .../pip/_internal/req/req_tracker.py | 151 + .../pip/_internal/req/req_uninstall.py | 657 ++ .../pip/_internal/resolution/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 224 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 1056 bytes .../pip/_internal/resolution/base.py | 21 + .../_internal/resolution/legacy/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 231 bytes .../__pycache__/resolver.cpython-39.pyc | Bin 0 -> 11611 bytes .../_internal/resolution/legacy/resolver.py | 473 ++ .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 235 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 5814 bytes .../__pycache__/candidates.cpython-39.pyc | Bin 0 -> 18039 bytes .../__pycache__/factory.cpython-39.pyc | Bin 0 -> 11584 bytes .../found_candidates.cpython-39.pyc | Bin 0 -> 3493 bytes .../__pycache__/provider.cpython-39.pyc | Bin 0 -> 6356 bytes .../__pycache__/reporter.cpython-39.pyc | Bin 0 -> 3242 bytes .../__pycache__/requirements.cpython-39.pyc | Bin 0 -> 7080 bytes .../__pycache__/resolver.cpython-39.pyc | Bin 0 -> 7929 bytes .../_internal/resolution/resolvelib/base.py | 156 + .../resolution/resolvelib/candidates.py | 604 ++ .../resolution/resolvelib/factory.py | 504 ++ .../resolution/resolvelib/found_candidates.py | 101 + .../resolution/resolvelib/provider.py | 174 + .../resolution/resolvelib/reporter.py | 84 + .../resolution/resolvelib/requirements.py | 201 + .../resolution/resolvelib/resolver.py | 297 + .../pip/_internal/self_outdated_check.py | 197 + .../pip/_internal/utils/__init__.py | 0 .../utils/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 219 bytes .../utils/__pycache__/appdirs.cpython-39.pyc | Bin 0 -> 1409 bytes .../utils/__pycache__/compat.cpython-39.pyc | Bin 0 -> 6734 bytes .../compatibility_tags.cpython-39.pyc | Bin 0 -> 3968 bytes .../utils/__pycache__/datetime.cpython-39.pyc | Bin 0 -> 540 bytes .../__pycache__/deprecation.cpython-39.pyc | Bin 0 -> 2866 bytes .../direct_url_helpers.cpython-39.pyc | Bin 0 -> 2687 bytes .../__pycache__/distutils_args.cpython-39.pyc | Bin 0 -> 1159 bytes .../utils/__pycache__/encoding.cpython-39.pyc | Bin 0 -> 1339 bytes .../__pycache__/entrypoints.cpython-39.pyc | Bin 0 -> 1363 bytes .../__pycache__/filesystem.cpython-39.pyc | Bin 0 -> 5700 bytes .../__pycache__/filetypes.cpython-39.pyc | Bin 0 -> 908 bytes .../utils/__pycache__/glibc.cpython-39.pyc | Bin 0 -> 1766 bytes .../utils/__pycache__/hashes.cpython-39.pyc | Bin 0 -> 5286 bytes .../inject_securetransport.cpython-39.pyc | Bin 0 -> 992 bytes .../utils/__pycache__/logging.cpython-39.pyc | Bin 0 -> 9259 bytes .../utils/__pycache__/misc.cpython-39.pyc | Bin 0 -> 25544 bytes .../utils/__pycache__/models.cpython-39.pyc | Bin 0 -> 2019 bytes .../__pycache__/packaging.cpython-39.pyc | Bin 0 -> 2672 bytes .../utils/__pycache__/parallel.cpython-39.pyc | Bin 0 -> 3237 bytes .../__pycache__/pkg_resources.cpython-39.pyc | Bin 0 -> 1888 bytes .../setuptools_build.cpython-39.pyc | Bin 0 -> 2965 bytes .../__pycache__/subprocess.cpython-39.pyc | Bin 0 -> 6102 bytes .../utils/__pycache__/temp_dir.cpython-39.pyc | Bin 0 -> 7247 bytes .../utils/__pycache__/typing.cpython-39.pyc | Bin 0 -> 1501 bytes .../__pycache__/unpacking.cpython-39.pyc | Bin 0 -> 6663 bytes .../utils/__pycache__/urls.cpython-39.pyc | Bin 0 -> 1563 bytes .../__pycache__/virtualenv.cpython-39.pyc | Bin 0 -> 3396 bytes .../utils/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 6375 bytes .../pip/_internal/utils/appdirs.py | 44 + .../pip/_internal/utils/compat.py | 293 + .../pip/_internal/utils/compatibility_tags.py | 178 + .../pip/_internal/utils/datetime.py | 14 + .../pip/_internal/utils/deprecation.py | 104 + .../pip/_internal/utils/direct_url_helpers.py | 126 + .../pip/_internal/utils/distutils_args.py | 48 + .../pip/_internal/utils/encoding.py | 41 + .../pip/_internal/utils/entrypoints.py | 31 + .../pip/_internal/utils/filesystem.py | 224 + .../pip/_internal/utils/filetypes.py | 26 + .../pip/_internal/utils/glibc.py | 98 + .../pip/_internal/utils/hashes.py | 169 + .../_internal/utils/inject_securetransport.py | 36 + .../pip/_internal/utils/logging.py | 399 ++ .../site-packages/pip/_internal/utils/misc.py | 977 +++ .../pip/_internal/utils/models.py | 44 + .../pip/_internal/utils/packaging.py | 95 + .../pip/_internal/utils/parallel.py | 107 + .../pip/_internal/utils/pkg_resources.py | 44 + .../pip/_internal/utils/setuptools_build.py | 181 + .../pip/_internal/utils/subprocess.py | 299 + .../pip/_internal/utils/temp_dir.py | 284 + .../pip/_internal/utils/typing.py | 38 + .../pip/_internal/utils/unpacking.py | 281 + .../site-packages/pip/_internal/utils/urls.py | 55 + .../pip/_internal/utils/virtualenv.py | 119 + .../pip/_internal/utils/wheel.py | 225 + .../pip/_internal/vcs/__init__.py | 15 + .../vcs/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 512 bytes .../vcs/__pycache__/bazaar.cpython-39.pyc | Bin 0 -> 3834 bytes .../vcs/__pycache__/git.cpython-39.pyc | Bin 0 -> 10647 bytes .../vcs/__pycache__/mercurial.cpython-39.pyc | Bin 0 -> 5209 bytes .../vcs/__pycache__/subversion.cpython-39.pyc | Bin 0 -> 8634 bytes .../__pycache__/versioncontrol.cpython-39.pyc | Bin 0 -> 19722 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 123 + .../site-packages/pip/_internal/vcs/git.py | 460 ++ .../pip/_internal/vcs/mercurial.py | 172 + .../pip/_internal/vcs/subversion.py | 340 + .../pip/_internal/vcs/versioncontrol.py | 735 +++ .../pip/_internal/wheel_builder.py | 363 ++ .../site-packages/pip/_vendor/__init__.py | 123 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 3339 bytes .../site-packages/pip/_vendor/vendor.txt | 24 + .../pkg_resources-0.0.0.dist-info/AUTHORS.txt | 590 ++ .../pkg_resources-0.0.0.dist-info/INSTALLER | 1 + .../pkg_resources-0.0.0.dist-info/LICENSE.txt | 20 + .../pkg_resources-0.0.0.dist-info/METADATA | 13 + .../pkg_resources-0.0.0.dist-info/RECORD | 39 + .../pkg_resources-0.0.0.dist-info/REQUESTED | 0 .../pkg_resources-0.0.0.dist-info/WHEEL | 6 + .../site-packages/pkg_resources/__init__.py | 3296 ++++++++++ .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 100401 bytes .../__pycache__/py31compat.cpython-39.pyc | Bin 0 -> 666 bytes .../pkg_resources/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 221 bytes .../__pycache__/appdirs.cpython-39.pyc | Bin 0 -> 20538 bytes .../__pycache__/pyparsing.cpython-39.pyc | Bin 0 -> 201374 bytes .../_vendor/__pycache__/six.cpython-39.pyc | Bin 0 -> 24504 bytes .../pkg_resources/_vendor/appdirs.py | 608 ++ .../_vendor/packaging/__about__.py | 21 + .../_vendor/packaging/__init__.py | 14 + .../__pycache__/__about__.cpython-39.pyc | Bin 0 -> 745 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 583 bytes .../__pycache__/_compat.cpython-39.pyc | Bin 0 -> 1045 bytes .../__pycache__/_structures.cpython-39.pyc | Bin 0 -> 2827 bytes .../__pycache__/markers.cpython-39.pyc | Bin 0 -> 8955 bytes .../__pycache__/requirements.cpython-39.pyc | Bin 0 -> 3942 bytes .../__pycache__/specifiers.cpython-39.pyc | Bin 0 -> 19831 bytes .../__pycache__/utils.cpython-39.pyc | Bin 0 -> 530 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 10666 bytes .../_vendor/packaging/_compat.py | 30 + .../_vendor/packaging/_structures.py | 68 + .../_vendor/packaging/markers.py | 301 + .../_vendor/packaging/requirements.py | 127 + .../_vendor/packaging/specifiers.py | 774 +++ .../pkg_resources/_vendor/packaging/utils.py | 14 + .../_vendor/packaging/version.py | 393 ++ .../pkg_resources/_vendor/pyparsing.py | 5742 +++++++++++++++++ .../pkg_resources/_vendor/six.py | 868 +++ .../pkg_resources/extern/__init__.py | 73 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2472 bytes .../site-packages/pkg_resources/py31compat.py | 23 + .../setuptools-44.1.1.dist-info/AUTHORS.txt | 590 ++ .../setuptools-44.1.1.dist-info/INSTALLER | 1 + .../setuptools-44.1.1.dist-info/LICENSE.txt | 20 + .../setuptools-44.1.1.dist-info/METADATA | 82 + .../setuptools-44.1.1.dist-info/RECORD | 164 + .../setuptools-44.1.1.dist-info/REQUESTED | 0 .../setuptools-44.1.1.dist-info/WHEEL | 6 + .../dependency_links.txt | 2 + .../entry_points.txt | 68 + .../setuptools-44.1.1.dist-info/top_level.txt | 3 + .../setuptools-44.1.1.dist-info/zip-safe | 1 + .../site-packages/setuptools/__init__.py | 245 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 8662 bytes .../_deprecation_warning.cpython-39.pyc | Bin 0 -> 580 bytes .../__pycache__/_imp.cpython-39.pyc | Bin 0 -> 1950 bytes .../__pycache__/archive_util.cpython-39.pyc | Bin 0 -> 5252 bytes .../__pycache__/build_meta.cpython-39.pyc | Bin 0 -> 8667 bytes .../__pycache__/config.cpython-39.pyc | Bin 0 -> 17973 bytes .../__pycache__/dep_util.cpython-39.pyc | Bin 0 -> 883 bytes .../__pycache__/depends.cpython-39.pyc | Bin 0 -> 5301 bytes .../__pycache__/dist.cpython-39.pyc | Bin 0 -> 42507 bytes .../__pycache__/errors.cpython-39.pyc | Bin 0 -> 880 bytes .../__pycache__/extension.cpython-39.pyc | Bin 0 -> 2029 bytes .../__pycache__/glob.cpython-39.pyc | Bin 0 -> 3787 bytes .../__pycache__/installer.cpython-39.pyc | Bin 0 -> 4134 bytes .../__pycache__/launch.cpython-39.pyc | Bin 0 -> 888 bytes .../__pycache__/lib2to3_ex.cpython-39.pyc | Bin 0 -> 2481 bytes .../__pycache__/monkey.cpython-39.pyc | Bin 0 -> 4702 bytes .../__pycache__/msvc.cpython-39.pyc | Bin 0 -> 39690 bytes .../__pycache__/namespaces.cpython-39.pyc | Bin 0 -> 3700 bytes .../__pycache__/package_index.cpython-39.pyc | Bin 0 -> 33138 bytes .../__pycache__/py27compat.cpython-39.pyc | Bin 0 -> 1813 bytes .../__pycache__/py31compat.cpython-39.pyc | Bin 0 -> 1255 bytes .../__pycache__/py33compat.cpython-39.pyc | Bin 0 -> 1470 bytes .../__pycache__/py34compat.cpython-39.pyc | Bin 0 -> 510 bytes .../__pycache__/sandbox.cpython-39.pyc | Bin 0 -> 15940 bytes .../__pycache__/site-patch.cpython-39.pyc | Bin 0 -> 1540 bytes .../__pycache__/ssl_support.cpython-39.pyc | Bin 0 -> 6908 bytes .../__pycache__/unicode_utils.cpython-39.pyc | Bin 0 -> 1209 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 354 bytes .../__pycache__/wheel.cpython-39.pyc | Bin 0 -> 7493 bytes .../windows_support.cpython-39.pyc | Bin 0 -> 1053 bytes .../setuptools/_deprecation_warning.py | 7 + .../site-packages/setuptools/_imp.py | 73 + .../setuptools/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 218 bytes .../__pycache__/ordered_set.cpython-39.pyc | Bin 0 -> 16412 bytes .../__pycache__/pyparsing.cpython-39.pyc | Bin 0 -> 201371 bytes .../_vendor/__pycache__/six.cpython-39.pyc | Bin 0 -> 24501 bytes .../setuptools/_vendor/ordered_set.py | 488 ++ .../setuptools/_vendor/packaging/__about__.py | 27 + .../setuptools/_vendor/packaging/__init__.py | 26 + .../__pycache__/__about__.cpython-39.pyc | Bin 0 -> 742 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 580 bytes .../__pycache__/_compat.cpython-39.pyc | Bin 0 -> 1042 bytes .../__pycache__/_structures.cpython-39.pyc | Bin 0 -> 2824 bytes .../__pycache__/markers.cpython-39.pyc | Bin 0 -> 8963 bytes .../__pycache__/requirements.cpython-39.pyc | Bin 0 -> 4055 bytes .../__pycache__/specifiers.cpython-39.pyc | Bin 0 -> 19776 bytes .../packaging/__pycache__/tags.cpython-39.pyc | Bin 0 -> 10854 bytes .../__pycache__/utils.cpython-39.pyc | Bin 0 -> 1489 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 12109 bytes .../setuptools/_vendor/packaging/_compat.py | 31 + .../_vendor/packaging/_structures.py | 68 + .../setuptools/_vendor/packaging/markers.py | 296 + .../_vendor/packaging/requirements.py | 138 + .../_vendor/packaging/specifiers.py | 749 +++ .../setuptools/_vendor/packaging/tags.py | 404 ++ .../setuptools/_vendor/packaging/utils.py | 57 + .../setuptools/_vendor/packaging/version.py | 420 ++ .../setuptools/_vendor/pyparsing.py | 5742 +++++++++++++++++ .../site-packages/setuptools/_vendor/six.py | 868 +++ .../site-packages/setuptools/archive_util.py | 173 + .../site-packages/setuptools/build_meta.py | 264 + .../site-packages/setuptools/cli-32.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/cli-64.exe | Bin 0 -> 74752 bytes .../site-packages/setuptools/cli.exe | Bin 0 -> 65536 bytes .../setuptools/command/__init__.py | 17 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 698 bytes .../command/__pycache__/alias.cpython-39.pyc | Bin 0 -> 2456 bytes .../__pycache__/bdist_egg.cpython-39.pyc | Bin 0 -> 14244 bytes .../__pycache__/bdist_rpm.cpython-39.pyc | Bin 0 -> 1846 bytes .../__pycache__/bdist_wininst.cpython-39.pyc | Bin 0 -> 1022 bytes .../__pycache__/build_clib.cpython-39.pyc | Bin 0 -> 2501 bytes .../__pycache__/build_ext.cpython-39.pyc | Bin 0 -> 9891 bytes .../__pycache__/build_py.cpython-39.pyc | Bin 0 -> 8722 bytes .../__pycache__/develop.cpython-39.pyc | Bin 0 -> 6601 bytes .../__pycache__/dist_info.cpython-39.pyc | Bin 0 -> 1425 bytes .../__pycache__/easy_install.cpython-39.pyc | Bin 0 -> 67035 bytes .../__pycache__/egg_info.cpython-39.pyc | Bin 0 -> 21852 bytes .../__pycache__/install.cpython-39.pyc | Bin 0 -> 4066 bytes .../install_egg_info.cpython-39.pyc | Bin 0 -> 2954 bytes .../__pycache__/install_lib.cpython-39.pyc | Bin 0 -> 5119 bytes .../install_scripts.cpython-39.pyc | Bin 0 -> 2333 bytes .../__pycache__/py36compat.cpython-39.pyc | Bin 0 -> 4674 bytes .../__pycache__/register.cpython-39.pyc | Bin 0 -> 875 bytes .../command/__pycache__/rotate.cpython-39.pyc | Bin 0 -> 2570 bytes .../__pycache__/saveopts.cpython-39.pyc | Bin 0 -> 953 bytes .../command/__pycache__/sdist.cpython-39.pyc | Bin 0 -> 7963 bytes .../command/__pycache__/setopt.cpython-39.pyc | Bin 0 -> 4605 bytes .../command/__pycache__/test.cpython-39.pyc | Bin 0 -> 8703 bytes .../command/__pycache__/upload.cpython-39.pyc | Bin 0 -> 848 bytes .../__pycache__/upload_docs.cpython-39.pyc | Bin 0 -> 6242 bytes .../site-packages/setuptools/command/alias.py | 80 + .../setuptools/command/bdist_egg.py | 502 ++ .../setuptools/command/bdist_rpm.py | 43 + .../setuptools/command/bdist_wininst.py | 21 + .../setuptools/command/build_clib.py | 98 + .../setuptools/command/build_ext.py | 327 + .../setuptools/command/build_py.py | 270 + .../setuptools/command/develop.py | 221 + .../setuptools/command/dist_info.py | 36 + .../setuptools/command/easy_install.py | 2402 +++++++ .../setuptools/command/egg_info.py | 717 ++ .../setuptools/command/install.py | 125 + .../setuptools/command/install_egg_info.py | 82 + .../setuptools/command/install_lib.py | 147 + .../setuptools/command/install_scripts.py | 65 + .../setuptools/command/launcher manifest.xml | 15 + .../setuptools/command/py36compat.py | 136 + .../setuptools/command/register.py | 18 + .../setuptools/command/rotate.py | 66 + .../setuptools/command/saveopts.py | 22 + .../site-packages/setuptools/command/sdist.py | 252 + .../setuptools/command/setopt.py | 149 + .../site-packages/setuptools/command/test.py | 279 + .../setuptools/command/upload.py | 17 + .../setuptools/command/upload_docs.py | 206 + .../site-packages/setuptools/config.py | 659 ++ .../site-packages/setuptools/dep_util.py | 23 + .../site-packages/setuptools/depends.py | 176 + .../site-packages/setuptools/dist.py | 1274 ++++ .../site-packages/setuptools/errors.py | 16 + .../site-packages/setuptools/extension.py | 57 + .../setuptools/extern/__init__.py | 73 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2486 bytes .../site-packages/setuptools/glob.py | 174 + .../site-packages/setuptools/gui-32.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/gui-64.exe | Bin 0 -> 75264 bytes .../site-packages/setuptools/gui.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/installer.py | 150 + .../site-packages/setuptools/launch.py | 35 + .../site-packages/setuptools/lib2to3_ex.py | 62 + .../site-packages/setuptools/monkey.py | 179 + .../site-packages/setuptools/msvc.py | 1679 +++++ .../site-packages/setuptools/namespaces.py | 107 + .../site-packages/setuptools/package_index.py | 1136 ++++ .../site-packages/setuptools/py27compat.py | 60 + .../site-packages/setuptools/py31compat.py | 32 + .../site-packages/setuptools/py33compat.py | 59 + .../site-packages/setuptools/py34compat.py | 13 + .../site-packages/setuptools/sandbox.py | 491 ++ .../setuptools/script (dev).tmpl | 6 + .../site-packages/setuptools/script.tmpl | 3 + .../site-packages/setuptools/site-patch.py | 74 + .../site-packages/setuptools/ssl_support.py | 260 + .../site-packages/setuptools/unicode_utils.py | 44 + .../site-packages/setuptools/version.py | 6 + .../site-packages/setuptools/wheel.py | 220 + .../setuptools/windows_support.py | 29 + src/awesome-date-dimension/.venv/lib64 | 1 + src/awesome-date-dimension/.venv/pyvenv.cfg | 3 + .../CacheControl-0.12.6-py2.py3-none-any.whl | Bin 0 -> 23441 bytes .../appdirs-1.4.4-py2.py3-none-any.whl | Bin 0 -> 14285 bytes .../certifi-2020.6.20-py2.py3-none-any.whl | Bin 0 -> 161344 bytes .../chardet-4.0.0-py2.py3-none-any.whl | Bin 0 -> 174749 bytes .../colorama-0.4.4-py2.py3-none-any.whl | Bin 0 -> 20722 bytes ...ntextlib2-0.6.0.post1-py2.py3-none-any.whl | Bin 0 -> 12692 bytes .../distlib-0.3.1-py2.py3-none-any.whl | Bin 0 -> 147633 bytes .../distro-1.5.0-py2.py3-none-any.whl | Bin 0 -> 19426 bytes .../html5lib-1.1-py2.py3-none-any.whl | Bin 0 -> 116071 bytes .../idna-2.10-py2.py3-none-any.whl | Bin 0 -> 63344 bytes .../ipaddr-2.2.0-py2.py3-none-any.whl | Bin 0 -> 19706 bytes .../msgpack-1.0.0-py2.py3-none-any.whl | Bin 0 -> 76178 bytes .../packaging-20.9-py2.py3-none-any.whl | Bin 0 -> 41435 bytes .../pep517-0.9.1-py2.py3-none-any.whl | Bin 0 -> 22249 bytes .../pip-20.3.4-py2.py3-none-any.whl | Bin 0 -> 311145 bytes .../pkg_resources-0.0.0-py2.py3-none-any.whl | Bin 0 -> 122731 bytes .../progress-1.5-py2.py3-none-any.whl | Bin 0 -> 12965 bytes .../pyparsing-2.4.7-py2.py3-none-any.whl | Bin 0 -> 72626 bytes .../requests-2.25.1-py2.py3-none-any.whl | Bin 0 -> 62975 bytes .../resolvelib-0.5.4-py2.py3-none-any.whl | Bin 0 -> 17707 bytes .../retrying-1.3.3-py2.py3-none-any.whl | Bin 0 -> 11776 bytes .../setuptools-44.1.1-py2.py3-none-any.whl | Bin 0 -> 473123 bytes .../six-1.16.0-py2.py3-none-any.whl | Bin 0 -> 15791 bytes .../toml-0.10.1-py2.py3-none-any.whl | Bin 0 -> 21108 bytes .../urllib3-1.26.5-py2.py3-none-any.whl | Bin 0 -> 134200 bytes .../webencodings-0.5.1-py2.py3-none-any.whl | Bin 0 -> 15904 bytes .../wheel-0.34.2-py2.py3-none-any.whl | Bin 0 -> 31030 bytes src/awesome-date-dimension/__init__.py | 0 src/awesome-date-dimension/config.py | 849 +++ .../generators/__init__.py | 0 .../awesome-date-dimension/generators/tsql.py | 6 +- 532 files changed, 66509 insertions(+), 898 deletions(-) delete mode 100644 generate/columns.py delete mode 100644 generate/holidays.py delete mode 100644 generate/script_generatior.py delete mode 100644 generate/script_generator_factory.py create mode 100644 src/awesome-date-dimension/.venv/bin/Activate.ps1 create mode 100644 src/awesome-date-dimension/.venv/bin/activate create mode 100644 src/awesome-date-dimension/.venv/bin/activate.csh create mode 100644 src/awesome-date-dimension/.venv/bin/activate.fish create mode 100755 src/awesome-date-dimension/.venv/bin/easy_install create mode 100755 src/awesome-date-dimension/.venv/bin/easy_install-3.9 create mode 100755 src/awesome-date-dimension/.venv/bin/pip create mode 100755 src/awesome-date-dimension/.venv/bin/pip3 create mode 100755 src/awesome-date-dimension/.venv/bin/pip3.9 create mode 120000 src/awesome-date-dimension/.venv/bin/python create mode 120000 src/awesome-date-dimension/.venv/bin/python3 create mode 120000 src/awesome-date-dimension/.venv/bin/python3.9 create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/__pycache__/easy_install.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/easy_install.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/INSTALLER create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/LICENSE.txt create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/METADATA create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/RECORD create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/REQUESTED create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/WHEEL create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/entry_points.txt create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/top_level.txt create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__main__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__pycache__/__main__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/build_env.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/cache.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/configuration.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/exceptions.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/locations.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/main.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/pyproject.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/build_env.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cache.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/main.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/parser.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/autocompletion.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/base_command.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/cmdoptions.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/command_context.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/main.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/main_parser.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/parser.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/progress_bars.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/req_command.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/spinners.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/status_codes.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/cache.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/check.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/completion.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/debug.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/download.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/hash.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/help.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/install.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/list.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/search.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/show.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/cache.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/check.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/completion.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/configuration.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/debug.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/download.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/freeze.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/hash.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/help.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/install.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/list.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/search.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/show.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/uninstall.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/wheel.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/configuration.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/base.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/base.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/installed.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/sdist.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/wheel.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/exceptions.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/__pycache__/collector.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/collector.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/package_finder.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/locations.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/main.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/candidate.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/format_control.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/index.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/link.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/scheme.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/target_python.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/wheel.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/candidate.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/direct_url.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/format_control.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/index.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/link.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/scheme.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/search_scope.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/selection_prefs.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/target_python.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/wheel.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/auth.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/cache.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/download.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/session.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/utils.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/auth.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/cache.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/download.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/lazy_wheel.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/session.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/utils.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/xmlrpc.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/check.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/metadata.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/metadata_legacy.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel_legacy.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/check.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/freeze.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__pycache__/legacy.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/editable_legacy.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/legacy.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/wheel.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/prepare.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/pyproject.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__pycache__/constructors.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__pycache__/req_file.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__pycache__/req_install.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__pycache__/req_set.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__pycache__/req_tracker.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/constructors.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_file.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_install.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_set.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_tracker.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_uninstall.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/__pycache__/base.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/base.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/resolver.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/base.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/candidates.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/factory.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/provider.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/reporter.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/requirements.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/resolver.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/self_outdated_check.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/compat.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/distutils_args.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/logging.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/misc.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/models.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/parallel.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/pkg_resources.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/typing.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/urls.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/appdirs.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/compat.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/compatibility_tags.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/datetime.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/deprecation.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/direct_url_helpers.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/distutils_args.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/encoding.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/entrypoints.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/filesystem.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/filetypes.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/glibc.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/hashes.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/inject_securetransport.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/logging.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/misc.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/models.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/packaging.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/parallel.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/pkg_resources.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/setuptools_build.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/subprocess.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/temp_dir.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/typing.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/unpacking.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/urls.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/virtualenv.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/wheel.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/git.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/bazaar.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/git.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/mercurial.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/subversion.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/versioncontrol.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/wheel_builder.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_vendor/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_vendor/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_vendor/vendor.txt create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/AUTHORS.txt create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/INSTALLER create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/LICENSE.txt create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/METADATA create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/RECORD create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/REQUESTED create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/WHEEL create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/__pycache__/py31compat.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__pycache__/appdirs.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__pycache__/pyparsing.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__pycache__/six.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/appdirs.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__about__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/markers.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/utils.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/_compat.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/_structures.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/markers.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/requirements.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/specifiers.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/utils.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/version.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/pyparsing.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/six.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/extern/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/extern/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/py31compat.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/AUTHORS.txt create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/INSTALLER create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/LICENSE.txt create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/METADATA create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/RECORD create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/REQUESTED create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/WHEEL create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/dependency_links.txt create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/entry_points.txt create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/top_level.txt create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/zip-safe create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/_imp.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/archive_util.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/build_meta.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/config.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/dep_util.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/depends.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/dist.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/errors.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/extension.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/glob.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/installer.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/launch.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/lib2to3_ex.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/monkey.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/msvc.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/namespaces.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/package_index.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py27compat.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py31compat.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py33compat.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py34compat.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/sandbox.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/site-patch.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/ssl_support.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/unicode_utils.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/version.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/wheel.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/windows_support.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_deprecation_warning.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_imp.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/pyparsing.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/six.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/ordered_set.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__about__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/_compat.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/_structures.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/markers.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/tags.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/utils.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/version.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_compat.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_structures.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/markers.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/requirements.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/specifiers.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/tags.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/utils.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/version.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/pyparsing.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/six.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/archive_util.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/build_meta.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/cli-32.exe create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/cli-64.exe create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/cli.exe create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/alias.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/bdist_egg.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/bdist_wininst.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/build_clib.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/build_ext.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/build_py.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/develop.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/dist_info.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/easy_install.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/egg_info.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/install.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/install_egg_info.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/install_lib.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/install_scripts.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/py36compat.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/register.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/rotate.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/saveopts.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/sdist.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/setopt.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/test.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/upload.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/upload_docs.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/alias.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/bdist_egg.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/bdist_rpm.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/bdist_wininst.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/build_clib.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/build_ext.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/build_py.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/develop.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/dist_info.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/easy_install.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/egg_info.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/install.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/install_egg_info.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/install_lib.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/install_scripts.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/launcher manifest.xml create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/py36compat.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/register.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/rotate.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/saveopts.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/sdist.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/setopt.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/test.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/upload.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/upload_docs.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/config.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/dep_util.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/depends.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/dist.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/errors.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/extension.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/extern/__init__.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/extern/__pycache__/__init__.cpython-39.pyc create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/glob.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/gui-32.exe create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/gui-64.exe create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/gui.exe create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/installer.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/launch.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/lib2to3_ex.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/monkey.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/msvc.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/namespaces.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/package_index.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/py27compat.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/py31compat.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/py33compat.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/py34compat.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/sandbox.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/script (dev).tmpl create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/script.tmpl create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/site-patch.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/ssl_support.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/unicode_utils.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/version.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/wheel.py create mode 100644 src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/windows_support.py create mode 120000 src/awesome-date-dimension/.venv/lib64 create mode 100644 src/awesome-date-dimension/.venv/pyvenv.cfg create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/CacheControl-0.12.6-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/appdirs-1.4.4-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/certifi-2020.6.20-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/chardet-4.0.0-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/colorama-0.4.4-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/contextlib2-0.6.0.post1-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/distlib-0.3.1-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/distro-1.5.0-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/html5lib-1.1-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/idna-2.10-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/ipaddr-2.2.0-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/msgpack-1.0.0-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/packaging-20.9-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/pep517-0.9.1-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/pip-20.3.4-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/progress-1.5-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/pyparsing-2.4.7-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/requests-2.25.1-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/resolvelib-0.5.4-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/retrying-1.3.3-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/setuptools-44.1.1-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/six-1.16.0-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/toml-0.10.1-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/urllib3-1.26.5-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/webencodings-0.5.1-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/.venv/share/python-wheels/wheel-0.34.2-py2.py3-none-any.whl create mode 100644 src/awesome-date-dimension/__init__.py create mode 100644 src/awesome-date-dimension/config.py create mode 100644 src/awesome-date-dimension/generators/__init__.py rename generate/tsql_generator/tsql_generator.py => src/awesome-date-dimension/generators/tsql.py (77%) diff --git a/.gitignore b/.gitignore index 0b4eb24..da15433 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -generate/.venv \ No newline at end of file +awesome-date-dimension/.venv \ No newline at end of file diff --git a/generate/columns.py b/generate/columns.py deleted file mode 100644 index a87701d..0000000 --- a/generate/columns.py +++ /dev/null @@ -1,362 +0,0 @@ -from dataclasses import dataclass - - -@dataclass(frozen=True) -class Column: - name: str - include: bool - sort_index: int - - -@dataclass(frozen=True) -class DimDateColumns: - date_key = Column('DateKey', True, 0) - the_date = Column('TheDate', True, 1) - iso_date_name = Column('ISODateName', True, 2) - american_date_name = Column('AmericanDateName', True, 3) - day_of_week_name = Column('DayOfWeekName', True, 4) - day_of_week_abbrev = Column('DayOfWeekAbbrev', True, 5) - month_name = Column('MonthName', True, 6) - month_abbrev = Column('MonthAbbrev', True, 7) - year_week_name = Column('YearWeekName', True, 8) - year_month_name = Column('YearMonthName', True, 9) - month_year_name = Column('MonthYearName', True, 10) - year_quarter_name = Column('YearQuarterName', True, 11) - year = Column('Year', True, 12) - year_week = Column('YearWeek', True, 13) - iso_year_week_code = Column('ISOYearWeekCode', True, 14) - year_month = Column('YearMonth', True, 15) - year_quarter = Column('YearQuarter', True, 16) - day_of_week_starting_monday = Column('DayOfWeekStartingMonday', True, 17) - day_of_week = Column('DayOfWeek', True, 18) - day_of_month = Column('DayOfMonth', True, 19) - day_of_quarter = Column('DayOfQuarter', True, 20) - day_of_year = Column('DayOfYear', True, 21) - week_of_quarter = Column('WeekOfQuarter', True, 22) - week_of_year = Column('WeekOfYear', True, 23) - iso_week_of_year = Column('ISOWeekOfYear', True, 24) - month = Column('Month', True, 25) - month_of_quarter = Column('MonthOfQuarter', True, 26) - quarter = Column('Quarter', True, 27) - days_in_month = Column('DaysInMonth', True, 28) - days_in_quarter = Column('DaysInQuarter', True, 29) - days_in_year = Column('DaysInYear', True, 30) - day_offset_from_today = Column('DayOffsetFromToday', True, 31) - month_offset_from_today = Column('MonthOffsetFromToday', True, 32) - quarter_offset_from_today = Column('QuarterOffsetFromToday', True, 33) - year_offset_from_today = Column('YearOffsetFromToday', True, 34) - today_flag = Column('TodayFlag', True, 35) - current_week_starting_monday_flag = Column, 36( - 'CurrentWeekStartingMondayFlag', True, 37) - current_week_flag = Column('CurrentWeekFlag', True, 38) - prior_week_flag = Column('PriorWeekFlag', True, 39) - next_week_flag = Column('NextWeekFlag', True, 40) - current_month_flag = Column('CurrentMonthFlag', True, 41) - prior_month_flag = Column('PriorMonthFlag', True, 42) - next_month_flag = Column('NextMonthFlag', True, 43) - current_quarter_flag = Column('CurrentQuarterFlag', True, 44) - prior_quarter_flag = Column('PriorQuarterFlag', True, 45) - next_quarter_flag = Column('NextQuarterFlag', True, 46) - current_year_flag = Column('CurrentYearFlag', True, 47) - prior_year_flag = Column('PriorYearFlag', True, 48) - next_year_flag = Column('NextYearFlag', True, 49) - weekday_flag = Column('WeekdayFlag', True, 50) - business_day_flag = Column('BusinessDayFlag', True, 51) - company_holiday_flag = Column('CompanyHolidayFlag', True, 52) - us_public_holiday_flag = Column('USPublicHolidayFlag', True, 53) - first_day_of_month_flag = Column('FirstDayOfMonthFlag', True, 54) - last_day_of_month_flag = Column('LastDayOfMonthFlag', True, 55) - first_day_of_quarter_flag = Column('FirstDayOfQuarterFlag', True, 56) - last_day_of_quarter_flag = Column('LastDayOfQuarterFlag', True, 57) - first_day_of_year_flag = Column('FirstDayOfYearFlag', True, 58) - last_day_of_year_flag = Column('LastDayOfYearFlag', True, 59) - fraction_of_week = Column('FractionOfWeek', True, 60) - fraction_of_month = Column('FractionOfMonth', True, 61) - fraction_of_quarter = Column('FractionOfQuarter', True, 62) - fraction_of_year_ = Column('FractionOfYear', True, 63) - prior_day = Column('PriorDay', True, 64) - next_day = Column('NextDay', True, 65) - same_day_prior_week = Column('SameDayPriorWeek', True, 66) - same_day_prior_month = Column('SameDayPriorMonth', True, 67) - same_day_prior_quarter = Column('SameDayPriorQuarter', True, 68) - same_day_prior_year = Column('SameDayPriorYear', True, 69) - same_day_next_week = Column('SameDayNextWeek', True, 70) - same_day_next_month = Column('SameDayNextMonth', True, 71) - same_day_next_quarter = Column('SameDayNextQuarter', True, 72) - same_day_next_year = Column('SameDayNextYear', True, 73) - current_week_start = Column('CurrentWeekStart', True, 74) - current_week_end = Column('CurrentWeekEnd', True, 75) - current_month_start = Column('CurrentMonthStart', True, 76) - current_month_end = Column('CurrentMonthEnd', True, 77) - current_quarter_start = Column('CurrentQuarterStart', True, 78) - current_quarter_end = Column('CurrentQuarterEnd', True, 79) - current_year_start = Column('CurrentYearStart', True, 80) - current_year_end = Column('CurrentYearEnd', True, 81) - prior_week_start = Column('PriorWeekStart', True, 82) - prior_week_end = Column('PriorWeekEnd', True, 83) - prior_month_start = Column('PriorMonthStart', True, 84) - prior_month_end = Column('PriorMonthEnd', True, 85) - prior_quarter_start = Column('PriorQuarterStart', True, 86) - prior_quarter_end = Column('PriorQuarterEnd', True, 87) - prior_year_start = Column('PriorYearStart', True, 88) - prior_year_end = Column('PriorYearEnd', True, 89) - next_week_start = Column('NextWeekStart', True, 90) - next_week_end = Column('NextWeekEnd', True, 91) - next_month_start = Column('NextMonthStart', True, 92) - next_month_end = Column('NextMonthEnd', True, 93) - next_quarter_start = Column('NextQuarterStart', True, 94) - next_quarter_end = Column('NextQuarterEnd', True, 95) - next_year_start = Column('NextYearStart', True, 96) - next_year_end = Column('NextYearEnd', True, 97) - weekly_burnup_starting_monday = Column( - 'WeeklyBurnupStartingMonday', True, 98) - weekly_burnup = Column('WeeklyBurnup', True, 99) - monthly_burnup = Column('MonthlyBurnup', True, 100) - quarterly_burnup = Column('QuarterlyBurnup', True, 101) - yearly_burnup = Column('YearlyBurnup', True, 102) - fiscal_month_name = Column('FiscalMonthName', True, 103) - fiscal_month_abbrev = Column('FiscalMonthAbbrev', True, 104) - fiscal_year_name = Column('FiscalYearWeekName', True, 105) - fiscal_year_month_name = Column('FiscalYearMonthName', True, 106) - fiscal_month_year_name = Column('FiscalMonthYearName', True, 107) - fiscal_year_quarter_name = Column('FiscalYearQuarterName', True, 108) - fiscal_year = Column('FiscalYear', True, 109) - fiscal_year_week = Column('FiscalYearWeek', True, 110) - fiscal_year_month = Column('FiscalYearMonth', True, 111) - fiscal_year_quarter = Column('FiscalYearQuarter', True, 112) - fiscal_day_of_month = Column('FiscalDayOfMonth', True, 113) - fiscal_day_of_quarter = Column('FiscalDayOfQuarter', True, 114) - fiscal_day_of_year = Column('FiscalDayOfYear', True, 115) - fiscal_week_of_quarter = Column('FiscalWeekOfQuarter', True, 116) - fiscal_week_of_year = Column('FiscalWeekOfYear', True, 117) - fiscal_month = Column('FiscalMonth', True, 118) - fiscal_month_of_quarter = Column('FiscalMonthOfQuarter', True, 119) - fiscal_quarter = Column('FiscalQuarter', True, 120) - fiscal_days_in_month = Column('FiscalDaysInMonth', True, 121) - fiscal_days_in_quarter = Column('FiscalDaysInQuarter', True, 122) - fiscal_days_in_year = Column('FiscalDaysInYear', True, 123) - fiscal_current_month_flag = Column('FiscalCurrentMonthFlag', True, 124) - fiscal_prior_month_flag = Column('FiscalPriorMonthFlag', True, 125) - fiscal_next_month_flag = Column('FiscalNextMonthFlag', True, 126) - fiscal_current_quarter_flag = Column('FiscalCurrentQuarterFlag', True, 127) - fiscal_prior_quarter_flag = Column('FiscalPriorQuarterFlag', True, 128) - fiscal_next_quarter_flag = Column('FiscalNextQuarterFlag', True, 129) - fiscal_current_year_flag = Column('FiscalCurrentYearFlag', True, 130) - fiscal_prior_year_flag = Column('FiscalPriorYearFlag', True, 131) - fiscal_next_year_flag = Column('FiscalNextYearFlag', True, 132) - fiscal_first_day_of_month_flag = Column( - 'FiscalFirstDayOfMonthFlag', True, 133) - fiscal_last_day_of_month_flag = Column( - 'FiscalLastDayOfMonthFlag', True, 134) - fiscal_first_day_of_quarter_flag = Column, 135( - 'FiscalFirstDayOfQuarterFlag', True, 136) - fiscal_last_day_of_quarter_flag = Column, 137( - 'FiscalLastDayOfQuarterFlag', True, 138) - fiscal_first_day_of_year_flag = Column( - 'FiscalFirstDayOfYearFlag', True, 139) - fiscal_last_day_of_year_flag = Column('FiscalLastDayOfYearFlag', True, 140) - fiscal_fraction_of_month = Column('FiscalFractionOfMonth', True, 141) - fiscal_fraction_of_quarter = Column('FiscalFractionOfQuarter', True, 142) - fiscal_fraction_of_year = Column('FiscalFractionOfYear', True, 143) - fiscal_current_month_start = Column('FiscalCurrentMonthStart', True, 144) - fiscal_current_month_end = Column('FiscalCurrentMonthEnd', True, 145) - fiscal_current_quarter_start = Column( - 'FiscalCurrentQuarterStart', True, 146) - fiscal_current_quarter_end = Column('FiscalCurrentQuarterEnd', True, 147) - fiscal_current_year_start = Column('FiscalCurrentYearStart', True, 148) - fiscal_current_year_end = Column('FiscalCurrentYearEnd', True, 149) - fiscal_prior_month_start = Column('FiscalPriorMonthStart', True, 150) - fiscal_prior_month_end = Column('FiscalPriorMonthEnd', True, 151) - fiscal_prior_quarter_start = Column('FiscalPriorQuarterStart', True, 152) - fiscal_prior_quarter_end = Column('FiscalPriorQuarterEnd', True, 153) - fiscal_prior_year_start = Column('FiscalPriorYearStart', True, 154) - fiscal_prior_year_end = Column('FiscalPriorYearEnd', True, 155) - fiscal_next_month_start = Column('FiscalNextMonthStart', True, 156) - fiscal_next_month_end = Column('FiscalNextMonthEnd', True, 157) - fiscal_next_quarter_start = Column('FiscalNextQuarterStart', True, 158) - fiscal_next_quarter_end = Column('FiscalNextQuarterEnd', True, 159) - fiscal_next_year_start = Column('FiscalNextYearStart', True, 160) - fiscal_next_year_end = Column('FiscalNextYearEnd', True, 161) - fiscal_monthly_burnup = Column('FiscalMonthlyBurnup', True, 162) - fiscal_quarterly_burnup = Column('FiscalQuarterlyBurnup', True, 163) - fiscal_yearly_burnup = Column('FiscalYearlyBurnup', True, 164) - company_holiday_name = Column('CompanyHolidayName', True, 165) - us_public_holiday_name = Column('USPublicHolidayName', True, 166) - - -@dataclass(frozen=True) -class DimFiscalMonthColumns: - month_start_key = Column('MonthStartKey', True, 0) - month_end_key = Column('MonthEndKey', True, 1) - month_start_date = Column('MonthStartDate', True, 2) - month_end_date = Column('MonthEndDate', True, 3) - month_start_iso_date_name = Column('MonthStartISODateName', True, 4) - month_end_iso_date_name = Column('MonthEndISODateName', True, 5) - month_start_american_date_name = Column( - 'MonthStartAmericanDateName', True, 6) - month_end_american_date_name = Column('MonthEndAmericanDateName', True, 7) - month_name = Column('MonthName', True, 8) - month_abbrev = Column('MonthAbbrev', True, 9) - month_start_year_week_name = Column('MonthStartYearWeekName', True, 10) - month_end_year_week_name = Column('MonthEndYearWeekName', True, 11) - year_month_name = Column('YearMonthName', True, 12) - month_year_name = Column('MonthYearName', True, 13) - year_quarter_name = Column('YearQuarterName', True, 14) - year = Column('Year', True, 15) - month_start_year_week = Column('MonthStartYearWeek', True, 16) - month_end_year_week = Column('MonthEndYearWeek', True, 17) - year_month = Column('YearMonth', True, 18) - year_quarter = Column('YearQuarter', True, 19) - month_start_day_of_quarter = Column('MonthStartDayOfQuarter', True, 20) - month_end_day_of_quarter = Column('MonthEndDayOfQuarter', True, 21) - month_start_day_of_year = Column('MonthStartDayOfYear', True, 22) - month_end_day_of_year = Column('MonthEndDayOfYear', True, 23) - month_start_week_of_quarter = Column('MonthStartWeekOfQuarter', True, 24) - month_end_week_of_quarter = Column('MonthEndWeekOfQuarter', True, 25) - month_start_week_of_year = Column('MonthStartWeekOfYear', True, 26) - month_end_week_of_year = Column('MonthEndWeekOfYear', True, 27) - month_of_quarter = Column('MonthOfQuarter', True, 28) - quarter = Column('Quarter', True, 29) - days_in_month = Column('DaysInMonth', True, 30) - days_in_quarter = Column('DaysInQuarter', True, 31) - days_in_year = Column('DaysInYear', True, 32) - current_month_flag = Column('CurrentMonthFlag', True, 33) - prior_month_flag = Column('PriorMonthFlag', True, 34) - next_month_flag = Column('NextMonthFlag', True, 35) - current_quarter_flag = Column('CurrentQuarterFlag', True, 36) - prior_quarter_flag = Column('PriorQuarterFlag', True, 37) - next_quarter_flag = Column('NextQuarterFlag', True, 38) - current_year_flag = Column('CurrentYearFlag', True, 39) - prior_year_flag = Column('PriorYearFlag', True, 40) - next_year_flag = Column('NextYearFlag', True, 41) - first_day_of_month_flag = Column('FirstDayOfMonthFlag', True, 42) - last_day_of_month_flag = Column('LastDayOfMonthFlag', True, 43) - first_day_of_quarter_flag = Column('FirstDayOfQuarterFlag', True, 44) - last_day_of_quarter_flag = Column('LastDayOfQuarterFlag', True, 45) - first_day_of_year_flag = Column('FirstDayOfYearFlag', True, 46) - last_day_of_year_flag = Column('LastDayOfYearFlag', True, 47) - month_start_fraction_of_quarter = Column( - 'MonthStartFractionOfQuarter', True, 48) - month_end_fraction_of_quarter = Column( - 'MonthEndFractionOfQuarter', True, 49) - month_start_fraction_of_year = Column('MonthStartFractionOfYear', True, 50) - month_end_fraction_of_year = Column('MonthEndFractionOfYear', True, 51) - month_start_current_quarter_start = Column( - 'MonthStartCurrentQuarterStart', True, 52) - month_start_current_quarter_end = Column( - 'MonthStartCurrentQuarterEnd', True, 53) - month_start_current_year_start = Column( - 'MonthStartCurrentYearStart', True, 54) - month_start_current_year_end = Column('MonthStartCurrentYearEnd', True, 55) - month_start_prior_month_start = Column( - 'MonthStartPriorMonthStart', True, 56) - month_start_prior_month_end = Column('MonthStartPriorMonthEnd', True, 57) - month_start_prior_quarter_start = Column( - 'MonthStartPriorQuarterStart', True, 58) - month_start_prior_quarter_end = Column( - 'MonthStartPriorQuarterEnd', True, 59) - month_start_prior_year_start = Column('MonthStartPriorYearStart', True, 60) - month_start_prior_year_end = Column('MonthStartPriorYearEnd', True, 61) - month_start_next_month_start = Column('MonthStartNextMonthStart', True, 62) - month_start_next_month_end = Column('MonthStartNextMonthEnd', True, 63) - month_start_next_quarter_start = Column( - 'MonthStartNextQuarterStart', True, 64) - month_start_next_quarter_end = Column('MonthStartNextQuarterEnd', True, 65) - month_start_next_year_start = Column('MonthStartNextYearStart', True, 66) - month_start_next_year_end = Column('MonthStartNextYearEnd', True, 67) - month_start_quarterly_burnup = Column( - 'MonthStartQuarterlyBurnup', True, 68) - month_end_quarterly_burnup = Column('MonthEndQuarterlyBurnup', True, 69) - month_start_yearly_burnup = Column('MonthStartYearlyBurnup', True, 70) - month_end_yearly_burnup = Column('MonthEndYearlyBurnup', True, 71) - company_holidays_in_month = Column('CompanyHolidaysInMonth', True, 72) - us_public_holidays_in_month = Column('USPublicHolidaysInMonth', True, 73) - - -@dataclass(frozen=True) -class DimCalendarMonthColumns: - month_start_key = Column('MonthStartKey', True, 0) - month_end_key = Column('MonthEndKey', True, 1) - month_start_date = Column('MonthStartDate', True, 2) - month_end_date = Column('MonthEndDate', True, 3) - month_start_iso_date_name = Column('MonthStartISODateName', True, 4) - month_end_iso_date_name = Column('MonthEndISODateName', True, 5) - month_start_american_date_name = Column( - 'MonthStartAmericanDateName', True, 6) - month_end_american_date_name = Column('MonthEndAmericanDateName', True, 7) - month_name = Column('MonthName', True, 8) - month_abbrev = Column('MonthAbbrev', True, 9) - month_start_year_week_name = Column('MonthStartYearWeekName', True, 10) - month_end_year_week_name = Column('MonthEndYearWeekName', True, 11) - year_month_name = Column('YearMonthName', True, 12) - month_year_name = Column('MonthYearName', True, 13) - year_quarter_name = Column('YearQuarterName', True, 14) - year = Column('Year', True, 15) - month_start_year_week = Column('MonthStartYearWeek', True, 16) - month_end_year_week = Column('MonthEndYearWeek', True, 17) - year_month = Column('YearMonth', True, 18) - year_quarter = Column('YearQuarter', True, 19) - month_start_day_of_quarter = Column('MonthStartDayOfQuarter', True, 20) - month_end_day_of_quarter = Column('MonthEndDayOfQuarter', True, 21) - month_start_day_of_year = Column('MonthStartDayOfYear', True, 22) - month_end_day_of_year = Column('MonthEndDayOfYear', True, 23) - month_start_week_of_quarter = Column('MonthStartWeekOfQuarter', True, 24) - month_end_week_of_quarter = Column('MonthEndWeekOfQuarter', True, 25) - month_start_week_of_year = Column('MonthStartWeekOfYear', True, 26) - month_end_week_of_year = Column('MonthEndWeekOfYear', True, 27) - month_of_quarter = Column('MonthOfQuarter', True, 28) - quarter = Column('Quarter', True, 29) - days_in_month = Column('DaysInMonth', True, 30) - days_in_quarter = Column('DaysInQuarter', True, 31) - days_in_year = Column('DaysInYear', True, 32) - current_month_flag = Column('CurrentMonthFlag', True, 33) - prior_month_flag = Column('PriorMonthFlag', True, 34) - next_month_flag = Column('NextMonthFlag', True, 35) - current_quarter_flag = Column('CurrentQuarterFlag', True, 36) - prior_quarter_flag = Column('PriorQuarterFlag', True, 37) - next_quarter_flag = Column('NextQuarterFlag', True, 38) - current_year_flag = Column('CurrentYearFlag', True, 39) - prior_year_flag = Column('PriorYearFlag', True, 40) - next_year_flag = Column('NextYearFlag', True, 41) - first_day_of_month_flag = Column('FirstDayOfMonthFlag', True, 42) - last_day_of_month_flag = Column('LastDayOfMonthFlag', True, 43) - first_day_of_quarter_flag = Column('FirstDayOfQuarterFlag', True, 44) - last_day_of_quarter_flag = Column('LastDayOfQuarterFlag', True, 45) - first_day_of_year_flag = Column('FirstDayOfYearFlag', True, 46) - last_day_of_year_flag = Column('LastDayOfYearFlag', True, 47) - month_start_fraction_of_quarter = Column( - 'MonthStartFractionOfQuarter', True, 48) - month_end_fraction_of_quarter = Column( - 'MonthEndFractionOfQuarter', True, 49) - month_start_fraction_of_year = Column('MonthStartFractionOfYear', True, 50) - month_end_fraction_of_year = Column('MonthEndFractionOfYear', True, 51) - month_start_current_quarter_start = Column( - 'MonthStartCurrentQuarterStart', True, 52) - month_start_current_quarter_end = Column( - 'MonthStartCurrentQuarterEnd', True, 53) - month_start_current_year_start = Column( - 'MonthStartCurrentYearStart', True, 54) - month_start_current_year_end = Column('MonthStartCurrentYearEnd', True, 55) - month_start_prior_month_start = Column( - 'MonthStartPriorMonthStart', True, 56) - month_start_prior_month_end = Column('MonthStartPriorMonthEnd', True, 57) - month_start_prior_quarter_start = Column( - 'MonthStartPriorQuarterStart', True, 58) - month_start_prior_quarter_end = Column( - 'MonthStartPriorQuarterEnd', True, 59) - month_start_prior_year_start = Column('MonthStartPriorYearStart', True, 60) - month_start_prior_year_end = Column('MonthStartPriorYearEnd', True, 61) - month_start_next_month_start = Column('MonthStartNextMonthStart', True, 62) - month_start_next_month_end = Column('MonthStartNextMonthEnd', True, 63) - month_start_next_quarter_start = Column( - 'MonthStartNextQuarterStart', True, 64) - month_start_next_quarter_end = Column('MonthStartNextQuarterEnd', True, 65) - month_start_next_year_start = Column('MonthStartNextYearStart', True, 66) - month_start_next_year_end = Column('MonthStartNextYearEnd', True, 67) - month_start_quarterly_burnup = Column( - 'MonthStartQuarterlyBurnup', True, 68) - month_end_quarterly_burnup = Column('MonthEndQuarterlyBurnup', True, 69) - month_start_yearly_burnup = Column('MonthStartYearlyBurnup', True, 70) - month_end_yearly_burnup = Column('MonthEndYearlyBurnup', True, 71) - company_holidays_in_month = Column('CompanyHolidaysInMonth', True, 72) - us_public_holidays_in_month = Column('USPublicHolidaysInMonth', True, 73) diff --git a/generate/holidays.py b/generate/holidays.py deleted file mode 100644 index b344fa5..0000000 --- a/generate/holidays.py +++ /dev/null @@ -1,366 +0,0 @@ -from dataclasses import dataclass -from datetime import datetime - - -@dataclass(frozen=True) -class HolidayType: - name: str - generated_column_prefix: str - included_in_business_day_calc: bool - - -@dataclass(frozen=True) -class Holiday: - holiday_name: str - holiday_date: datetime.date - - -@dataclass(frozen=True) -class HolidayCalendar: - holiday_type: HolidayType - holidays: list[Holiday] - - -default_company_holidays: HolidayCalendar = HolidayCalendar( - HolidayType('Company Holiday', 'Company', True), - [ - Holiday('New Year''s Day', datetime.fromisoformat('2012-01-02')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2012-01-16')), - Holiday('Memorial Day', datetime.fromisoformat('2012-05-28')), - Holiday('Independence Day', datetime.fromisoformat('2012-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2012-09-03')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2012-11-22')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2012-11-23')), - Holiday('Christmas Eve', datetime.fromisoformat('2012-12-24')), - Holiday('Christmas Day', datetime.fromisoformat('2012-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2013-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2013-01-21')), - Holiday('Memorial Day', datetime.fromisoformat('2013-05-27')), - Holiday('Independence Day', datetime.fromisoformat('2013-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2013-09-02')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2013-11-28')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2013-11-29')), - Holiday('Christmas Eve', datetime.fromisoformat('2013-12-24')), - Holiday('Christmas Day', datetime.fromisoformat('2013-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2014-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2014-01-20')), - Holiday('Memorial Day', datetime.fromisoformat('2014-05-26')), - Holiday('Independence Day', datetime.fromisoformat('2014-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2014-09-01')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2014-11-28')), - Holiday('Christmas Eve', datetime.fromisoformat('2014-12-24')), - Holiday('Christmas Day', datetime.fromisoformat('2014-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2015-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2015-01-19')), - Holiday('Memorial Day', datetime.fromisoformat('2015-05-25')), - Holiday('Independence Day', datetime.fromisoformat('2015-07-03')), - Holiday('Labor Day', datetime.fromisoformat('2015-09-07')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2015-11-26')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2015-11-27')), - Holiday('Christmas Eve', datetime.fromisoformat('2015-12-24')), - Holiday('Christmas Day', datetime.fromisoformat('2015-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2016-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2016-01-18')), - Holiday('Memorial Day', datetime.fromisoformat('2016-05-30')), - Holiday('Independence Day', datetime.fromisoformat('2016-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2016-09-05')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2016-11-24')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2016-11-25')), - Holiday('Christmas Eve', datetime.fromisoformat('2016-12-23')), - Holiday('Christmas Day', datetime.fromisoformat('2016-12-26')), - - Holiday('New Year''s Day', datetime.fromisoformat('2017-01-02')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2017-01-16')), - Holiday('Memorial Day', datetime.fromisoformat('2017-05-29')), - Holiday('Independence Day', datetime.fromisoformat('2017-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2017-09-04')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2017-11-23')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2017-11-24')), - Holiday('Christmas Eve', datetime.fromisoformat('2017-12-25')), - Holiday('Christmas Day', datetime.fromisoformat('2017-12-26')), - - Holiday('New Year''s Day', datetime.fromisoformat('2018-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2018-01-15')), - Holiday('Memorial Day', datetime.fromisoformat('2018-05-28')), - Holiday('Independence Day', datetime.fromisoformat('2018-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2018-09-03')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2018-11-22')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2018-11-23')), - Holiday('Christmas Eve', datetime.fromisoformat('2018-12-24')), - Holiday('Christmas Day', datetime.fromisoformat('2018-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2019-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2019-01-21')), - Holiday('Memorial Day', datetime.fromisoformat('2019-05-27')), - Holiday('Independence Day', datetime.fromisoformat('2019-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2019-09-02')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2019-11-28')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2019-11-29')), - Holiday('Christmas Eve', datetime.fromisoformat('2019-12-24')), - Holiday('Christmas Day', datetime.fromisoformat('2019-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2020-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2020-01-20')), - Holiday('Memorial Day', datetime.fromisoformat('2020-05-25')), - Holiday('Independence Day', datetime.fromisoformat('2020-07-03')), - Holiday('Labor Day', datetime.fromisoformat('2020-09-07')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2020-11-26')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2020-11-27')), - Holiday('Christmas Eve', datetime.fromisoformat('2020-12-24')), - Holiday('Christmas Day', datetime.fromisoformat('2020-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2021-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2021-01-18')), - Holiday('Memorial Day', datetime.fromisoformat('2021-05-31')), - Holiday('Independence Day', datetime.fromisoformat('2021-07-05')), - Holiday('Labor Day', datetime.fromisoformat('2021-09-06')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2021-11-26')), - Holiday('Christmas Eve', datetime.fromisoformat('2021-12-23')), - Holiday('Christmas Day', datetime.fromisoformat('2021-12-24')), - - Holiday('New Year''s Day', datetime.fromisoformat('2021-12-31')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2022-01-17')), - Holiday('Memorial Day', datetime.fromisoformat('2022-05-30')), - Holiday('Independence Day', datetime.fromisoformat('2022-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2022-09-05')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2022-11-24')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2022-11-25')), - Holiday('Christmas Eve', datetime.fromisoformat('2022-12-23')), - Holiday('Christmas Day', datetime.fromisoformat('2022-12-26')), - - Holiday('New Year''s Day', datetime.fromisoformat('2023-01-02')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2023-01-16')), - Holiday('Memorial Day', datetime.fromisoformat('2023-05-29')), - Holiday('Independence Day', datetime.fromisoformat('2023-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2023-09-04')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2023-11-23')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2023-11-24')), - Holiday('Christmas Eve', datetime.fromisoformat('2023-12-25')), - Holiday('Christmas Day', datetime.fromisoformat('2023-12-26')), - - Holiday('New Year''s Day', datetime.fromisoformat('2024-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2024-01-15')), - Holiday('Memorial Day', datetime.fromisoformat('2024-05-27')), - Holiday('Independence Day', datetime.fromisoformat('2024-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2024-09-02')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2024-11-28')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2024-11-29')), - Holiday('Christmas Eve', datetime.fromisoformat('2024-12-24')), - Holiday('Christmas Day', datetime.fromisoformat('2024-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2025-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2025-01-20')), - Holiday('Memorial Day', datetime.fromisoformat('2025-05-26')), - Holiday('Independence Day', datetime.fromisoformat('2025-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2025-09-01')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2025-11-27')), - Holiday('Friday After Thanksgiving', - datetime.fromisoformat('2025-11-28')), - Holiday('Christmas Eve', datetime.fromisoformat('2025-12-24')), - Holiday('Christmas Day', datetime.fromisoformat('2025-12-25')), - ] -) - -default_us_public_holidays: HolidayCalendar = HolidayCalendar( - HolidayType('US Public Holiday', 'USPublic', False), - [ - Holiday('New Year''s Day', datetime.fromisoformat('2012-01-02')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2012-01-16')), - Holiday('Presidents'' Day', datetime.fromisoformat('2012-02-20')), - Holiday('Memorial Day', datetime.fromisoformat('2012-05-28')), - Holiday('Independence Day', datetime.fromisoformat('2012-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2012-09-03')), - Holiday('Columbus Day', datetime.fromisoformat('2012-10-08')), - Holiday('Veterans Day', datetime.fromisoformat('2012-11-12')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2012-11-22')), - Holiday('Christmas Day', datetime.fromisoformat('2012-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2013-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2013-01-21')), - Holiday('Presidents'' Day', datetime.fromisoformat('2013-02-18')), - Holiday('Memorial Day', datetime.fromisoformat('2013-05-27')), - Holiday('Independence Day', datetime.fromisoformat('2013-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2013-09-02')), - Holiday('Columbus Day', datetime.fromisoformat('2013-10-14')), - Holiday('Veterans Day', datetime.fromisoformat('2013-11-11')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2013-11-28')), - Holiday('Christmas Day', datetime.fromisoformat('2013-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2014-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2014-01-20')), - Holiday('Presidents'' Day', datetime.fromisoformat('2014-02-17')), - Holiday('Memorial Day', datetime.fromisoformat('2014-05-26')), - Holiday('Independence Day', datetime.fromisoformat('2014-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2014-09-01')), - Holiday('Columbus Day', datetime.fromisoformat('2014-10-13')), - Holiday('Veterans Day', datetime.fromisoformat('2014-11-11')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2014-11-27')), - Holiday('Christmas Day', datetime.fromisoformat('2014-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2015-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2015-01-19')), - Holiday('Presidents'' Day', datetime.fromisoformat('2015-02-16')), - Holiday('Memorial Day', datetime.fromisoformat('2015-05-25')), - Holiday('Independence Day', datetime.fromisoformat('2015-07-03')), - Holiday('Labor Day', datetime.fromisoformat('2015-09-07')), - Holiday('Columbus Day', datetime.fromisoformat('2015-10-12')), - Holiday('Veterans Day', datetime.fromisoformat('2015-11-11')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2015-11-26')), - Holiday('Christmas Day', datetime.fromisoformat('2015-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2016-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2016-01-18')), - Holiday('Presidents'' Day', datetime.fromisoformat('2016-02-15')), - Holiday('Memorial Day', datetime.fromisoformat('2016-05-30')), - Holiday('Independence Day', datetime.fromisoformat('2016-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2016-09-05')), - Holiday('Columbus Day', datetime.fromisoformat('2016-10-10')), - Holiday('Veterans Day', datetime.fromisoformat('2016-11-11')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2016-11-24')), - Holiday('Christmas Day', datetime.fromisoformat('2016-12-26')), - - Holiday('New Year''s Day', datetime.fromisoformat('2017-01-02')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2017-01-16')), - Holiday('Presidents'' Day', datetime.fromisoformat('2017-02-20')), - Holiday('Memorial Day', datetime.fromisoformat('2017-05-29')), - Holiday('Independence Day', datetime.fromisoformat('2017-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2017-09-04')), - Holiday('Columbus Day', datetime.fromisoformat('2017-10-09')), - Holiday('Veterans Day', datetime.fromisoformat('2017-11-10')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2017-11-23')), - Holiday('Christmas Day', datetime.fromisoformat('2017-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2018-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2018-01-15')), - Holiday('Presidents'' Day', datetime.fromisoformat('2018-02-19')), - Holiday('Memorial Day', datetime.fromisoformat('2018-05-28')), - Holiday('Independence Day', datetime.fromisoformat('2018-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2018-09-03')), - Holiday('Columbus Day', datetime.fromisoformat('2018-10-08')), - Holiday('Veterans Day', datetime.fromisoformat('2018-11-12')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2018-11-22')), - Holiday('Christmas Day', datetime.fromisoformat('2018-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2019-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2019-01-21')), - Holiday('Presidents'' Day', datetime.fromisoformat('2019-02-18')), - Holiday('Memorial Day', datetime.fromisoformat('2019-05-27')), - Holiday('Independence Day', datetime.fromisoformat('2019-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2019-09-02')), - Holiday('Columbus Day', datetime.fromisoformat('2019-10-14')), - Holiday('Veterans Day', datetime.fromisoformat('2019-11-11')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2019-11-28')), - Holiday('Christmas Day', datetime.fromisoformat('2019-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2020-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2020-01-20')), - Holiday('Presidents'' Day', datetime.fromisoformat('2020-02-17')), - Holiday('Memorial Day', datetime.fromisoformat('2020-05-25')), - Holiday('Independence Day', datetime.fromisoformat('2020-07-03')), - Holiday('Labor Day', datetime.fromisoformat('2020-09-07')), - Holiday('Columbus Day', datetime.fromisoformat('2020-10-12')), - Holiday('Veterans Day', datetime.fromisoformat('2020-11-11')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2020-11-26')), - Holiday('Christmas Day', datetime.fromisoformat('2020-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2021-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2021-01-18')), - Holiday('Presidents'' Day', datetime.fromisoformat('2021-02-15')), - Holiday('Memorial Day', datetime.fromisoformat('2021-05-31')), - Holiday('Independence Day', datetime.fromisoformat('2021-07-05')), - Holiday('Labor Day', datetime.fromisoformat('2021-09-06')), - Holiday('Columbus Day', datetime.fromisoformat('2021-10-11')), - Holiday('Veterans Day', datetime.fromisoformat('2021-11-11')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2021-11-25')), - Holiday('Christmas Day', datetime.fromisoformat('2021-12-24')), - - Holiday('New Year''s Day', datetime.fromisoformat('2021-12-31')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2022-01-17')), - Holiday('Presidents'' Day', datetime.fromisoformat('2022-02-21')), - Holiday('Memorial Day', datetime.fromisoformat('2022-05-30')), - Holiday('Independence Day', datetime.fromisoformat('2022-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2022-09-05')), - Holiday('Columbus Day', datetime.fromisoformat('2022-10-10')), - Holiday('Veterans Day', datetime.fromisoformat('2022-11-11')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2022-11-24')), - Holiday('Christmas Day', datetime.fromisoformat('2022-12-26')), - - Holiday('New Year''s Day', datetime.fromisoformat('2023-01-02')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2023-01-16')), - Holiday('Presidents'' Day', datetime.fromisoformat('2023-02-20')), - Holiday('Memorial Day', datetime.fromisoformat('2023-05-29')), - Holiday('Independence Day', datetime.fromisoformat('2023-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2023-09-04')), - Holiday('Columbus Day', datetime.fromisoformat('2023-10-09')), - Holiday('Veterans Day', datetime.fromisoformat('2023-11-10')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2023-11-23')), - Holiday('Christmas Day', datetime.fromisoformat('2023-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2024-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2024-01-15')), - Holiday('Presidents'' Day', datetime.fromisoformat('2024-02-19')), - Holiday('Memorial Day', datetime.fromisoformat('2024-05-27')), - Holiday('Independence Day', datetime.fromisoformat('2024-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2024-09-02')), - Holiday('Columbus Day', datetime.fromisoformat('2024-10-14')), - Holiday('Veterans Day', datetime.fromisoformat('2024-11-11')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2024-11-28')), - Holiday('Christmas Day', datetime.fromisoformat('2024-12-25')), - - Holiday('New Year''s Day', datetime.fromisoformat('2025-01-01')), - Holiday('Martin Luther King, Jr. Day', - datetime.fromisoformat('2025-01-20')), - Holiday('Presidents'' Day', datetime.fromisoformat('2025-02-17')), - Holiday('Memorial Day', datetime.fromisoformat('2025-05-26')), - Holiday('Independence Day', datetime.fromisoformat('2025-07-04')), - Holiday('Labor Day', datetime.fromisoformat('2025-09-01')), - Holiday('Columbus Day', datetime.fromisoformat('2025-10-13')), - Holiday('Veterans Day', datetime.fromisoformat('2025-11-11')), - Holiday('Thanksgiving Day', datetime.fromisoformat('2025-11-27')), - Holiday('Christmas Day', datetime.fromisoformat('2025-12-25')), - ] -) diff --git a/generate/script_generatior.py b/generate/script_generatior.py deleted file mode 100644 index e959f45..0000000 --- a/generate/script_generatior.py +++ /dev/null @@ -1,149 +0,0 @@ -from dataclasses import asdict, dataclass, field -from datetime import datetime -from typing import Callable -from columns import Column, DimCalendarMonthColumns, DimDateColumns, DimFiscalMonthColumns -from holidays import HolidayCalendar, HolidayType, default_company_holidays, default_us_public_holidays -from abc import ABC, abstractmethod -from pathlib import Path - - -@dataclass(frozen=True) -class DateRange: - start_date: datetime.date = datetime.fromisoformat('2000-01-01').date() - num_years: int = 100 - - def __post_init__(self): - assert self.num_years > 0, 'num_years must be greater than 0.' - - -@dataclass(frozen=True) -class FiscalConfig: - fiscal_month_start_day: int = 1 - fiscal_year_start_month: int = 1 - fiscal_month_end_matches_calendar: bool = True - fiscal_quarter_end_matches_calendar: bool = True - fiscal_year_end_matches_calendar: bool = True - - def __post_init__(self): - assert 1 <= self.fiscal_month_start_day <= 28, 'fiscal_month_start_day must be between 1 and 28.' - assert 1 <= self.fiscal_year_start_month <= 12, 'fiscal_year_start_month must be between 1 and 12.' - - -@dataclass(frozen=True) -class HolidayConfig: - generate_holidays: bool = True - holiday_types_schema_name: str = 'integration' - holiday_types_table_name: str = 'manual_HolidayTypes' - holidays_schema_name: str = 'integration' - holidays_table_name: str = 'manual_Holidays' - holiday_calendars: list[HolidayCalendar] = [ - default_company_holidays, default_us_public_holidays] - holiday_types: list[HolidayType] = field(init=False) - - def __post_init__(self): - if self.generate_holidays: - holiday_types = [ - cal.holiday_type for cal in self.holiday_calendars] - holiday_type_names = [t.name for t in holiday_types] - holiday_type_prefixes = [ - t.generated_column_prefix for t in holiday_types] - assert len(holiday_type_names) == len(set(holiday_type_names) - ), 'detected a duplicate HolidayType name in HolidayConfig.' - assert len(holiday_type_prefixes) == len(set(holiday_type_prefixes) - ), 'detected a duplicate HolidayTypePrefix in HolidayConfig.' - self.holiday_types = holiday_types - - -@dataclass(frozen=True) -class DimDateConfig: - table_schema: str = 'dbo' - table_name: str = 'DimDate' - columns: DimDateColumns = DimDateColumns() - column_name_factory: Callable[[str], str] = None - - def __post_init__(self): - col_dict = asdict(self.columns) - sort_keys = [v['sort_index'] - for v in col_dict.values()] - distinct_sort_keys = set(sort_keys) - assert len(sort_keys) == len( - distinct_sort_keys), 'there was a duplicate sort key in the column definitions for DimDateColumnConfig.' - - if self.column_name_factory is not None: - new_cols: dict[str, Column] = {} - for k, v in col_dict.values(): - new_cols[k] = Column(self.column_name_factory( - v['name']), v['include'], v['sort_index']) - self.columns = DimCalendarMonthColumns(**new_cols) - - -@dataclass(frozen=True) -class DimFiscalMonthConfig: - table_schema: str = 'dbo' - table_name: str = 'DimFiscalMonth' - columns: DimFiscalMonthColumns = DimFiscalMonthColumns() - column_name_factory: Callable[[str], str] = None - - def __post_init__(self): - col_dict = asdict(self.columns) - sort_keys = [v['sort_index'] - for v in col_dict.values()] - distinct_sort_keys = set(sort_keys) - assert len(sort_keys) == len( - distinct_sort_keys), 'there was a duplicate sort key in the column definitions for DimFiscalMonthColumnConfig.' - - if self.column_name_factory is not None: - new_cols: dict[str, Column] = {} - for k, v in col_dict.values(): - new_cols[k] = Column(self.column_name_factory( - v['name']), v['include'], v['sort_index']) - self.columns = DimCalendarMonthColumns(**new_cols) - - -@dataclass(frozen=True) -class DimCalendarMonthConfig: - table_schema: str = 'dbo' - table_name: str = 'DimCalendarMonth' - columns: DimCalendarMonthColumns = DimCalendarMonthColumns() - column_name_factory: Callable[[str], str] = None - - def __post_init__(self): - col_dict = asdict(self.columns) - sort_keys = [v['sort_index'] - for v in col_dict.values()] - distinct_sort_keys = set(sort_keys) - assert len(sort_keys) == len( - distinct_sort_keys), 'there was a duplicate sort key in the column definitions for DimCalendarMonthColumnConfig.' - - if self.column_name_factory is not None: - new_cols: dict[str, Column] = {} - for k, v in col_dict.values(): - new_cols[k] = Column(self.column_name_factory( - v['name']), v['include'], v['sort_index']) - self.columns = DimCalendarMonthColumns(**new_cols) - - -@dataclass -class ScriptGeneratorConfig: - outdir_base: Path = Path('../output') - date_range: DateRange = DateRange() - fiscal_config: FiscalConfig = FiscalConfig() - time_zone: str = "Mountain Standard Time" - holiday_config: HolidayConfig = HolidayConfig() - dim_date_config: DimDateConfig = DimDateConfig() - dim_fiscal_month_config: DimFiscalMonthConfig = DimFiscalMonthConfig() - dim_calendar_month_config: DimCalendarMonthConfig = DimCalendarMonthConfig() - - -class ScriptGenerator(ABC): - @abstractmethod - def __init__(self, config: ScriptGeneratorConfig = ScriptGeneratorConfig()): - pass - - @abstractmethod - def add_generator_specific_config(self, config: object) -> None: - pass - - @abstractmethod - def generate_scripts(self) -> None: - pass diff --git a/generate/script_generator_factory.py b/generate/script_generator_factory.py deleted file mode 100644 index 67a62d0..0000000 --- a/generate/script_generator_factory.py +++ /dev/null @@ -1,17 +0,0 @@ -from enum import Enum, auto - - -class Language(Enum): - TSQL = auto() - - -class ScriptGeneratorFactory(): - def __init__(self, language: Language): - self.script_generators = { - Language.TSQL: '' - } - - generator = self.script_generators.get(language) - if generator is None: - raise NotImplementedError( - 'The provided language does not have an implemented ScriptGenerator.') diff --git a/src/awesome-date-dimension/.venv/bin/Activate.ps1 b/src/awesome-date-dimension/.venv/bin/Activate.ps1 new file mode 100644 index 0000000..2fb3852 --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/Activate.ps1 @@ -0,0 +1,241 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/src/awesome-date-dimension/.venv/bin/activate b/src/awesome-date-dimension/.venv/bin/activate new file mode 100644 index 0000000..3fc859f --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/activate @@ -0,0 +1,66 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null + fi + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV="/home/elliottjohnson/src/repos/awesome-date-dimension/generate/.venv" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="(.venv) ${PS1:-}" + export PS1 +fi + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null +fi diff --git a/src/awesome-date-dimension/.venv/bin/activate.csh b/src/awesome-date-dimension/.venv/bin/activate.csh new file mode 100644 index 0000000..4b5688c --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/activate.csh @@ -0,0 +1,25 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. +# Created by Davide Di Blasi . +# Ported to Python 3.3 venv by Andrew Svetlov + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "/home/elliottjohnson/src/repos/awesome-date-dimension/generate/.venv" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/bin:$PATH" + + +set _OLD_VIRTUAL_PROMPT="$prompt" + +if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then + set prompt = "(.venv) $prompt" +endif + +alias pydoc python -m pydoc + +rehash diff --git a/src/awesome-date-dimension/.venv/bin/activate.fish b/src/awesome-date-dimension/.venv/bin/activate.fish new file mode 100644 index 0000000..c0038f1 --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/activate.fish @@ -0,0 +1,64 @@ +# This file must be used with "source /bin/activate.fish" *from fish* +# (https://fishshell.com/); you cannot run it directly. + +function deactivate -d "Exit virtual environment and return to normal shell environment" + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + functions -e fish_prompt + set -e _OLD_FISH_PROMPT_OVERRIDE + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end + + set -e VIRTUAL_ENV + if test "$argv[1]" != "nondestructive" + # Self-destruct! + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "/home/elliottjohnson/src/repos/awesome-date-dimension/generate/.venv" + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/bin" $PATH + +# Unset PYTHONHOME if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # fish uses a function instead of an env var to generate the prompt. + + # Save the current fish_prompt function as the function _old_fish_prompt. + functions -c fish_prompt _old_fish_prompt + + # With the original prompt function renamed, we can override with our own. + function fish_prompt + # Save the return status of the last command. + set -l old_status $status + + # Output the venv prompt; color taken from the blue of the Python logo. + printf "%s%s%s" (set_color 4B8BBE) "(.venv) " (set_color normal) + + # Restore the return status of the previous command. + echo "exit $old_status" | . + # Output the original/"old" prompt. + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" +end diff --git a/src/awesome-date-dimension/.venv/bin/easy_install b/src/awesome-date-dimension/.venv/bin/easy_install new file mode 100755 index 0000000..0d332c1 --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/easy_install @@ -0,0 +1,8 @@ +#!/home/elliottjohnson/src/repos/awesome-date-dimension/generate/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from setuptools.command.easy_install import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/src/awesome-date-dimension/.venv/bin/easy_install-3.9 b/src/awesome-date-dimension/.venv/bin/easy_install-3.9 new file mode 100755 index 0000000..0d332c1 --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/easy_install-3.9 @@ -0,0 +1,8 @@ +#!/home/elliottjohnson/src/repos/awesome-date-dimension/generate/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from setuptools.command.easy_install import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/src/awesome-date-dimension/.venv/bin/pip b/src/awesome-date-dimension/.venv/bin/pip new file mode 100755 index 0000000..5ae0c35 --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/pip @@ -0,0 +1,8 @@ +#!/home/elliottjohnson/src/repos/awesome-date-dimension/generate/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/src/awesome-date-dimension/.venv/bin/pip3 b/src/awesome-date-dimension/.venv/bin/pip3 new file mode 100755 index 0000000..5ae0c35 --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/pip3 @@ -0,0 +1,8 @@ +#!/home/elliottjohnson/src/repos/awesome-date-dimension/generate/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/src/awesome-date-dimension/.venv/bin/pip3.9 b/src/awesome-date-dimension/.venv/bin/pip3.9 new file mode 100755 index 0000000..5ae0c35 --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/pip3.9 @@ -0,0 +1,8 @@ +#!/home/elliottjohnson/src/repos/awesome-date-dimension/generate/.venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/src/awesome-date-dimension/.venv/bin/python b/src/awesome-date-dimension/.venv/bin/python new file mode 120000 index 0000000..b8a0adb --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/python @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/src/awesome-date-dimension/.venv/bin/python3 b/src/awesome-date-dimension/.venv/bin/python3 new file mode 120000 index 0000000..ae65fda --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/python3 @@ -0,0 +1 @@ +/usr/bin/python3 \ No newline at end of file diff --git a/src/awesome-date-dimension/.venv/bin/python3.9 b/src/awesome-date-dimension/.venv/bin/python3.9 new file mode 120000 index 0000000..b8a0adb --- /dev/null +++ b/src/awesome-date-dimension/.venv/bin/python3.9 @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/__pycache__/easy_install.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/__pycache__/easy_install.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2fe551d955b90f11f83a3bcb19b2f86ba421060c GIT binary patch literal 345 zcmYk0ze>bF5XN_ts6o6Z5H#4OFk4s&A~qH_7TTp**6eUuZ~u|mJBgr;Pva}4wX(Oe za-tSDFyHVEAHNy3SnM;Z{^d)(()^gsc4cI)sPTkEvz7tZe3cDHI@7t$T;ArKLH@=# z)5Sfjcb*UL*1k$TRM!f}8;?m@TXn%X<@Hob>6GzOeiDw=d@5#pTNl%wlsa@$&JnL1 zNZB4Eq;*UoSZw|Q4G>hCKkASZ_w-ap2KVU@Mq1rKttK6x|Lc2itYPN9H;Wa1--U#$>|B4 KKPj@3AMhWUR%Lhq literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/easy_install.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/easy_install.py new file mode 100644 index 0000000..d87e984 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/easy_install.py @@ -0,0 +1,5 @@ +"""Run the EasyInstall command""" + +if __name__ == '__main__': + from setuptools.command.easy_install import main + main() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/INSTALLER b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/LICENSE.txt b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/LICENSE.txt new file mode 100644 index 0000000..75eb0fd --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2020 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/METADATA b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/METADATA new file mode 100644 index 0000000..f7e5e81 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/METADATA @@ -0,0 +1,94 @@ +Metadata-Version: 2.1 +Name: pip +Version: 20.3.4 +Summary: The PyPA recommended tool for installing Python packages. +Home-page: https://pip.pypa.io/ +Author: The pip developers +Author-email: distutils-sig@python.org +License: MIT +Project-URL: Documentation, https://pip.pypa.io +Project-URL: Source, https://github.com/pypa/pip +Project-URL: Changelog, https://pip.pypa.io/en/stable/news/ +Keywords: distutils easy_install egg setuptools wheel virtualenv +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Topic :: Software Development :: Build Tools +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.* + +pip - The Python Package Installer +================================== + +.. image:: https://img.shields.io/pypi/v/pip.svg + :target: https://pypi.org/project/pip/ + +.. image:: https://readthedocs.org/projects/pip/badge/?version=latest + :target: https://pip.pypa.io/en/latest + +pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes. + +Please take a look at our documentation for how to install and use pip: + +* `Installation`_ +* `Usage`_ + +We release updates regularly, with a new version every 3 months. Find more details in our documentation: + +* `Release notes`_ +* `Release process`_ + +In pip 20.3, we've `made a big improvement to the heart of pip`_; `learn more`_. We want your input, so `sign up for our user experience research studies`_ to help us do it right. + +**Note**: pip 21.0, in January 2021, will remove Python 2 support, per pip's `Python 2 support policy`_. Please migrate to Python 3. + +If you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms: + +* `Issue tracking`_ +* `Discourse channel`_ +* `User IRC`_ + +If you want to get involved head over to GitHub to get the source code, look at our development documentation and feel free to jump on the developer mailing lists and chat rooms: + +* `GitHub page`_ +* `Development documentation`_ +* `Development mailing list`_ +* `Development IRC`_ + +Code of Conduct +--------------- + +Everyone interacting in the pip project's codebases, issue trackers, chat +rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_. + +.. _package installer: https://packaging.python.org/guides/tool-recommendations/ +.. _Python Package Index: https://pypi.org +.. _Installation: https://pip.pypa.io/en/stable/installing.html +.. _Usage: https://pip.pypa.io/en/stable/ +.. _Release notes: https://pip.pypa.io/en/stable/news.html +.. _Release process: https://pip.pypa.io/en/latest/development/release-process/ +.. _GitHub page: https://github.com/pypa/pip +.. _Development documentation: https://pip.pypa.io/en/latest/development +.. _made a big improvement to the heart of pip: https://pyfound.blogspot.com/2020/11/pip-20-3-new-resolver.html +.. _learn more: https://pip.pypa.io/en/latest/user_guide/#changes-to-the-pip-dependency-resolver-in-20-3-2020 +.. _sign up for our user experience research studies: https://pyfound.blogspot.com/2020/03/new-pip-resolver-to-roll-out-this-year.html +.. _Python 2 support policy: https://pip.pypa.io/en/latest/development/release-process/#python-2-support +.. _Issue tracking: https://github.com/pypa/pip/issues +.. _Discourse channel: https://discuss.python.org/c/packaging +.. _Development mailing list: https://mail.python.org/mailman3/lists/distutils-sig.python.org/ +.. _User IRC: https://webchat.freenode.net/?channels=%23pypa +.. _Development IRC: https://webchat.freenode.net/?channels=%23pypa-dev +.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md + + diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/RECORD b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/RECORD new file mode 100644 index 0000000..7cf3342 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/RECORD @@ -0,0 +1,284 @@ +../../../bin/pip,sha256=ggaoAvOvEA4E-lAuKML_7PahOCJd4SqWQEF7AowdXhg,285 +../../../bin/pip3,sha256=ggaoAvOvEA4E-lAuKML_7PahOCJd4SqWQEF7AowdXhg,285 +../../../bin/pip3.9,sha256=ggaoAvOvEA4E-lAuKML_7PahOCJd4SqWQEF7AowdXhg,285 +pip-20.3.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip-20.3.4.dist-info/LICENSE.txt,sha256=gdAS_gPyTUkBTvvgoNNlG9Mv1KFDTig6W1JdeMD2Efg,1090 +pip-20.3.4.dist-info/METADATA,sha256=NrQymkcD8Kl04ckwQXiv2W-ZCeORlee9lZ0RlurDR-o,4304 +pip-20.3.4.dist-info/RECORD,, +pip-20.3.4.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip-20.3.4.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +pip-20.3.4.dist-info/entry_points.txt,sha256=5ExSa1s54zSPNA_1epJn5SX06786S8k5YHwskMvVYzw,125 +pip-20.3.4.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip/__init__.py,sha256=dUUDS2wGpUgaxc_qko944J7JopSJIz53d0FM7Eml96k,455 +pip/__main__.py,sha256=bqCAM1cj1HwHCDx3WJa-LJxOBXimGxE8OjBqAvnhVg0,911 +pip/__pycache__/__init__.cpython-39.pyc,, +pip/__pycache__/__main__.cpython-39.pyc,, +pip/_internal/__init__.py,sha256=TeXyNeKLd7EETjf3lJAGSY1Db-dYA6a_xCLHWUkEmXA,495 +pip/_internal/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/__pycache__/build_env.cpython-39.pyc,, +pip/_internal/__pycache__/cache.cpython-39.pyc,, +pip/_internal/__pycache__/configuration.cpython-39.pyc,, +pip/_internal/__pycache__/exceptions.cpython-39.pyc,, +pip/_internal/__pycache__/locations.cpython-39.pyc,, +pip/_internal/__pycache__/main.cpython-39.pyc,, +pip/_internal/__pycache__/pyproject.cpython-39.pyc,, +pip/_internal/__pycache__/self_outdated_check.cpython-39.pyc,, +pip/_internal/__pycache__/wheel_builder.cpython-39.pyc,, +pip/_internal/build_env.py,sha256=5PdJVlRvDe-fmGfc_wqOWtQ9Ad9gm2Elwfy2V5aVuio,8089 +pip/_internal/cache.py,sha256=HDTjGrm57Fl-vuojIcL17744KRCl66uuNXaAmwA8HLQ,12249 +pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132 +pip/_internal/cli/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/cli/__pycache__/autocompletion.cpython-39.pyc,, +pip/_internal/cli/__pycache__/base_command.cpython-39.pyc,, +pip/_internal/cli/__pycache__/cmdoptions.cpython-39.pyc,, +pip/_internal/cli/__pycache__/command_context.cpython-39.pyc,, +pip/_internal/cli/__pycache__/main.cpython-39.pyc,, +pip/_internal/cli/__pycache__/main_parser.cpython-39.pyc,, +pip/_internal/cli/__pycache__/parser.cpython-39.pyc,, +pip/_internal/cli/__pycache__/progress_bars.cpython-39.pyc,, +pip/_internal/cli/__pycache__/req_command.cpython-39.pyc,, +pip/_internal/cli/__pycache__/spinners.cpython-39.pyc,, +pip/_internal/cli/__pycache__/status_codes.cpython-39.pyc,, +pip/_internal/cli/autocompletion.py,sha256=ekGNtcDI0p7rFVc-7s4T9Tbss4Jgb7vsB649XJIblRg,6547 +pip/_internal/cli/base_command.py,sha256=duI7mshtryhdmzI9GeHGqssTZM4UkZW0IT5pX3SYqtA,9337 +pip/_internal/cli/cmdoptions.py,sha256=biNkTbqoY13QHo0BxnjndJFrQmzFSrEiR-5PKX30rWY,28617 +pip/_internal/cli/command_context.py,sha256=k1VHqTCeYjQ0b3tyqiUToA3An5FxpQmo5rb-9AHJ6VY,975 +pip/_internal/cli/main.py,sha256=Hxc9dZyW3xiDsYZX-_J2cGXT5DWNLNn_Y7o9oUme-Ec,2616 +pip/_internal/cli/main_parser.py,sha256=QSUbu5dPZ3pxsmChno8eH16kZxAcUkGy8YcCG_eeGrc,2830 +pip/_internal/cli/parser.py,sha256=ne2OH7B3xSeGPUelZkRQ38Tv9hqyl__sgyNiP3P55-U,10388 +pip/_internal/cli/progress_bars.py,sha256=J1zykt2LI4gbBeXorfYRmYV5FgXhcW4x3r6xE_a7Z7c,9121 +pip/_internal/cli/req_command.py,sha256=_WNGkkvnuP210DcZXWRUzJ8wMYNNQQ2Nw9mGOnHCHS4,16455 +pip/_internal/cli/spinners.py,sha256=GUQWNPnBD1CTRHxxumvUwodHovIvofMBu-bkaSaUnQY,5509 +pip/_internal/cli/status_codes.py,sha256=F6uDG6Gj7RNKQJUDnd87QKqI16Us-t-B0wPF_4QMpWc,156 +pip/_internal/commands/__init__.py,sha256=30max1NT-jWYrzAKwioPuUgD75EKubqLkBhHYmeZQH8,4101 +pip/_internal/commands/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/commands/__pycache__/cache.cpython-39.pyc,, +pip/_internal/commands/__pycache__/check.cpython-39.pyc,, +pip/_internal/commands/__pycache__/completion.cpython-39.pyc,, +pip/_internal/commands/__pycache__/configuration.cpython-39.pyc,, +pip/_internal/commands/__pycache__/debug.cpython-39.pyc,, +pip/_internal/commands/__pycache__/download.cpython-39.pyc,, +pip/_internal/commands/__pycache__/freeze.cpython-39.pyc,, +pip/_internal/commands/__pycache__/hash.cpython-39.pyc,, +pip/_internal/commands/__pycache__/help.cpython-39.pyc,, +pip/_internal/commands/__pycache__/install.cpython-39.pyc,, +pip/_internal/commands/__pycache__/list.cpython-39.pyc,, +pip/_internal/commands/__pycache__/search.cpython-39.pyc,, +pip/_internal/commands/__pycache__/show.cpython-39.pyc,, +pip/_internal/commands/__pycache__/uninstall.cpython-39.pyc,, +pip/_internal/commands/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/commands/cache.py,sha256=m7T9C6jB7fmNozyG24J1LkeTsoyfyIUYg_5otImUq64,7555 +pip/_internal/commands/check.py,sha256=NijmAIKljW3kY-V0QLMT7VttuEDtDroQa5qrfy4B-1I,1677 +pip/_internal/commands/completion.py,sha256=SFurXIoVZgXMhD-rPwyftjD2dtaOosIgBbHbCJ4Bnmo,3081 +pip/_internal/commands/configuration.py,sha256=i4uMbWcK-PW1VLY7f6eKklh7qO1Jnsvqvqe4cY6Uj4Y,9327 +pip/_internal/commands/debug.py,sha256=A54tXwZIEefYoOYlHvu-QbVyfNDqN00cHWkCe_6DdCU,8193 +pip/_internal/commands/download.py,sha256=NGk_sEGui-Id-1jki2FzbcTA4HZKEVbnImENnHGw8is,4919 +pip/_internal/commands/freeze.py,sha256=BcB1CYWMK95dE2SAkuk7aAhenv-pMVRfQQZ0_W8oKNc,3888 +pip/_internal/commands/hash.py,sha256=v2nYCiEsEI9nEam1p6GwdG8xyj5gFv-4WrqvNexKmeY,1843 +pip/_internal/commands/help.py,sha256=ofk4ez1AaR16kha-w4DLuWOi_B82wxU_2aT2VnHM8cg,1294 +pip/_internal/commands/install.py,sha256=L5depJz54VvwxCFV0_b9f1F_o4sKP9QR0dKIFH1ocL4,28449 +pip/_internal/commands/list.py,sha256=ymQtkUi4lbi8KfEABQ7kVAW5GqrDczp_f7QwpNrIUu0,11616 +pip/_internal/commands/search.py,sha256=YtTJydvon5CVZ5OYAvof495HyghFfMQkkUberJjYm1c,6033 +pip/_internal/commands/show.py,sha256=zk9FZqNPZ5Q4dGXnKrKdk3PaLPsWOHOwoFWGbMzhoKA,6996 +pip/_internal/commands/uninstall.py,sha256=Ys8hwFsg0kvvGtLGYG3ibL5BKvURhlSlCX50ZQ-hsHk,3311 +pip/_internal/commands/wheel.py,sha256=xvUMV9v_Qjwtip_4y1CWSTDVUdxa4dd4DY1PwtkXUxI,6802 +pip/_internal/configuration.py,sha256=B57qs7H0cGj8OPHQ8feeAzF8q333Wbdgd63pp1CtScM,13904 +pip/_internal/distributions/__init__.py,sha256=ECBUW5Gtu9TjJwyFLvim-i6kUMYVuikNh9I5asL6tbA,959 +pip/_internal/distributions/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/distributions/__pycache__/base.cpython-39.pyc,, +pip/_internal/distributions/__pycache__/installed.cpython-39.pyc,, +pip/_internal/distributions/__pycache__/sdist.cpython-39.pyc,, +pip/_internal/distributions/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/distributions/base.py,sha256=rGDUfzALQQN-9vkrcbCl7bhGMQbQ-BdHLWW6xWJObQs,1426 +pip/_internal/distributions/installed.py,sha256=aUtTvTcnVQSEts20D0Z0ifHnfT-fwMA-SXoqAq5pR58,761 +pip/_internal/distributions/sdist.py,sha256=UvAp42AhjJwa0x-QM72GptF5k_Y7KXhEjm0owTrskG4,4087 +pip/_internal/distributions/wheel.py,sha256=lePMBDS_ptPq1NI7n-GQYbFdDn8RdCbXoZ1PagrqvW8,1295 +pip/_internal/exceptions.py,sha256=8_7M9CgtGmTHHwgvpT8Mg8iDli7DfIMoIDfIvpdXUSY,13003 +pip/_internal/index/__init__.py,sha256=vpt-JeTZefh8a-FC22ZeBSXFVbuBcXSGiILhQZJaNpQ,30 +pip/_internal/index/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/index/__pycache__/collector.cpython-39.pyc,, +pip/_internal/index/__pycache__/package_finder.cpython-39.pyc,, +pip/_internal/index/collector.py,sha256=gZ_9wP_AmiIS8TVlpzHOKZvQsZAXUwCmC4Tg12Uz7LE,22070 +pip/_internal/index/package_finder.py,sha256=l8bLOqUbTZuqt9js7lzqTTWfKzwErOsXiYE3tfJF0Mk,37454 +pip/_internal/locations.py,sha256=MEkFeloQEtkH2EgMbpAI2wHFDXVFV299pw_b1nCGYIM,6870 +pip/_internal/main.py,sha256=LqoUFbyaZAZ1wZ0xSZ6wIIx9-m1JoSnSDztWnjR_pMo,437 +pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63 +pip/_internal/models/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/models/__pycache__/candidate.cpython-39.pyc,, +pip/_internal/models/__pycache__/direct_url.cpython-39.pyc,, +pip/_internal/models/__pycache__/format_control.cpython-39.pyc,, +pip/_internal/models/__pycache__/index.cpython-39.pyc,, +pip/_internal/models/__pycache__/link.cpython-39.pyc,, +pip/_internal/models/__pycache__/scheme.cpython-39.pyc,, +pip/_internal/models/__pycache__/search_scope.cpython-39.pyc,, +pip/_internal/models/__pycache__/selection_prefs.cpython-39.pyc,, +pip/_internal/models/__pycache__/target_python.cpython-39.pyc,, +pip/_internal/models/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/models/candidate.py,sha256=GmprVP8YD1kXg4VlREolYjC_fqwLl7LfeCN-ZBSNNig,1196 +pip/_internal/models/direct_url.py,sha256=ZE07jfJmU_AlLgYOkuFup7kgsZP5k8BRewB8YXp50mc,6884 +pip/_internal/models/format_control.py,sha256=YFi9CrJrfpEkuS2DOCtrWqYudrho1BHaBSwT8KexxH8,2823 +pip/_internal/models/index.py,sha256=carvxxaT7mJyoEkptaECHUZiNaA6R5NrsGF55zawNn8,1161 +pip/_internal/models/link.py,sha256=BywYuw790dC1zvSFij8-Cm4QZfmUcupe6xSAmk3i8CM,7471 +pip/_internal/models/scheme.py,sha256=EhPkT_6G0Md84JTLSVopYsp5H_K6BREYmFvU8H6wMK8,778 +pip/_internal/models/search_scope.py,sha256=Lum0mY4_pdR9DDBy6HV5xHGIMPp_kU8vMsqYKFHZip4,4751 +pip/_internal/models/selection_prefs.py,sha256=1lS2d6nbrMrjWgRuwdl05tnGChjtDijKjG4XCbnuLmc,2045 +pip/_internal/models/target_python.py,sha256=PK8GMs15pSUGCG18RgTGmvxvYE8-M5WKnudl4CikTYM,4070 +pip/_internal/models/wheel.py,sha256=FTfzVb4WIbfIehxhdlAVvCil_MQ0-W44oyN56cE6NHc,2772 +pip/_internal/network/__init__.py,sha256=jf6Tt5nV_7zkARBrKojIXItgejvoegVJVKUbhAa5Ioc,50 +pip/_internal/network/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/network/__pycache__/auth.cpython-39.pyc,, +pip/_internal/network/__pycache__/cache.cpython-39.pyc,, +pip/_internal/network/__pycache__/download.cpython-39.pyc,, +pip/_internal/network/__pycache__/lazy_wheel.cpython-39.pyc,, +pip/_internal/network/__pycache__/session.cpython-39.pyc,, +pip/_internal/network/__pycache__/utils.cpython-39.pyc,, +pip/_internal/network/__pycache__/xmlrpc.cpython-39.pyc,, +pip/_internal/network/auth.py,sha256=ntH7kjy1f6OI0O8s8RncqhyjwiiNkMChJVFB9PInP08,11652 +pip/_internal/network/cache.py,sha256=6rpBfrrzr9SaBy7_AM1EUH1pSFYq1pXCftMqk-1kkQQ,2329 +pip/_internal/network/download.py,sha256=mcmjWRKFOwdL6niizxm0ACv9tdf06TOYBK_xY4l_3c4,6401 +pip/_internal/network/lazy_wheel.py,sha256=o8DD4VooJvZJ2SfBsZDI4i85eONCITQKLydfklNroh0,8121 +pip/_internal/network/session.py,sha256=doOFU1lep6MjHBS_H1AVmRzcwEs7zcXbJtsfu7Xcgy0,15449 +pip/_internal/network/utils.py,sha256=ZPHg7u6DEcg2EvILIdPECnvPLp21OPHxNVmeXfMy-n0,4172 +pip/_internal/network/xmlrpc.py,sha256=4GnaQBJBKycuyWStRYUi93kmv70XootLfxOymAsP4SM,1883 +pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/operations/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/operations/__pycache__/check.cpython-39.pyc,, +pip/_internal/operations/__pycache__/freeze.cpython-39.pyc,, +pip/_internal/operations/__pycache__/prepare.cpython-39.pyc,, +pip/_internal/operations/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/operations/build/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/operations/build/__pycache__/metadata.cpython-39.pyc,, +pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-39.pyc,, +pip/_internal/operations/build/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-39.pyc,, +pip/_internal/operations/build/metadata.py,sha256=lXcRhnnN2-f49dYBNf1_NLkHZ-s-4OPV7tCOyJJmZ94,1255 +pip/_internal/operations/build/metadata_legacy.py,sha256=VgzBTk8naIO8-8N_ifEYF7ZAxWUDhphWVIaVlZ2FqYM,2011 +pip/_internal/operations/build/wheel.py,sha256=Ya0i8_uzfssdN2vorOVzNJYbAYVTLUnSZimCFdP4F7w,1466 +pip/_internal/operations/build/wheel_legacy.py,sha256=9CnTpc25Agvl9MnMgrVnHUWTlJ3um8aV4m9dbGdGHi0,3347 +pip/_internal/operations/check.py,sha256=EPNWcQyUSc3_pa_6Npv_mI5sXZ5zqRrmk0M67YViDIY,5216 +pip/_internal/operations/freeze.py,sha256=35mnNtUYhwYb_Lioo1RxHEgD7Eqm3KUqOOJ6RQQT_7Y,10411 +pip/_internal/operations/install/__init__.py,sha256=mX7hyD2GNBO2mFGokDQ30r_GXv7Y_PLdtxcUv144e-s,51 +pip/_internal/operations/install/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/operations/install/__pycache__/editable_legacy.cpython-39.pyc,, +pip/_internal/operations/install/__pycache__/legacy.cpython-39.pyc,, +pip/_internal/operations/install/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/operations/install/editable_legacy.py,sha256=rJ_xs2qtDUjpY2-n6eYlVyZiNoKbOtZXZrYrcnIELt4,1488 +pip/_internal/operations/install/legacy.py,sha256=zu3Gw54dgHtluyW5n8j5qKcAScidQXJvqB8fb0oLB-4,4281 +pip/_internal/operations/install/wheel.py,sha256=ENg_QbLbBnwYiPt1lzFIrQGu2QhkECxKm9_dTaaz5TU,31247 +pip/_internal/operations/prepare.py,sha256=-MKVSMKGYpqJ0y6fa1gq3eDvSKhR0ZLXZVlzaC_TVNo,22460 +pip/_internal/pyproject.py,sha256=DoQzvtOh5_wCPpU8E-J3IDCOKHvJw_SIY_gI8ih4I58,7400 +pip/_internal/req/__init__.py,sha256=s-E5Vxxqqpcs7xfY5gY69oHogsWJ4sLbnUiDoWmkHOU,3133 +pip/_internal/req/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/req/__pycache__/constructors.cpython-39.pyc,, +pip/_internal/req/__pycache__/req_file.cpython-39.pyc,, +pip/_internal/req/__pycache__/req_install.cpython-39.pyc,, +pip/_internal/req/__pycache__/req_set.cpython-39.pyc,, +pip/_internal/req/__pycache__/req_tracker.cpython-39.pyc,, +pip/_internal/req/__pycache__/req_uninstall.cpython-39.pyc,, +pip/_internal/req/constructors.py,sha256=0pLw8q5kozJyAUfFNCHGC3Y1acQV7FxuD6f-fVmrOMo,16135 +pip/_internal/req/req_file.py,sha256=f62QFxszUwN1q14Z_YZ3GdYm8mUCe2WoD0r8sDebQoE,18594 +pip/_internal/req/req_install.py,sha256=1d1QqpMV-xgGkNTF4j1guPNDV4_SxPbaFrvAvQthcrk,33803 +pip/_internal/req/req_set.py,sha256=csA7N4VelGpf-ovyFQRaxR9XTeAk2j9kiZHO6SIDxW0,7887 +pip/_internal/req/req_tracker.py,sha256=fVl3Pgl3yl12rFBQICYpy3StxWxD3j5pDWrHo8QmP7g,4691 +pip/_internal/req/req_uninstall.py,sha256=vuT3vX3zab3d8Gh-p1AgoDhpKU1P3OVyuC8a_57Es4U,23771 +pip/_internal/resolution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/resolution/__pycache__/base.cpython-39.pyc,, +pip/_internal/resolution/base.py,sha256=MemTQyKXiVrtdxsGzuI7QqBd7Ek0wNHvCoe3ZLZO4_A,683 +pip/_internal/resolution/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/legacy/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/resolution/legacy/__pycache__/resolver.cpython-39.pyc,, +pip/_internal/resolution/legacy/resolver.py,sha256=4aLvLZt0_BPHLaROEl9IjEhza9CZia8PLHlvZfMUMoQ,18234 +pip/_internal/resolution/resolvelib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/base.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/base.py,sha256=Kw8tB9Q7bYlJPIZmR4bGGRruk4SU9io5dnzshRVRvI4,5061 +pip/_internal/resolution/resolvelib/candidates.py,sha256=WNQUFRfJOokXCdpbTMadg9KcL2PXmhwnoXMwD6-E2Vo,20083 +pip/_internal/resolution/resolvelib/factory.py,sha256=ovOeMdAC2vhsZZLZbMqnisZaoBDlF8d64fJdpVCSMto,18946 +pip/_internal/resolution/resolvelib/found_candidates.py,sha256=_o9lCikecM_61kgl5xCKAByv_haREFlrc1qRoyVB9ts,3773 +pip/_internal/resolution/resolvelib/provider.py,sha256=bFS1-xUV9Pz1DefrDNfFaSlBjM785ftzoJi_fXbzdig,7339 +pip/_internal/resolution/resolvelib/reporter.py,sha256=dw4K2w0m7HEgxFF3r60voTrFDDPyhBLN8rzw4cQXaoo,2857 +pip/_internal/resolution/resolvelib/requirements.py,sha256=sps2y82iZtBdjPHZ16Ej9A4KdI7_8YC9R9nhAo1abyA,5969 +pip/_internal/resolution/resolvelib/resolver.py,sha256=ZHXXMwLkSUXfs0LG7gVK1IuIqNZlORNrwXjBmBVmDN4,11707 +pip/_internal/self_outdated_check.py,sha256=cVPuBaP89nm8Qdf_vVdXZxwtt8ebm4tL8fcStPl3dU8,6745 +pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/utils/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/utils/__pycache__/appdirs.cpython-39.pyc,, +pip/_internal/utils/__pycache__/compat.cpython-39.pyc,, +pip/_internal/utils/__pycache__/compatibility_tags.cpython-39.pyc,, +pip/_internal/utils/__pycache__/datetime.cpython-39.pyc,, +pip/_internal/utils/__pycache__/deprecation.cpython-39.pyc,, +pip/_internal/utils/__pycache__/direct_url_helpers.cpython-39.pyc,, +pip/_internal/utils/__pycache__/distutils_args.cpython-39.pyc,, +pip/_internal/utils/__pycache__/encoding.cpython-39.pyc,, +pip/_internal/utils/__pycache__/entrypoints.cpython-39.pyc,, +pip/_internal/utils/__pycache__/filesystem.cpython-39.pyc,, +pip/_internal/utils/__pycache__/filetypes.cpython-39.pyc,, +pip/_internal/utils/__pycache__/glibc.cpython-39.pyc,, +pip/_internal/utils/__pycache__/hashes.cpython-39.pyc,, +pip/_internal/utils/__pycache__/inject_securetransport.cpython-39.pyc,, +pip/_internal/utils/__pycache__/logging.cpython-39.pyc,, +pip/_internal/utils/__pycache__/misc.cpython-39.pyc,, +pip/_internal/utils/__pycache__/models.cpython-39.pyc,, +pip/_internal/utils/__pycache__/packaging.cpython-39.pyc,, +pip/_internal/utils/__pycache__/parallel.cpython-39.pyc,, +pip/_internal/utils/__pycache__/pkg_resources.cpython-39.pyc,, +pip/_internal/utils/__pycache__/setuptools_build.cpython-39.pyc,, +pip/_internal/utils/__pycache__/subprocess.cpython-39.pyc,, +pip/_internal/utils/__pycache__/temp_dir.cpython-39.pyc,, +pip/_internal/utils/__pycache__/typing.cpython-39.pyc,, +pip/_internal/utils/__pycache__/unpacking.cpython-39.pyc,, +pip/_internal/utils/__pycache__/urls.cpython-39.pyc,, +pip/_internal/utils/__pycache__/virtualenv.cpython-39.pyc,, +pip/_internal/utils/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/utils/appdirs.py,sha256=RZzUG-Bkh2b-miX0DSZ3v703_-bgK-v0PfWCCjwVE9g,1349 +pip/_internal/utils/compat.py,sha256=JoSVxgMmV8ZZTwXrPRGgQk1EyomJZM3gb-nolCxslko,9489 +pip/_internal/utils/compatibility_tags.py,sha256=2frtUos4dHeHKV38noN_rs_u8VTehy4eMxqyEYVtZtY,5690 +pip/_internal/utils/datetime.py,sha256=KL-vIdGU9JIpGB5NYkmwXWkH-G_2mvvABlmRtoSZsao,295 +pip/_internal/utils/deprecation.py,sha256=pBnNogoA4UGTxa_JDnPXBRRYpKMbExAhXpBwAwklOBs,3318 +pip/_internal/utils/direct_url_helpers.py,sha256=Q0c-z0iuQx_D1FeRlu7nZD5h2nt4QSow23B26PQrp0s,4146 +pip/_internal/utils/distutils_args.py,sha256=a56mblNxk9BGifbpEETG61mmBrqhjtjRkJ4HYn-oOEE,1350 +pip/_internal/utils/encoding.py,sha256=53p3H36wc49dyr0EgtBbdHdvH4Dr-Egl0zc_J0sweqc,1284 +pip/_internal/utils/entrypoints.py,sha256=yvizXdrIeK44OI-J2YBIcojfrXxGO9oe8JCxBvMdxIk,1152 +pip/_internal/utils/filesystem.py,sha256=-fU3XteCAIJwf_9FvCZU7vhywvt3nuf_cqkCdwgy1Y8,6943 +pip/_internal/utils/filetypes.py,sha256=QvagL0Vm4tMZ_qyFqopZWpaDHEM3Q6FyF35vfOY-CJg,847 +pip/_internal/utils/glibc.py,sha256=LOeNGgawCKS-4ke9fii78fwXD73dtNav3uxz1Bf-Ab8,3297 +pip/_internal/utils/hashes.py,sha256=ydFGVhDk0Nj2JyaTKzUHRe5iBnbgh4KG-HFtXbr_xmo,5297 +pip/_internal/utils/inject_securetransport.py,sha256=M17ZlFVY66ApgeASVjKKLKNz0LAfk-SyU0HZ4ZB6MmI,810 +pip/_internal/utils/logging.py,sha256=YIfuDUEkmdn9cIRQ_Ec8rgXs1m5nOwDECtZqM4CBH5U,13093 +pip/_internal/utils/misc.py,sha256=BpnBnDkypGrWZHIBFU0g9IYsO6rglX8sQVnUselvY-8,28698 +pip/_internal/utils/models.py,sha256=HqiBVtTbW_b_Umvj2fjhDWOHo2RKhPwSz4iAYkQZ688,1201 +pip/_internal/utils/packaging.py,sha256=KOLx30EXZobHKTaA8khLNqEMb986DeaCcgDhZHaw6RY,3036 +pip/_internal/utils/parallel.py,sha256=d6wJWWHnPOcwO4pyL7pv08DG3l_5YtHzIBdhHhI3epw,3404 +pip/_internal/utils/pkg_resources.py,sha256=ZX-k7V5q_aNWyDse92nN7orN1aCpRLsaxzpkBZ1XKzU,1254 +pip/_internal/utils/setuptools_build.py,sha256=E1KswI7wfNnCDE5R6G8c9ZbByENpu7NqocjY26PCQDw,5058 +pip/_internal/utils/subprocess.py,sha256=nihl4bmnTpU4wQPjJESYNdTrS2-5T1SC00kM2JZx2gI,10866 +pip/_internal/utils/temp_dir.py,sha256=cmFpYI_5VDeXUsGvia9jUNh8XEKXYvpGlIi_iq2MRVU,8845 +pip/_internal/utils/typing.py,sha256=xkYwOeHlf4zsHXBDC4310HtEqwhQcYXFPq2h35Tcrl0,1401 +pip/_internal/utils/unpacking.py,sha256=YFAckhqqvmehA8Kan5vd3b1kN_9TafqmOk4b-yz4fho,9488 +pip/_internal/utils/urls.py,sha256=q2rw1kMiiig_XZcoyJSsWMJQqYw-2wUmrMoST4mCW_I,1527 +pip/_internal/utils/virtualenv.py,sha256=fNGrRp-8QmNL5OzXajBd-z7PbwOsx1XY6G-AVMAhfso,3706 +pip/_internal/utils/wheel.py,sha256=wFzn3h8GqYvgsyWPZtUyn0Rb3MJzmtyP3owMOhKnmL0,7303 +pip/_internal/vcs/__init__.py,sha256=viJxJRqRE_mVScum85bgQIXAd6o0ozFt18VpC-qIJrM,617 +pip/_internal/vcs/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/vcs/__pycache__/bazaar.cpython-39.pyc,, +pip/_internal/vcs/__pycache__/git.cpython-39.pyc,, +pip/_internal/vcs/__pycache__/mercurial.cpython-39.pyc,, +pip/_internal/vcs/__pycache__/subversion.cpython-39.pyc,, +pip/_internal/vcs/__pycache__/versioncontrol.cpython-39.pyc,, +pip/_internal/vcs/bazaar.py,sha256=ivvSGrrYbryp7TU9Vn8hkJddcYCRfvKzqPx05o_G71k,4016 +pip/_internal/vcs/git.py,sha256=_RePK_kSTbjzsQCn5Dv-alIxoLPJu2GkhFjehd20bpY,15893 +pip/_internal/vcs/mercurial.py,sha256=EcevyquppjAS-y1CrDxcFPwAid0d9gEGhxVp_DUJSZ0,5564 +pip/_internal/vcs/subversion.py,sha256=OajehInnYm8T9BVD-yeaIjN5hG_F9ZSJqFlt5OZqEuk,12558 +pip/_internal/vcs/versioncontrol.py,sha256=_FmtOI-jxJl5vthUgedDgNJG-OHQK_6SLoEIvTNIES4,23767 +pip/_internal/wheel_builder.py,sha256=krzl8rpbRqlXDb3W---hqTPn09msEprUmpqpG2Bcys4,11889 +pip/_vendor/__init__.py,sha256=9W5OMec7OR5iGiLkewOfrMJ9Wt-FjLAezVSYzwHc2ds,5156 +pip/_vendor/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/vendor.txt,sha256=B9Th9JlPs1TDBKZkMFiB54aghp1RFZHuJ5djqKyl6a0,437 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/REQUESTED b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/WHEEL b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/WHEEL new file mode 100644 index 0000000..ef99c6c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/entry_points.txt b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/entry_points.txt new file mode 100644 index 0000000..9609f72 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/entry_points.txt @@ -0,0 +1,5 @@ +[console_scripts] +pip = pip._internal.cli.main:main +pip3 = pip._internal.cli.main:main +pip3.9 = pip._internal.cli.main:main + diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/top_level.txt b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/top_level.txt new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip-20.3.4.dist-info/top_level.txt @@ -0,0 +1 @@ +pip diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__init__.py new file mode 100644 index 0000000..f9bd063 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__init__.py @@ -0,0 +1,18 @@ +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional + + +__version__ = "20.3.4" + + +def main(args=None): + # type: (Optional[List[str]]) -> int + """This is an internal API only meant for use by pip's own console scripts. + + For additional details, see https://github.com/pypa/pip/issues/7498. + """ + from pip._internal.utils.entrypoints import _wrapper + + return _wrapper(args) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__main__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__main__.py new file mode 100644 index 0000000..7c2505f --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__main__.py @@ -0,0 +1,26 @@ +from __future__ import absolute_import + +import os +import sys + +# Remove '' and current working directory from the first entry +# of sys.path, if present to avoid using current directory +# in pip commands check, freeze, install, list and show, +# when invoked as python -m pip +if sys.path[0] in ('', os.getcwd()): + sys.path.pop(0) + +# If we are running from a wheel, add the wheel to sys.path +# This allows the usage python pip-*.whl/pip install pip-*.whl +if __package__ == '': + # __file__ is pip-*.whl/pip/__main__.py + # first dirname call strips of '/__main__.py', second strips off '/pip' + # Resulting path is the name of the wheel itself + # Add that to sys.path so we can import pip + path = os.path.dirname(os.path.dirname(__file__)) + sys.path.insert(0, path) + +from pip._internal.cli.main import main as _main # isort:skip # noqa + +if __name__ == '__main__': + sys.exit(_main()) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a0f019bc00b35ba947efd25b6ea5ce2de8c2228e GIT binary patch literal 693 zcmZuvO>Yx15VdzVX$Y-^P)}U&4Ml=AYAeyA3V|X%Dj-yR9Gc6@S(~h3*S0)PqOIB! z{0Dvmzl8s=S5DkHablbT>VeUEfyZ-Xz_@o#=dpv$# zynZ*C98I2%k}i9pA#{URE@*2+ecIo-oA2g(lM=Q3iv)LZjd8&?CQ0#L)NzhF&gdEW zMDeEd^vl~y1H(@krcF>D8QG)bBW6wAvPKCL*n8{Q0u-CI%xQNEm|YoGS_8IL3`(zE zfP6S)7*DWONU1NRF{y&kHQZ*P6stmTaG&$J4%K3om$u=qb%G-&*8mFz{NCQde!eF1 z(F~4YP^`RgPI)wb6Fc+bugZK8kUCc;_|{phg73vMI3VHY7vL-L1FZdWyt0krs;;#S z;e)MEyW!wV?v=B^#YzD-+>s(+(v32Jv*mMTl*ba!m&z=8t!Jn>RMza~2OKo^I#GTU zb5tHp6sS#yqR3s_WsT4#J`>0=k^W}lBO1}kXrsIFKO>=a+RT0YXz#l9>nQEw7!{S^jeywzX4u&yn_G$ literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__pycache__/__main__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/__pycache__/__main__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07a986179198bbeaba782fe14acf123eb1cff30f GIT binary patch literal 537 zcmYjNJ&zMH5VgG@x8#yLiqlE_gcPg`DkOB`7tqjcWBKAq)^}dpvYi|$sAwpV_zOwN zUvf)DPesLebx4fl8PD^3Gf$SQ)q-G*pMT5m6(K)M^M5qhyvGy2VNyg!i%!Uznp?m53W(=#3FnYT~`>NA^X z*XD9s4l7h$sRmVFp*mf|>dQPyv5#ck{z6A&P4l(9kIw892t9ch(uZ8odXn1aPKZ*4 zSij5*A-4Op4l{gh@|eqej9GEChsje*k;nM&EOPOrx`J`nNo4 int + """This is preserved for old console scripts that may still be referencing + it. + + For additional details, see https://github.com/pypa/pip/issues/7498. + """ + from pip._internal.utils.entrypoints import _wrapper + + return _wrapper(args) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..339280e3790af85a716f0c06f1a6bef061bbd779 GIT binary patch literal 742 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/cache.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/cache.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8fe36a45b1b5eee416d347925e93fc07225a362b GIT binary patch literal 9134 zcmbtZ&2t>bb)T=Don0(IfCRrOc|=+SSEd#$*_GG~Et`TMQZ@yvC^`%`a>j$5#_oW# zGpp`dg4ir7DN~M5N^(h6ate^jA*{+FRjKkR$NU4iC3DS5_ncTIGr#v{_6r0RI^M16 z>7MD2*ZsbJ?~Ok{U)AvI?ER1bU#pt--_)4?S!nzamwHRrv_NZWfgTu<-qiVSG!4F+ zO_T3d)56`1N?p5YcgxMPPW`RO=~kK*u9u=}cdj|dbvvqc=bQ6fFGmaAW6fh+ccR7a zQgf+$ym_44mFPrwxw*{sYIL%Ds(DJ+#IpQ%%sm&K?w)C$>7H$#?Vf9%>z;3(?_OwL z;J!7`@mljWuFprWcfZm62F98Du6W}>Z(a-*f@7a+%}ckmU@=(wTnm=OH=mfzH_<*G zoIv}8coXf*XfFpR(LO0IqrHOmso*r)r@8+Xw9f=*(LT%l>w)o!RzEjbTJu{S;eO=D zep_@!oL0Z2gWaeb*BW9mWGAMdJQ7lcNnF>nrIsHjaoF;sa3HuR9xi_v zKf;6Hen*JtgD?^_1D;!V!uTQXC4PZr=I@Da@BL7UR+`A&Y(7OZ2&MNhj01&^$3J@T z@dIz|_WIh7y}Li%*!Xbc7M{-a{IuhxiPx7=y_A_Z^&W~{l~tAK`O?SsRaO(R>PzAIsuhM=iEni~v$jZvB*z)qg+tag&FSQSweCTY5zbYjf6s$^?bie92t z{T-pu;qAarQG^f#;_Yf%!~%qg)y5+cKU&3_tG(T{lf>U{d~a2S=-cyK4=SrHYna6c`3HKH?rhjJ9P#>crH0ZBJy4y5=rENi@ z1M_nSx@!d`XhbQngEH=R-~<)i%Rx1m!`%sL!94DjLUXFW(k!hx2SzPsC6;#o7hwBM zuxnGL(r=}1EAo|c-*$U4c@zdhxlBGdmkVWxCtHbhaX7xaC6lfjL55YeT6K%xb>d$) zABMfk>+U@$l}wV9WFSR7Kaj%%Fe`-7Yvs~--33v}<~B5ehRsN7L1UU=?QWQkCn5qi zLr519xhcZ9?MmSXIhikC*pH%QM+9C@fV%GPbi!7Lb_seEt-b}7RTI)7(n&uGAmE7< zjhW@ItS|w)E3O|0?uttKvL(=vf`=z@wCfh@xiATRq3S%o#j;Rvyo5V(pDy)BC{itj z@;x#3jRQ^BhPu3%n%mZXX$Zwr7k{MvLLchAD}grDJbP%MEDueT4pi0X7<<-G+jjOV zLn!LddT6M7G$J5%H8-F)Ok-x}gx9NCN%ea|%5P%f%<&+{Vd{CAk*LffLz9(41!>7D z%tqpHwlK@P?AW0r%}V{4%ws9Dl!&(ERZK14rlLWMEO=}kM+|tXXBE$5IrKbMS$UEA zUO@qer>O-Lnz5iS>s8&>ZNt$A3oOiy5w$I{U!xz{v9T@tb2Ntfw$|474BX)q`?~xN zYEUh%!KwwuzD4ioY1<&{28U$g8R~mxTH3dV=6?A=gVl2mG#oFvQ0te*Sq(KPWKn}s z7BxH2sn)jkO2ZP4y*&7Q#@Ke>8IY7^xNbYVO+_Ou^+Ukn%RD@C*lCM83fDo7%MMOL3U2Q zPE*vzwVX=#8wV`kNzrzAK64l1z>KJt}^mitnPRm*w}UPKPW107Z6kdfZqTrY5*V z!%EC(`7RCn0Tnl?c#jHZ=Y*#xkL2keqNiF$p*dABvj!EfmaAZ?Lo7Z2H7sq>E=Io! zD#XtB_Q3N8}HHCv*7tQxS!9;unEW83mA6lAl>P?sa% zK~&@odU)oA5rsb0D-#}Or^bjDvopZS6@MPjy*Me9GAkGUGOOZw5E6J&`Py(4#e-}v z*H-v1Cvzm1<84hbV8O3IB6qBS}B(_9Bh~M6fPpBA*(QLpemd+`zEE!KG+! z%^19%Q}MF%eI;^qD84axcMPY;8tVf1F!ac+c;Etic9k2(Z1RcmQ+8dFI!OW%hiU#X zp8XxJoMvlq`Xw~aKofEeN1a_xte+FBT%S=P5$aD9>4sY%))kK-h3cxC0F%j`Pyros z%)k(945xa)p>Tai?Wb-{SdrCcq;dh^rH5z&crNwZ>d>Y$6D;}r@usVT%6QZD8i5^h zX#hJ_&+8^ZKcafg^FHhQQSqkic|pd-Jwu5hx%K61at!Og@7)K3eYfPYl);0XjSLXm;lzH4lk&8^aB$Z z3fAI#m0^1Ca4ciQ`ysfKc0>r7Y4Ny((KySkr{DXd1`%41J20(It9Pn*4MQ)tO##MeF z&qn04+k1~XG368TNj83sYfOGsAJktU|CKDp@3MJ<5`Dj{R{CL+*Vg&vH)cmTuBSx{LO9_A?w=q_8*oYRVT`*f0LUxrSCp2Ogp`hwV z1u`Cwq@`jvN)jYR+HSu$o++QE6Q&T+@x%MT(iC(-dIf`Q3?f^JWwA!FG|UnjyKcvS z1Y#p>E~Lywk<}T`75BTFNc3EF6%7Vj$JT-*UO~`|pw;gp^i1#F54dqs3NcC)6XZ{o{j0QG?ivb|+9 zF{^@79HDk(jsI<|c8kD~2n+siwVQEzgb^yZ)@UA@43H4PpsEew_ENxnfO>+62o{E= z0|U@5{?ypB_sWA>Y7A|>b?$5NDN9Su-5=@jpSt!y`^koZ<&_r5Ho#h?p0{@bS|x>^Vu z-pO#YPtemP--ywT`l2L&kUPUN)yOMk76*!Ul(gGIB5@}+`)%a>MvgiMqf12_`G!C| z_Ml9ei9(XKmvdCia=TugU;z1m-Z!bZOT|x6WL4f&j#Vpp9X2E@aW&Ju!v>mM_J80~ z6!2(eLYEd&3n-u0OanNx2DG_=wqe*`StSFKWN;5dH@-5S+Ya?#&!y2nBai?Xy%ut6!1fT371*Vn*rg9E1jZMXw=z>Jg(e}>Wm6coU51l3a^Qem6;j5TMXB&?u^lCw03*9z zmy`8D-H{Halcc8E()!1@*FW;^-(Fw8jakT#&4Vw!;dqE4sDD+knMOWyMIngAH`py={LAIFHHQE^yCH3!g*^yq;3== zPdFPG$n%BjW?O zb`6j6sQwYvCOf!DO*%__3o4S@C0ieyn9wjjmkl8ILkGi5m`uhsp0SS^7idNz*wH1m zUpNdBB>Jh_C?<#T|4WjyI#h9h3t4qa6aMqQ^n1!Z#B27VFK7q@3*RNj2>`(-kYka1 z{iwn#BqsbItC3rh=-#z)-8UKR6` zt=>xd9P>1BXWfL#hg=f|^apUT$I# zl12>ccTmsu%SR0{6kFXqf5&2tN4&M-5iwRCp?UcHm)pA>@Ke}7I5FYPSg>BOGPI2~ zT&jiwwuHU&0sP-c!XML$Y>PPh!pPkL$eS@16Kg-74bfM?@BvwQRxdhlw%d|~?IjGek^I5;pTiF2Pch;L#H-g) z(dLl!qyJZS$ot+9zHvN zbT44-NHM_9&Tx;>7v_d|+!FkWU*&-N?Cfi#vXIMZke6UMo#kYVhZpa62>eNc?b(Id z33%nk7(tQtd9&MOV>S03j4)_S67}95Un)f9mE$6AAgO$gqAb28|P-K^8 zsVT^v{pKi-Q_l(v#T^baa;~>&j!X2$&c7vdN-a-1_2?ae3g+CD__5I-dyzRe@+{!H qV0rEoE##v4Z!AI#DJH1tsG)A@7YsZxs-{z3{4=excz1DevHHL1|MkQG literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/configuration.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/configuration.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59ff8a1840d6b01e71abe7bc61da1469eb8ab05d GIT binary patch literal 10877 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 QGhaA?Xi#*ZY^eQz0Q4yST>t<8 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/exceptions.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/exceptions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..31044213619e403a9601749bf8f5ff02da56bb19 GIT binary patch literal 14966 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 U`Lb@B+LPL^)E^M^2K3$k0M#BR2><{9 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/main.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/main.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d260b3eb39d1f47abfce2cc386d6c994c50d259 GIT binary patch literal 679 zcmZuvJC74F5Vm(W528B>Au1Z&MuK$#5*$J&q==V*fOr&_CUVwuS%cTMJWftQcNP2& zdVT|BRN|0s%yuQosjNE=_7zi@Nch44a^2FhLr`6`;I#_uziLYZNmly1;OL5>*HgiT6#) ztmnohh(xxL8eg%D6gg zwpBI;v;kHGY_M0v{A$L0I___8{EtrB1UhQWe{kFX=j5jpbAw&+j?pE!l2eBdJFiz3 P4)fWtPq0^1{A&3Z(1*ES literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/pyproject.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/pyproject.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..55e050c2194a5d977bfbb604fd1ca1aac75f45c3 GIT binary patch literal 3782 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 S<}zD0%h;T-9LH&PD*pp}9z1&h literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e67ac387858f8b9cdf5b3bdb82fa713b03a2f6ff GIT binary patch literal 4613 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f6a979a9f7464f0f6b23786e64755319c8addd5b GIT binary patch literal 8655 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 B0B`^R literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/build_env.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/build_env.py new file mode 100644 index 0000000..a08e63c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/build_env.py @@ -0,0 +1,242 @@ +"""Build Environment used for isolation during sdist building +""" + +import logging +import os +import sys +import textwrap +from collections import OrderedDict +from distutils.sysconfig import get_python_lib +from sysconfig import get_paths + +from pip._vendor.pkg_resources import Requirement, VersionConflict, WorkingSet + +from pip import __file__ as pip_location +from pip._internal.cli.spinners import open_spinner +from pip._internal.utils.subprocess import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from types import TracebackType + from typing import Iterable, List, Optional, Set, Tuple, Type + + from pip._internal.index.package_finder import PackageFinder + +logger = logging.getLogger(__name__) + + +class _Prefix: + + def __init__(self, path): + # type: (str) -> None + self.path = path + self.setup = False + self.bin_dir = get_paths( + 'nt' if os.name == 'nt' else 'posix_prefix', + vars={'base': path, 'platbase': path} + )['scripts'] + # Note: prefer distutils' sysconfig to get the + # library paths so PyPy is correctly supported. + purelib = get_python_lib(plat_specific=False, prefix=path) + platlib = get_python_lib(plat_specific=True, prefix=path) + if purelib == platlib: + self.lib_dirs = [purelib] + else: + self.lib_dirs = [purelib, platlib] + + +class BuildEnvironment(object): + """Creates and manages an isolated environment to install build deps + """ + + def __init__(self): + # type: () -> None + temp_dir = TempDirectory( + kind=tempdir_kinds.BUILD_ENV, globally_managed=True + ) + + self._prefixes = OrderedDict(( + (name, _Prefix(os.path.join(temp_dir.path, name))) + for name in ('normal', 'overlay') + )) + + self._bin_dirs = [] # type: List[str] + self._lib_dirs = [] # type: List[str] + for prefix in reversed(list(self._prefixes.values())): + self._bin_dirs.append(prefix.bin_dir) + self._lib_dirs.extend(prefix.lib_dirs) + + # Customize site to: + # - ensure .pth files are honored + # - prevent access to system site packages + system_sites = { + os.path.normcase(site) for site in ( + get_python_lib(plat_specific=False), + get_python_lib(plat_specific=True), + ) + } + self._site_dir = os.path.join(temp_dir.path, 'site') + if not os.path.exists(self._site_dir): + os.mkdir(self._site_dir) + with open(os.path.join(self._site_dir, 'sitecustomize.py'), 'w') as fp: + fp.write(textwrap.dedent( + ''' + import os, site, sys + + # First, drop system-sites related paths. + original_sys_path = sys.path[:] + known_paths = set() + for path in {system_sites!r}: + site.addsitedir(path, known_paths=known_paths) + system_paths = set( + os.path.normcase(path) + for path in sys.path[len(original_sys_path):] + ) + original_sys_path = [ + path for path in original_sys_path + if os.path.normcase(path) not in system_paths + ] + sys.path = original_sys_path + + # Second, add lib directories. + # ensuring .pth file are processed. + for path in {lib_dirs!r}: + assert not path in sys.path + site.addsitedir(path) + ''' + ).format(system_sites=system_sites, lib_dirs=self._lib_dirs)) + + def __enter__(self): + # type: () -> None + self._save_env = { + name: os.environ.get(name, None) + for name in ('PATH', 'PYTHONNOUSERSITE', 'PYTHONPATH') + } + + path = self._bin_dirs[:] + old_path = self._save_env['PATH'] + if old_path: + path.extend(old_path.split(os.pathsep)) + + pythonpath = [self._site_dir] + + os.environ.update({ + 'PATH': os.pathsep.join(path), + 'PYTHONNOUSERSITE': '1', + 'PYTHONPATH': os.pathsep.join(pythonpath), + }) + + def __exit__( + self, + exc_type, # type: Optional[Type[BaseException]] + exc_val, # type: Optional[BaseException] + exc_tb # type: Optional[TracebackType] + ): + # type: (...) -> None + for varname, old_value in self._save_env.items(): + if old_value is None: + os.environ.pop(varname, None) + else: + os.environ[varname] = old_value + + def check_requirements(self, reqs): + # type: (Iterable[str]) -> Tuple[Set[Tuple[str, str]], Set[str]] + """Return 2 sets: + - conflicting requirements: set of (installed, wanted) reqs tuples + - missing requirements: set of reqs + """ + missing = set() + conflicting = set() + if reqs: + ws = WorkingSet(self._lib_dirs) + for req in reqs: + try: + if ws.find(Requirement.parse(req)) is None: + missing.add(req) + except VersionConflict as e: + conflicting.add((str(e.args[0].as_requirement()), + str(e.args[1]))) + return conflicting, missing + + def install_requirements( + self, + finder, # type: PackageFinder + requirements, # type: Iterable[str] + prefix_as_string, # type: str + message # type: str + ): + # type: (...) -> None + prefix = self._prefixes[prefix_as_string] + assert not prefix.setup + prefix.setup = True + if not requirements: + return + args = [ + sys.executable, os.path.dirname(pip_location), 'install', + '--ignore-installed', '--no-user', '--prefix', prefix.path, + '--no-warn-script-location', + ] # type: List[str] + if logger.getEffectiveLevel() <= logging.DEBUG: + args.append('-v') + for format_control in ('no_binary', 'only_binary'): + formats = getattr(finder.format_control, format_control) + args.extend(('--' + format_control.replace('_', '-'), + ','.join(sorted(formats or {':none:'})))) + + index_urls = finder.index_urls + if index_urls: + args.extend(['-i', index_urls[0]]) + for extra_index in index_urls[1:]: + args.extend(['--extra-index-url', extra_index]) + else: + args.append('--no-index') + for link in finder.find_links: + args.extend(['--find-links', link]) + + for host in finder.trusted_hosts: + args.extend(['--trusted-host', host]) + if finder.allow_all_prereleases: + args.append('--pre') + if finder.prefer_binary: + args.append('--prefer-binary') + args.append('--') + args.extend(requirements) + with open_spinner(message) as spinner: + call_subprocess(args, spinner=spinner) + + +class NoOpBuildEnvironment(BuildEnvironment): + """A no-op drop-in replacement for BuildEnvironment + """ + + def __init__(self): + # type: () -> None + pass + + def __enter__(self): + # type: () -> None + pass + + def __exit__( + self, + exc_type, # type: Optional[Type[BaseException]] + exc_val, # type: Optional[BaseException] + exc_tb # type: Optional[TracebackType] + ): + # type: (...) -> None + pass + + def cleanup(self): + # type: () -> None + pass + + def install_requirements( + self, + finder, # type: PackageFinder + requirements, # type: Iterable[str] + prefix_as_string, # type: str + message # type: str + ): + # type: (...) -> None + raise NotImplementedError() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cache.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cache.py new file mode 100644 index 0000000..def8dd6 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cache.py @@ -0,0 +1,346 @@ +"""Cache Management +""" + +import hashlib +import json +import logging +import os + +from pip._vendor.packaging.tags import interpreter_name, interpreter_version +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import InvalidWheelFilename +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.urls import path_to_url + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, List, Optional, Set + + from pip._vendor.packaging.tags import Tag + + from pip._internal.models.format_control import FormatControl + +logger = logging.getLogger(__name__) + + +def _hash_dict(d): + # type: (Dict[str, str]) -> str + """Return a stable sha224 of a dictionary.""" + s = json.dumps(d, sort_keys=True, separators=(",", ":"), ensure_ascii=True) + return hashlib.sha224(s.encode("ascii")).hexdigest() + + +class Cache(object): + """An abstract class - provides cache directories for data from links + + + :param cache_dir: The root of the cache. + :param format_control: An object of FormatControl class to limit + binaries being read from the cache. + :param allowed_formats: which formats of files the cache should store. + ('binary' and 'source' are the only allowed values) + """ + + def __init__(self, cache_dir, format_control, allowed_formats): + # type: (str, FormatControl, Set[str]) -> None + super(Cache, self).__init__() + assert not cache_dir or os.path.isabs(cache_dir) + self.cache_dir = cache_dir or None + self.format_control = format_control + self.allowed_formats = allowed_formats + + _valid_formats = {"source", "binary"} + assert self.allowed_formats.union(_valid_formats) == _valid_formats + + def _get_cache_path_parts_legacy(self, link): + # type: (Link) -> List[str] + """Get parts of part that must be os.path.joined with cache_dir + + Legacy cache key (pip < 20) for compatibility with older caches. + """ + + # We want to generate an url to use as our cache key, we don't want to + # just re-use the URL because it might have other items in the fragment + # and we don't care about those. + key_parts = [link.url_without_fragment] + if link.hash_name is not None and link.hash is not None: + key_parts.append("=".join([link.hash_name, link.hash])) + key_url = "#".join(key_parts) + + # Encode our key url with sha224, we'll use this because it has similar + # security properties to sha256, but with a shorter total output (and + # thus less secure). However the differences don't make a lot of + # difference for our use case here. + hashed = hashlib.sha224(key_url.encode()).hexdigest() + + # We want to nest the directories some to prevent having a ton of top + # level directories where we might run out of sub directories on some + # FS. + parts = [hashed[:2], hashed[2:4], hashed[4:6], hashed[6:]] + + return parts + + def _get_cache_path_parts(self, link): + # type: (Link) -> List[str] + """Get parts of part that must be os.path.joined with cache_dir + """ + + # We want to generate an url to use as our cache key, we don't want to + # just re-use the URL because it might have other items in the fragment + # and we don't care about those. + key_parts = {"url": link.url_without_fragment} + if link.hash_name is not None and link.hash is not None: + key_parts[link.hash_name] = link.hash + if link.subdirectory_fragment: + key_parts["subdirectory"] = link.subdirectory_fragment + + # Include interpreter name, major and minor version in cache key + # to cope with ill-behaved sdists that build a different wheel + # depending on the python version their setup.py is being run on, + # and don't encode the difference in compatibility tags. + # https://github.com/pypa/pip/issues/7296 + key_parts["interpreter_name"] = interpreter_name() + key_parts["interpreter_version"] = interpreter_version() + + # Encode our key url with sha224, we'll use this because it has similar + # security properties to sha256, but with a shorter total output (and + # thus less secure). However the differences don't make a lot of + # difference for our use case here. + hashed = _hash_dict(key_parts) + + # We want to nest the directories some to prevent having a ton of top + # level directories where we might run out of sub directories on some + # FS. + parts = [hashed[:2], hashed[2:4], hashed[4:6], hashed[6:]] + + return parts + + def _get_candidates(self, link, canonical_package_name): + # type: (Link, str) -> List[Any] + can_not_cache = ( + not self.cache_dir or + not canonical_package_name or + not link + ) + if can_not_cache: + return [] + + formats = self.format_control.get_allowed_formats( + canonical_package_name + ) + if not self.allowed_formats.intersection(formats): + return [] + + candidates = [] + path = self.get_path_for_link(link) + if os.path.isdir(path): + for candidate in os.listdir(path): + candidates.append((candidate, path)) + # TODO remove legacy path lookup in pip>=21 + legacy_path = self.get_path_for_link_legacy(link) + if os.path.isdir(legacy_path): + for candidate in os.listdir(legacy_path): + candidates.append((candidate, legacy_path)) + return candidates + + def get_path_for_link_legacy(self, link): + # type: (Link) -> str + raise NotImplementedError() + + def get_path_for_link(self, link): + # type: (Link) -> str + """Return a directory to store cached items in for link. + """ + raise NotImplementedError() + + def get( + self, + link, # type: Link + package_name, # type: Optional[str] + supported_tags, # type: List[Tag] + ): + # type: (...) -> Link + """Returns a link to a cached item if it exists, otherwise returns the + passed link. + """ + raise NotImplementedError() + + +class SimpleWheelCache(Cache): + """A cache of wheels for future installs. + """ + + def __init__(self, cache_dir, format_control): + # type: (str, FormatControl) -> None + super(SimpleWheelCache, self).__init__( + cache_dir, format_control, {"binary"} + ) + + def get_path_for_link_legacy(self, link): + # type: (Link) -> str + parts = self._get_cache_path_parts_legacy(link) + assert self.cache_dir + return os.path.join(self.cache_dir, "wheels", *parts) + + def get_path_for_link(self, link): + # type: (Link) -> str + """Return a directory to store cached wheels for link + + Because there are M wheels for any one sdist, we provide a directory + to cache them in, and then consult that directory when looking up + cache hits. + + We only insert things into the cache if they have plausible version + numbers, so that we don't contaminate the cache with things that were + not unique. E.g. ./package might have dozens of installs done for it + and build a version of 0.0...and if we built and cached a wheel, we'd + end up using the same wheel even if the source has been edited. + + :param link: The link of the sdist for which this will cache wheels. + """ + parts = self._get_cache_path_parts(link) + assert self.cache_dir + # Store wheels within the root cache_dir + return os.path.join(self.cache_dir, "wheels", *parts) + + def get( + self, + link, # type: Link + package_name, # type: Optional[str] + supported_tags, # type: List[Tag] + ): + # type: (...) -> Link + candidates = [] + + if not package_name: + return link + + canonical_package_name = canonicalize_name(package_name) + for wheel_name, wheel_dir in self._get_candidates( + link, canonical_package_name + ): + try: + wheel = Wheel(wheel_name) + except InvalidWheelFilename: + continue + if canonicalize_name(wheel.name) != canonical_package_name: + logger.debug( + "Ignoring cached wheel %s for %s as it " + "does not match the expected distribution name %s.", + wheel_name, link, package_name, + ) + continue + if not wheel.supported(supported_tags): + # Built for a different python/arch/etc + continue + candidates.append( + ( + wheel.support_index_min(supported_tags), + wheel_name, + wheel_dir, + ) + ) + + if not candidates: + return link + + _, wheel_name, wheel_dir = min(candidates) + return Link(path_to_url(os.path.join(wheel_dir, wheel_name))) + + +class EphemWheelCache(SimpleWheelCache): + """A SimpleWheelCache that creates it's own temporary cache directory + """ + + def __init__(self, format_control): + # type: (FormatControl) -> None + self._temp_dir = TempDirectory( + kind=tempdir_kinds.EPHEM_WHEEL_CACHE, + globally_managed=True, + ) + + super(EphemWheelCache, self).__init__( + self._temp_dir.path, format_control + ) + + +class CacheEntry(object): + def __init__( + self, + link, # type: Link + persistent, # type: bool + ): + self.link = link + self.persistent = persistent + + +class WheelCache(Cache): + """Wraps EphemWheelCache and SimpleWheelCache into a single Cache + + This Cache allows for gracefully degradation, using the ephem wheel cache + when a certain link is not found in the simple wheel cache first. + """ + + def __init__(self, cache_dir, format_control): + # type: (str, FormatControl) -> None + super(WheelCache, self).__init__( + cache_dir, format_control, {'binary'} + ) + self._wheel_cache = SimpleWheelCache(cache_dir, format_control) + self._ephem_cache = EphemWheelCache(format_control) + + def get_path_for_link_legacy(self, link): + # type: (Link) -> str + return self._wheel_cache.get_path_for_link_legacy(link) + + def get_path_for_link(self, link): + # type: (Link) -> str + return self._wheel_cache.get_path_for_link(link) + + def get_ephem_path_for_link(self, link): + # type: (Link) -> str + return self._ephem_cache.get_path_for_link(link) + + def get( + self, + link, # type: Link + package_name, # type: Optional[str] + supported_tags, # type: List[Tag] + ): + # type: (...) -> Link + cache_entry = self.get_cache_entry(link, package_name, supported_tags) + if cache_entry is None: + return link + return cache_entry.link + + def get_cache_entry( + self, + link, # type: Link + package_name, # type: Optional[str] + supported_tags, # type: List[Tag] + ): + # type: (...) -> Optional[CacheEntry] + """Returns a CacheEntry with a link to a cached item if it exists or + None. The cache entry indicates if the item was found in the persistent + or ephemeral cache. + """ + retval = self._wheel_cache.get( + link=link, + package_name=package_name, + supported_tags=supported_tags, + ) + if retval is not link: + return CacheEntry(retval, persistent=True) + + retval = self._ephem_cache.get( + link=link, + package_name=package_name, + supported_tags=supported_tags, + ) + if retval is not link: + return CacheEntry(retval, persistent=False) + + return None diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__init__.py new file mode 100644 index 0000000..e589bb9 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__init__.py @@ -0,0 +1,4 @@ +"""Subpackage containing all of pip's command line interface related code +""" + +# This file intentionally does not import submodules diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d3521ad2bae94a56325f4f60fc32363871accf5a GIT binary patch literal 300 zcmYjNF-}7<49)LCRjGH#hC1|nU_wHOjg6%nOOz(=|1OCWC23KSVB#`dsVhf-i3zu2 zz|ynz>?ixlc0QjeiShN@zDxZ)k^j*Nxf9f>B(ENo?^bFtdAVQh*4erzJD_%nn~$bUP28|-tV3Ne*oI!l9%m1W?s#F0PtKSRRVH%foPOS5Oc4P? zpw!wnja(B$Ee;CiRKY%D6~WTWuBE4lTuB52G8Sn;zenCfpf%(}8xvpk*HB5cf37Qt gNib(yYy-GJV1!aLrq74t^d=_13wV3_z?VS%0_Uz=#Q*>R literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d01db6b663128a1524e510a28f3b6968cd17d447 GIT binary patch literal 4979 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..133163538bf7bd4fe46689045a6a2872feef27f2 GIT binary patch literal 6887 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 OFO(7Wmrctk<^C5`&8VON literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2261835a30acc840f4e238f8b9d010125842683 GIT binary patch literal 20816 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 G+MfaWi*QQ- literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b350d9c46e09a8dfbe5d73f7d57b72e6fa68a482 GIT binary patch literal 1380 zcmZuw&1)1f6i+gV5cC9W2Hx9CF`#msbW(q+Z^sy@_DQ*1r;8Okh6OJlam%|e$&s8tdwS(Q4B z-%1S+E{oUzNpo4~6dr8I0_!Tn-i|DG!Yo}6t39(>7T0<=L!H9g3fcsH(_xiXAw&p$ zDB>(kvNTM_<(Y=ttM*hIBA$n(Js^b5Q;+UnIHrufY1aSM(+9l-EewGikS(Hu2jo4p z3~EUBZ-9h;K8qNA4i$a@y9;v!s4W(*5Pf|aq&U~cw+yukU)1|DyoMe)gW=sSQys9c zFjjQ}$?3mj5jfkPZ3Id*rbe8Ad6ZF~USj)8$K^GvmM~PA4CJw&eOUS|5X?>2xnWLU z*a7`YAv!wfI{#v`9f=j6mKefb09Cs%K?tu@xswXO($Vl0I#`0G@xv1qu>Fh2MSIk^ zk6QrbzssxRKXJakor1BqZPHBl%wCli8wxYF v-sI3g*N8>cM1sDpSFUf##MHiLLai%U_ujuXPW?9i@4D}8hSQ~stnK^(shm-r literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/main.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/main.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..791f7415d9a9f75c95a0adb4a633ff04c81432fb GIT binary patch literal 1484 zcmZuwOK&4Z5bo}IchnXVg{IRozw9UsWZoRs+FzKL0EE2&6yF z=Jw~n=5tu`Hy{*6h+;}O&PhbDksa(*F`JKEQbunUH@eBBB@Qr*k+RV42Ezr4(ZFYBwqaE6! zYqa?jj_y(C8`N)4d&eTn6EW!}RmHP3QCV5^SfRwEDzicj8n56jsE_q}awbbYRxHl) zsuXGnx@Iy~Wm@JHXNtkTRV6~Q7&LiOP*Ai}!4kOguO>LoszV`40oFCjD#2DUVcY%s z^!PMB`0DWBQGD|4aQJZeWuIvGD3eMDk1LZ|!c%PWx&D0MrX&ZjQ11?i7s`e}EpKX;-xtZPmJ1r_K@z4-wvn2(63GT=^?xOEZ{{sFXJm|LF+q9>VBM$5}I;cVL2-_M|oP!m(0;6~okj+{vC zCSr6cYT#XOXN6P==kZk{3h)r~ax?{@Pam9a6d${iB2Ui=!j$*^V$LObG2!b~YXf&-i!qBrE#9%}nYb&1qaD zIa^7Pt<(;CmTJs&?YhZ+N8(+$`S&zDFLM?$&a+afi}JjXWf4k|hJsb443jG+;lMrx zF!pJdvqD0Lg(Frl0jh9t$%@O6XJ=tGQRijx!QkUi!W;LiB>g@aF&S1_6~-_mOh99X zDbGTa?4X*6T}a?PSh5EMkpQ=yfcS*q4sPQvte#7NcgQ=i?CCxp_V4Rj9Mdw5W8H}3 zr(-o1ERF>M7ve4uKokIiT8K@fY8zD#k{H}1F@Pinw}uiPWDBNu|9{Nn8ry*tww`+X zKWA1`ELU~ddEE$@Gdq#ewn4PYfR!I=1TBsUeYmVpP9*!Zv$~j6L7abY2uroxPW+L_a6-opK<^I literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6bab4e2509e09da0387ccc92280cbc5f3063ff77 GIT binary patch literal 2271 zcmZWr&5ztP6px)uCX=0+{pj{<0TC6oFo(`mAn~PT1=_Z>qAV3{4-HgNHulbD*ZIKq z>{l}f*m6bU#(~2O;=+x;gg?MnPTV@hy0^$A8A% zIm`N8PfkA=CLcl*KR`#U&?1OnhC*cCIK=R_nVmVIgY=ri8krlqSu<>!d4qXbD{N(c z=$pCA=CXF!HsdDiWZkfv&4=@5?y-ezFX!AF5e^C6=_$>M|tTLll2A{Ua65(x`IoRfeal!ev`TFb`udv6RDPmR7N7rQWo>*WC?a^uh(ifI4`u>yw)qzGTNhD!2ZfJ z0$vP3dFj)KcOORUw{EO|5`F$)W8?P5$6(^zNrhC6`=gRkwUlrgOB(60qB<Ei#<1F|@DxF%8nEgUcZf)ncuy=jH)&6;>(((kZ;frznsh3A3f`h_g`jr+ z(cA0h=)%;9Q#sh@+ zYpBLZ#6zm)V?v^BC{|P}sTN?Qu9|Z4IHStZ-tH?aL6DD=$A*DU)IDh85_CgI$fK1n z@feLUv34w-BAqgwr0?-p4uph`g2&q9`)|H84j#`=7p3`D(HA2C2R|G``P_Pc<+37) zndsRH_pk9Yu!U-$w)w^4D%n%B(E(*FEu`EjwsTSB1HqF4r-180yiWxvTm^VS zmu58AI2sITPC1AM{XLrR4OqH4C=ca!k-yb{Zy-|8E#qVtG9(6&-vJyGaGb|%kg#-c z3Qhg;Q2DD2AP0vl*9JNt21VHY_vp%t=dZ|P1aS6w8jh&LIn zcNQh!pOPr%L%}`0-kdRl>$^xTX7Mhal`tCeVpOV59U_}e7j&WP8qXw-4udzec>@B@ zgmQL@G*@$kiiD?z-aSXPYT87*`^ud$2uPS~UxHr&Yg321dr40_(4B>5aACO^VdUuc zx9fG0hdsNCeA~5s?Ed39ZTt+bbZGiShJe4pK$Fjq3{}*50Gu|!XaRTaHu7=rf@($) zDUvAS*T9Hhg)UqKs`j5!wGULS*>T|odA~-op_*ZyI`^E;>~r;hcGPoT=s`m3Z=y-n z^UEWdGSSacpppi)VYXU%c9U919+vRoV-TjM71yac#W#~k iO*-YRW(65Bx~4HDwA``lq%EKY)Yc6{`fNz%YySZS27^HW literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/parser.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/parser.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2bef8446d917beae9571fbcafaf9b18b0cc36d30 GIT binary patch literal 9373 zcmbVS&vP3`cAlOY07DRjAc&GES+-}rT1#+Iplqw+ilSA?D|uz_x+q7s>;$#i$p}3J zhaAj+-3?KML08IjVtP}RIJJ98RgwZ-dvOk_%_Zkt^DoRPm7IJ_)#l`?*!f=1fC5Ow z`2lKrdU|@gU%!4ozV}-G!a~`=Z+-Va{9j!*jDMqt$)AmfTexJ3f*UP^Gj2w#Yqm^A zbt|%3mcH99Ti*+DFmx1lH(GaQ1+;mhKvSo>x9GcqOnm&h1&P^JrP% zRkT!t^LTy+&nI{d&o%V8fR<;`a+254QV*WR^K;yK*Jzv?Ed9urft&PHn8a?+7cvm8 z3{=1O6;^IESbD;LB$KGG0x#_L5}{VnHYb%($)hBR@ZiXPuO|X2QLo@d7b-IQ{=NGRGhMiy#A{)vFMOIXtxr9^Aw(kZ)yYnvJQav;82gbY!$E+? zMG6h#G& zuD$Mp1xkg1Sc$+2_i-Q|C1C72y18rPepDk~Yd$yI3^a~^L^w&^JzVk@3eJWmH*Xl+ z!ri`MC}Ypyg>wckE*WSkp@nUj8`jY1up#?`-8VwC|C;?dgVY!x)mi=OIgFE@?D|hU zqQmPYG9`Tz16}mL(AEDAQcI_eCFvR(xJ%adbK-|t52M`_9O>s4Eh2~_f z${N~xFoB!4coXkzZVs&jn8G0&6%Guc@Kv$*bCji#b71Ti^!MgyZdjn_1273fX^qN5 zTeHg^{CnBWfA?W*MC|%*JLz`)D>A^2VY9g#g;Kf6+SoSb+;shzyWK$fk728t<-=jF z(`Vhh^L5vS1&d(U*4)c-9af88EW1$>cc|7_c7tZ;x_kN3m9x`gqD*m)(q-qrEXS=*R5&DiU$nLo1i4g7>M>m`~?DO%{m?)Wq-gf|#dej|j}# ztSE@nVi?07t8`xZn}PHm`%yngOZnYL{nF7>;cgS&h+EVHGG$jV+pkmu5-hY{@^SJ|xgu21yr( zjI&KsRJi#r)vdE+wCvTibWb}YDV|5CfqA{GsT^xjX+7{cT+9*D(`v2|`RgCzTS+2s zK+SD7cwrXR)1ORHYvIchE=?_24bGtK#)v6%WRcQy^T0e{yXFwoH>|JJAC*Pad(CoVR;Ekezn z=3$?~eE9(lb>01NxBRu~x-i=fP@GnB15dNc)KS3`wJrQ!TI2y4{)Uy=rGh3TwYu^c zQ!6=#bdMil%*=KcY*zc$HV5u^FjaqYjHQJ!OW#Lj$i%7wQ#T+8d!{(U&0RCLxdo=O z5quul3)3{RU{DxXZ>z$ns99e)Fn1X*j!HxHr1}sxn3r&6elNAVei*0DZL%mam+AbS zr;JNkS-gzd2c-{pub06xEoTiUEv@?!-W;lw`HZv}k(PsB*csf#EBH#hO2suQh{t0d z&QI(NG}3<*L`Ma*p7U~|=T9+$Bvmj>8!A>bZL@4TW*v2K_r>qv?!+KdJSGJrFRsP5 zh6;G>Xzmb)h&$%0UhkAn6@y+FCC7GuA*VQd`w*jL8UH-d9GV0Vl?wrjynFgO?Ts`ly>M54vf5T|GeVp|8o^RTkZ_OZ;f z#$TFS_PY}%4QSJBUQKNh|1TNYQj+>?TeRmb-yjzQx6`{BV6@-jG6vUXEo)Mdnm3}P z?MLz^D&x<^@8MI-SCG9ZRN^IivNP?nN$td&Xi4W_0X(gY84-8UD2Ng*SsWEf%QM&# zo2^=tWURsd2ZT0;qe^c^2p0qtrLm@#{OnX7V~H$qGcTgY^&*%9IJfRDL8XZ-6`q!ZM>TL(bnC#)W6 z*QW^rNoE!1G@Aq_8KNGz!IK`$1!kwW-DTI0;9K#iO)WLKDskbrw=oLfiV#6t!MI~u z8cjoe5(#{fPx^W!6E}-nT#8#qrL6NYHnz%GR$pjXm+SCJ277)@=dHsN<$0bQo3}AsWa7>L=%_?d|t4tD%R_EKIHCX;m@oP?#zY3~WX>bbJ z#5+{{J{5YxS(vAkf&BZ*_1#X0kjx#&mCc5o)_l�Z@lJrVEJ%ES`Rnsntt*;v&e%H#N0F{zMSq z6lYPS1>Nt+E~ck4Bs?|pFVH;?=4xgcJ34srI4hbnKAiF@#BO5GZ5oX%H?aqfiT#Or zP6Lk(IHrfS43rGb4IL$IEs|4hn1dU41L6aTECm~|7-OwohFxe!{oI^TE&z5SV}+Zs zqPdE2c|PY3jUfIA)2Bs9GNOSow6Ks`Nm+Q5Atxrj^Dyl%iF_T|S|r$D#tSo;apa>_ z1PVt)m=g(3Pb57A9y@~Mbz*8Q*4kzL95421PO?*u>CBl-P+J?<)bG&r-$L_Kah{Qp zDe@9Tyr}asl#j{sGESbCnd4P({KPnAbWaOaX5t4j_Y2wb#%ZkW^{~BuXz)WNCk+0M z+g=aao4KveEbwGz3V0lO9F5MAa|lHeQ-;KkT*QN+{|N7RQ^HgSxO8^IK*(2NWhmC*nHgU7FhxSk z9{Uff_-X5;)y~@t`3GhUE-EBZM>b^z_Ta}906yX>)IKo& zkbIu~ksX(_`&HvAS|9<|>foih5&p_{bZeYj!n@;>Dq;glz`ixd!jWr2!DDV^8b zowq^tp0tnfFI~tc$^Fyc zpmKVIDuZJ226suv;7!hU~E+E@FF-S43=89NKG|{pgEvAG%27 z=y#~s@l6q<>OSwoS8NTo;&HrH>_o{UKN=LSLs_m*t%1~^MC4ssLmdVDj`6TeFI!MhF zc<`v-5ftr-@1a0noe-=h$P$Z?2N|{Lf&`vK!ZRZ?ogY6Q%3LXL5szu8Bm8myr*;1W zKFUClS%HtJQy9lgW`1MarddOpWYMA&&*0Vn2T!K}2Z=3N0a88ruLwsK(CWTPSasj@ zEM@NjY3`dNWDf5bpRfhQWTs=2eUyzoNe{Y?_}lQCAf;x5xfs z3AW~NByQS}&^?P8aqVS8{^qJ4kw!qTr~MbkGau>yFH`-iLrX0HU4JvQcySZ+i{EJ4 zN|Ut3f2(P7G)*_5mM4(nus$_DWuKaB7N6r~1jUwCY%3PJ@4W8&1zbrD&nIbx`)pLl zcQ)>)hCuA(Uhr=5bJkP5vRgp?H0pmG8oNc*&+G%%fj?%)9v1TBf?{@D5LZFt*?o$m ztpf`Y10W#Ha>LlVpd*4apBZWiI|%OXA?31f+`!7V{)uB3;m8OHEeyWU*g21^GF&(g z2Hfosv5(dqnT0?UFJ-Fv)X^R$wCH8-bery-gxoLymQu*)%3jb8;f2=`ry-K==mQl5 z2@3fh9aACSwstsB1_z{jnZT87GzaFDD~OxZGJ;4EcuF9fI-k|o5YY#N?uWai+Hpdd z4)lgR*LQ@6a3(o?TXvCJrc*Ob&Dsw7(ot9dfSg%}DBKL(9UMo*$+Anctmxrg4D#~I zRp3CWki=}Jg?7@7nC=(`8sCaN#7~HlaxNzIhi_gGUf;pN|~7hYa%n#VB!gS zA$dWDK4p);v@&Z(sp>4q({@eck+;zHTWZ&~{3om>r;r&uBp_ zNJjn~!9p*mE|ae5E6f5s)LVic=LKGw}@!C@u>5L%Yq_JU>;~ zA2EPPeJ2o!US%3@G*1Upgq%hdazqcWQL1DFGrv(qyRA+j0aAl0k71xs!q5Uojq1Qm zh>Z!*Zd73&V@(|#jt&O@>|W;3byShKT^!nE;YS{3JdHp6H5^fDL*U0M)Mw$7hKnp< zX1vC+3_@%fBJ5apkLFx1H(X9OlD^>~Vm5a>5u1oDPo-xN#3mwJ8KyHlML-B`TMVlR=t5w+%3cIyAt@~raAAWV z%#gO@BTc~+LZ-AzEpIQN0!h%}2{~8P0aOs203#o0Y09(b0}Dq6$hyqyV8PSJ96}N0 zMX7)}#Z&fWCj{B)ulOBwIkHyqIoh6~#pxIdiy17}WllZ2GHM}%+=+x9Dd(a2HjCM*b0bT|-^4Cw#~yZpEM)da0XALP P`D)p!zf*g@e)_)vu$r9; literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab57a986ec40b3b057a6a2b59e3ec32a31b164f6 GIT binary patch literal 7735 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 BA@=|P literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3145a195530b2d1140cbeaa12f2045126fb6dcd GIT binary patch literal 10586 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/autocompletion.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/autocompletion.py new file mode 100644 index 0000000..329de60 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/autocompletion.py @@ -0,0 +1,164 @@ +"""Logic that powers autocompletion installed by ``pip completion``. +""" + +import optparse +import os +import sys +from itertools import chain + +from pip._internal.cli.main_parser import create_main_parser +from pip._internal.commands import commands_dict, create_command +from pip._internal.utils.misc import get_installed_distributions +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Iterable, List, Optional + + +def autocomplete(): + # type: () -> None + """Entry Point for completion of main and subcommand options. + """ + # Don't complete if user hasn't sourced bash_completion file. + if 'PIP_AUTO_COMPLETE' not in os.environ: + return + cwords = os.environ['COMP_WORDS'].split()[1:] + cword = int(os.environ['COMP_CWORD']) + try: + current = cwords[cword - 1] + except IndexError: + current = '' + + parser = create_main_parser() + subcommands = list(commands_dict) + options = [] + + # subcommand + subcommand_name = None # type: Optional[str] + for word in cwords: + if word in subcommands: + subcommand_name = word + break + # subcommand options + if subcommand_name is not None: + # special case: 'help' subcommand has no options + if subcommand_name == 'help': + sys.exit(1) + # special case: list locally installed dists for show and uninstall + should_list_installed = ( + subcommand_name in ['show', 'uninstall'] and + not current.startswith('-') + ) + if should_list_installed: + installed = [] + lc = current.lower() + for dist in get_installed_distributions(local_only=True): + if dist.key.startswith(lc) and dist.key not in cwords[1:]: + installed.append(dist.key) + # if there are no dists installed, fall back to option completion + if installed: + for dist in installed: + print(dist) + sys.exit(1) + + subcommand = create_command(subcommand_name) + + for opt in subcommand.parser.option_list_all: + if opt.help != optparse.SUPPRESS_HELP: + for opt_str in opt._long_opts + opt._short_opts: + options.append((opt_str, opt.nargs)) + + # filter out previously specified options from available options + prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]] + options = [(x, v) for (x, v) in options if x not in prev_opts] + # filter options by current input + options = [(k, v) for k, v in options if k.startswith(current)] + # get completion type given cwords and available subcommand options + completion_type = get_path_completion_type( + cwords, cword, subcommand.parser.option_list_all, + ) + # get completion files and directories if ``completion_type`` is + # ````, ```` or ```` + if completion_type: + paths = auto_complete_paths(current, completion_type) + options = [(path, 0) for path in paths] + for option in options: + opt_label = option[0] + # append '=' to options which require args + if option[1] and option[0][:2] == "--": + opt_label += '=' + print(opt_label) + else: + # show main parser options only when necessary + + opts = [i.option_list for i in parser.option_groups] + opts.append(parser.option_list) + flattened_opts = chain.from_iterable(opts) + if current.startswith('-'): + for opt in flattened_opts: + if opt.help != optparse.SUPPRESS_HELP: + subcommands += opt._long_opts + opt._short_opts + else: + # get completion type given cwords and all available options + completion_type = get_path_completion_type(cwords, cword, + flattened_opts) + if completion_type: + subcommands = list(auto_complete_paths(current, + completion_type)) + + print(' '.join([x for x in subcommands if x.startswith(current)])) + sys.exit(1) + + +def get_path_completion_type(cwords, cword, opts): + # type: (List[str], int, Iterable[Any]) -> Optional[str] + """Get the type of path completion (``file``, ``dir``, ``path`` or None) + + :param cwords: same as the environmental variable ``COMP_WORDS`` + :param cword: same as the environmental variable ``COMP_CWORD`` + :param opts: The available options to check + :return: path completion type (``file``, ``dir``, ``path`` or None) + """ + if cword < 2 or not cwords[cword - 2].startswith('-'): + return None + for opt in opts: + if opt.help == optparse.SUPPRESS_HELP: + continue + for o in str(opt).split('/'): + if cwords[cword - 2].split('=')[0] == o: + if not opt.metavar or any( + x in ('path', 'file', 'dir') + for x in opt.metavar.split('/')): + return opt.metavar + return None + + +def auto_complete_paths(current, completion_type): + # type: (str, str) -> Iterable[str] + """If ``completion_type`` is ``file`` or ``path``, list all regular files + and directories starting with ``current``; otherwise only list directories + starting with ``current``. + + :param current: The word to be completed + :param completion_type: path completion type(`file`, `path` or `dir`)i + :return: A generator of regular files and/or directories + """ + directory, filename = os.path.split(current) + current_path = os.path.abspath(directory) + # Don't complete paths if they can't be accessed + if not os.access(current_path, os.R_OK): + return + filename = os.path.normcase(filename) + # list all files that start with ``filename`` + file_list = (x for x in os.listdir(current_path) + if os.path.normcase(x).startswith(filename)) + for f in file_list: + opt = os.path.join(current_path, f) + comp_file = os.path.normcase(os.path.join(directory, f)) + # complete regular files when there is not ```` after option + # complete directories when there is ````, ```` or + # ````after option + if completion_type != 'dir' and os.path.isfile(opt): + yield comp_file + elif os.path.isdir(opt): + yield os.path.join(comp_file, '') diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/base_command.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/base_command.py new file mode 100644 index 0000000..41e7dcf --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/base_command.py @@ -0,0 +1,260 @@ +"""Base Command class, and related routines""" + +from __future__ import absolute_import, print_function + +import logging +import logging.config +import optparse +import os +import platform +import sys +import traceback + +from pip._vendor.six import PY2 + +from pip._internal.cli import cmdoptions +from pip._internal.cli.command_context import CommandContextMixIn +from pip._internal.cli.parser import ConfigOptionParser, UpdatingDefaultsHelpFormatter +from pip._internal.cli.status_codes import ( + ERROR, + PREVIOUS_BUILD_DIR_ERROR, + UNKNOWN_ERROR, + VIRTUALENV_NOT_FOUND, +) +from pip._internal.exceptions import ( + BadCommand, + CommandError, + InstallationError, + NetworkConnectionError, + PreviousBuildDirError, + UninstallationError, +) +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.filesystem import check_path_owner +from pip._internal.utils.logging import BrokenStdoutLoggingError, setup_logging +from pip._internal.utils.misc import get_prog, normalize_path +from pip._internal.utils.temp_dir import global_tempdir_manager, tempdir_registry +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.virtualenv import running_under_virtualenv + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import Any, List, Optional, Tuple + + from pip._internal.utils.temp_dir import ( + TempDirectoryTypeRegistry as TempDirRegistry, + ) + +__all__ = ['Command'] + +logger = logging.getLogger(__name__) + + +class Command(CommandContextMixIn): + usage = None # type: str + ignore_require_venv = False # type: bool + + def __init__(self, name, summary, isolated=False): + # type: (str, str, bool) -> None + super(Command, self).__init__() + parser_kw = { + 'usage': self.usage, + 'prog': '{} {}'.format(get_prog(), name), + 'formatter': UpdatingDefaultsHelpFormatter(), + 'add_help_option': False, + 'name': name, + 'description': self.__doc__, + 'isolated': isolated, + } + + self.name = name + self.summary = summary + self.parser = ConfigOptionParser(**parser_kw) + + self.tempdir_registry = None # type: Optional[TempDirRegistry] + + # Commands should add options to this option group + optgroup_name = '{} Options'.format(self.name.capitalize()) + self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name) + + # Add the general options + gen_opts = cmdoptions.make_option_group( + cmdoptions.general_group, + self.parser, + ) + self.parser.add_option_group(gen_opts) + + self.add_options() + + def add_options(self): + # type: () -> None + pass + + def handle_pip_version_check(self, options): + # type: (Values) -> None + """ + This is a no-op so that commands by default do not do the pip version + check. + """ + # Make sure we do the pip version check if the index_group options + # are present. + assert not hasattr(options, 'no_index') + + def run(self, options, args): + # type: (Values, List[Any]) -> int + raise NotImplementedError + + def parse_args(self, args): + # type: (List[str]) -> Tuple[Any, Any] + # factored out for testability + return self.parser.parse_args(args) + + def main(self, args): + # type: (List[str]) -> int + try: + with self.main_context(): + return self._main(args) + finally: + logging.shutdown() + + def _main(self, args): + # type: (List[str]) -> int + # We must initialize this before the tempdir manager, otherwise the + # configuration would not be accessible by the time we clean up the + # tempdir manager. + self.tempdir_registry = self.enter_context(tempdir_registry()) + # Intentionally set as early as possible so globally-managed temporary + # directories are available to the rest of the code. + self.enter_context(global_tempdir_manager()) + + options, args = self.parse_args(args) + + # Set verbosity so that it can be used elsewhere. + self.verbosity = options.verbose - options.quiet + + level_number = setup_logging( + verbosity=self.verbosity, + no_color=options.no_color, + user_log_file=options.log, + ) + + if ( + sys.version_info[:2] == (2, 7) and + not options.no_python_version_warning + ): + message = ( + "pip 21.0 will drop support for Python 2.7 in January 2021. " + "More details about Python 2 support in pip can be found at " + "https://pip.pypa.io/en/latest/development/release-process/#python-2-support" # noqa + ) + if platform.python_implementation() == "CPython": + message = ( + "Python 2.7 reached the end of its life on January " + "1st, 2020. Please upgrade your Python as Python 2.7 " + "is no longer maintained. " + ) + message + deprecated(message, replacement=None, gone_in="21.0") + + if ( + sys.version_info[:2] == (3, 5) and + not options.no_python_version_warning + ): + message = ( + "Python 3.5 reached the end of its life on September " + "13th, 2020. Please upgrade your Python as Python 3.5 " + "is no longer maintained. pip 21.0 will drop support " + "for Python 3.5 in January 2021." + ) + deprecated(message, replacement=None, gone_in="21.0") + + # TODO: Try to get these passing down from the command? + # without resorting to os.environ to hold these. + # This also affects isolated builds and it should. + + if options.no_input: + os.environ['PIP_NO_INPUT'] = '1' + + if options.exists_action: + os.environ['PIP_EXISTS_ACTION'] = ' '.join(options.exists_action) + + if options.require_venv and not self.ignore_require_venv: + # If a venv is required check if it can really be found + if not running_under_virtualenv(): + logger.critical( + 'Could not find an activated virtualenv (required).' + ) + sys.exit(VIRTUALENV_NOT_FOUND) + + if options.cache_dir: + options.cache_dir = normalize_path(options.cache_dir) + if not check_path_owner(options.cache_dir): + logger.warning( + "The directory '%s' or its parent directory is not owned " + "or is not writable by the current user. The cache " + "has been disabled. Check the permissions and owner of " + "that directory. If executing pip with sudo, you may want " + "sudo's -H flag.", + options.cache_dir, + ) + options.cache_dir = None + + if getattr(options, "build_dir", None): + deprecated( + reason=( + "The -b/--build/--build-dir/--build-directory " + "option is deprecated and has no effect anymore." + ), + replacement=( + "use the TMPDIR/TEMP/TMP environment variable, " + "possibly combined with --no-clean" + ), + gone_in="21.1", + issue=8333, + ) + + if '2020-resolver' in options.features_enabled and not PY2: + logger.warning( + "--use-feature=2020-resolver no longer has any effect, " + "since it is now the default dependency resolver in pip. " + "This will become an error in pip 21.0." + ) + + try: + status = self.run(options, args) + assert isinstance(status, int) + return status + except PreviousBuildDirError as exc: + logger.critical(str(exc)) + logger.debug('Exception information:', exc_info=True) + + return PREVIOUS_BUILD_DIR_ERROR + except (InstallationError, UninstallationError, BadCommand, + NetworkConnectionError) as exc: + logger.critical(str(exc)) + logger.debug('Exception information:', exc_info=True) + + return ERROR + except CommandError as exc: + logger.critical('%s', exc) + logger.debug('Exception information:', exc_info=True) + + return ERROR + except BrokenStdoutLoggingError: + # Bypass our logger and write any remaining messages to stderr + # because stdout no longer works. + print('ERROR: Pipe to stdout was broken', file=sys.stderr) + if level_number <= logging.DEBUG: + traceback.print_exc(file=sys.stderr) + + return ERROR + except KeyboardInterrupt: + logger.critical('Operation cancelled by user') + logger.debug('Exception information:', exc_info=True) + + return ERROR + except BaseException: + logger.critical('Exception:', exc_info=True) + + return UNKNOWN_ERROR + finally: + self.handle_pip_version_check(options) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/cmdoptions.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/cmdoptions.py new file mode 100644 index 0000000..d4af37b --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/cmdoptions.py @@ -0,0 +1,971 @@ +""" +shared options and groups + +The principle here is to define options once, but *not* instantiate them +globally. One reason being that options with action='append' can carry state +between parses. pip parses general options twice internally, and shouldn't +pass on state. To be consistent, all options will follow this design. +""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +from __future__ import absolute_import + +import os +import textwrap +import warnings +from distutils.util import strtobool +from functools import partial +from optparse import SUPPRESS_HELP, Option, OptionGroup +from textwrap import dedent + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.progress_bars import BAR_TYPES +from pip._internal.exceptions import CommandError +from pip._internal.locations import USER_CACHE_DIR, get_src_prefix +from pip._internal.models.format_control import FormatControl +from pip._internal.models.index import PyPI +from pip._internal.models.target_python import TargetPython +from pip._internal.utils.hashes import STRONG_HASHES +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import OptionParser, Values + from typing import Any, Callable, Dict, Optional, Tuple + + from pip._internal.cli.parser import ConfigOptionParser + + +def raise_option_error(parser, option, msg): + # type: (OptionParser, Option, str) -> None + """ + Raise an option parsing error using parser.error(). + + Args: + parser: an OptionParser instance. + option: an Option instance. + msg: the error text. + """ + msg = '{} error: {}'.format(option, msg) + msg = textwrap.fill(' '.join(msg.split())) + parser.error(msg) + + +def make_option_group(group, parser): + # type: (Dict[str, Any], ConfigOptionParser) -> OptionGroup + """ + Return an OptionGroup object + group -- assumed to be dict with 'name' and 'options' keys + parser -- an optparse Parser + """ + option_group = OptionGroup(parser, group['name']) + for option in group['options']: + option_group.add_option(option()) + return option_group + + +def check_install_build_global(options, check_options=None): + # type: (Values, Optional[Values]) -> None + """Disable wheels if per-setup.py call options are set. + + :param options: The OptionParser options to update. + :param check_options: The options to check, if not supplied defaults to + options. + """ + if check_options is None: + check_options = options + + def getname(n): + # type: (str) -> Optional[Any] + return getattr(check_options, n, None) + names = ["build_options", "global_options", "install_options"] + if any(map(getname, names)): + control = options.format_control + control.disallow_binaries() + warnings.warn( + 'Disabling all use of wheels due to the use of --build-option ' + '/ --global-option / --install-option.', stacklevel=2, + ) + + +def check_dist_restriction(options, check_target=False): + # type: (Values, bool) -> None + """Function for determining if custom platform options are allowed. + + :param options: The OptionParser options. + :param check_target: Whether or not to check if --target is being used. + """ + dist_restriction_set = any([ + options.python_version, + options.platforms, + options.abis, + options.implementation, + ]) + + binary_only = FormatControl(set(), {':all:'}) + sdist_dependencies_allowed = ( + options.format_control != binary_only and + not options.ignore_dependencies + ) + + # Installations or downloads using dist restrictions must not combine + # source distributions and dist-specific wheels, as they are not + # guaranteed to be locally compatible. + if dist_restriction_set and sdist_dependencies_allowed: + raise CommandError( + "When restricting platform and interpreter constraints using " + "--python-version, --platform, --abi, or --implementation, " + "either --no-deps must be set, or --only-binary=:all: must be " + "set and --no-binary must not be set (or must be set to " + ":none:)." + ) + + if check_target: + if dist_restriction_set and not options.target_dir: + raise CommandError( + "Can not use any platform or abi specific options unless " + "installing via '--target'" + ) + + +def _path_option_check(option, opt, value): + # type: (Option, str, str) -> str + return os.path.expanduser(value) + + +def _package_name_option_check(option, opt, value): + # type: (Option, str, str) -> str + return canonicalize_name(value) + + +class PipOption(Option): + TYPES = Option.TYPES + ("path", "package_name") + TYPE_CHECKER = Option.TYPE_CHECKER.copy() + TYPE_CHECKER["package_name"] = _package_name_option_check + TYPE_CHECKER["path"] = _path_option_check + + +########### +# options # +########### + +help_ = partial( + Option, + '-h', '--help', + dest='help', + action='help', + help='Show help.', +) # type: Callable[..., Option] + +isolated_mode = partial( + Option, + "--isolated", + dest="isolated_mode", + action="store_true", + default=False, + help=( + "Run pip in an isolated mode, ignoring environment variables and user " + "configuration." + ), +) # type: Callable[..., Option] + +require_virtualenv = partial( + Option, + # Run only if inside a virtualenv, bail if not. + '--require-virtualenv', '--require-venv', + dest='require_venv', + action='store_true', + default=False, + help=SUPPRESS_HELP +) # type: Callable[..., Option] + +verbose = partial( + Option, + '-v', '--verbose', + dest='verbose', + action='count', + default=0, + help='Give more output. Option is additive, and can be used up to 3 times.' +) # type: Callable[..., Option] + +no_color = partial( + Option, + '--no-color', + dest='no_color', + action='store_true', + default=False, + help="Suppress colored output.", +) # type: Callable[..., Option] + +version = partial( + Option, + '-V', '--version', + dest='version', + action='store_true', + help='Show version and exit.', +) # type: Callable[..., Option] + +quiet = partial( + Option, + '-q', '--quiet', + dest='quiet', + action='count', + default=0, + help=( + 'Give less output. Option is additive, and can be used up to 3' + ' times (corresponding to WARNING, ERROR, and CRITICAL logging' + ' levels).' + ), +) # type: Callable[..., Option] + +progress_bar = partial( + Option, + '--progress-bar', + dest='progress_bar', + type='choice', + choices=list(BAR_TYPES.keys()), + default='on', + help=( + 'Specify type of progress to be displayed [' + + '|'.join(BAR_TYPES.keys()) + '] (default: %default)' + ), +) # type: Callable[..., Option] + +log = partial( + PipOption, + "--log", "--log-file", "--local-log", + dest="log", + metavar="path", + type="path", + help="Path to a verbose appending log." +) # type: Callable[..., Option] + +no_input = partial( + Option, + # Don't ask for input + '--no-input', + dest='no_input', + action='store_true', + default=False, + help="Disable prompting for input." +) # type: Callable[..., Option] + +proxy = partial( + Option, + '--proxy', + dest='proxy', + type='str', + default='', + help="Specify a proxy in the form [user:passwd@]proxy.server:port." +) # type: Callable[..., Option] + +retries = partial( + Option, + '--retries', + dest='retries', + type='int', + default=5, + help="Maximum number of retries each connection should attempt " + "(default %default times).", +) # type: Callable[..., Option] + +timeout = partial( + Option, + '--timeout', '--default-timeout', + metavar='sec', + dest='timeout', + type='float', + default=15, + help='Set the socket timeout (default %default seconds).', +) # type: Callable[..., Option] + + +def exists_action(): + # type: () -> Option + return Option( + # Option when path already exist + '--exists-action', + dest='exists_action', + type='choice', + choices=['s', 'i', 'w', 'b', 'a'], + default=[], + action='append', + metavar='action', + help="Default action when a path already exists: " + "(s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort.", + ) + + +cert = partial( + PipOption, + '--cert', + dest='cert', + type='path', + metavar='path', + help="Path to alternate CA bundle.", +) # type: Callable[..., Option] + +client_cert = partial( + PipOption, + '--client-cert', + dest='client_cert', + type='path', + default=None, + metavar='path', + help="Path to SSL client certificate, a single file containing the " + "private key and the certificate in PEM format.", +) # type: Callable[..., Option] + +index_url = partial( + Option, + '-i', '--index-url', '--pypi-url', + dest='index_url', + metavar='URL', + default=PyPI.simple_url, + help="Base URL of the Python Package Index (default %default). " + "This should point to a repository compliant with PEP 503 " + "(the simple repository API) or a local directory laid out " + "in the same format.", +) # type: Callable[..., Option] + + +def extra_index_url(): + # type: () -> Option + return Option( + '--extra-index-url', + dest='extra_index_urls', + metavar='URL', + action='append', + default=[], + help="Extra URLs of package indexes to use in addition to " + "--index-url. Should follow the same rules as " + "--index-url.", + ) + + +no_index = partial( + Option, + '--no-index', + dest='no_index', + action='store_true', + default=False, + help='Ignore package index (only looking at --find-links URLs instead).', +) # type: Callable[..., Option] + + +def find_links(): + # type: () -> Option + return Option( + '-f', '--find-links', + dest='find_links', + action='append', + default=[], + metavar='url', + help="If a URL or path to an html file, then parse for links to " + "archives such as sdist (.tar.gz) or wheel (.whl) files. " + "If a local path or file:// URL that's a directory, " + "then look for archives in the directory listing. " + "Links to VCS project URLs are not supported.", + ) + + +def trusted_host(): + # type: () -> Option + return Option( + "--trusted-host", + dest="trusted_hosts", + action="append", + metavar="HOSTNAME", + default=[], + help="Mark this host or host:port pair as trusted, even though it " + "does not have valid or any HTTPS.", + ) + + +def constraints(): + # type: () -> Option + return Option( + '-c', '--constraint', + dest='constraints', + action='append', + default=[], + metavar='file', + help='Constrain versions using the given constraints file. ' + 'This option can be used multiple times.' + ) + + +def requirements(): + # type: () -> Option + return Option( + '-r', '--requirement', + dest='requirements', + action='append', + default=[], + metavar='file', + help='Install from the given requirements file. ' + 'This option can be used multiple times.' + ) + + +def editable(): + # type: () -> Option + return Option( + '-e', '--editable', + dest='editables', + action='append', + default=[], + metavar='path/url', + help=('Install a project in editable mode (i.e. setuptools ' + '"develop mode") from a local project path or a VCS url.'), + ) + + +def _handle_src(option, opt_str, value, parser): + # type: (Option, str, str, OptionParser) -> None + value = os.path.abspath(value) + setattr(parser.values, option.dest, value) + + +src = partial( + PipOption, + '--src', '--source', '--source-dir', '--source-directory', + dest='src_dir', + type='path', + metavar='dir', + default=get_src_prefix(), + action='callback', + callback=_handle_src, + help='Directory to check out editable projects into. ' + 'The default in a virtualenv is "/src". ' + 'The default for global installs is "/src".' +) # type: Callable[..., Option] + + +def _get_format_control(values, option): + # type: (Values, Option) -> Any + """Get a format_control object.""" + return getattr(values, option.dest) + + +def _handle_no_binary(option, opt_str, value, parser): + # type: (Option, str, str, OptionParser) -> None + existing = _get_format_control(parser.values, option) + FormatControl.handle_mutual_excludes( + value, existing.no_binary, existing.only_binary, + ) + + +def _handle_only_binary(option, opt_str, value, parser): + # type: (Option, str, str, OptionParser) -> None + existing = _get_format_control(parser.values, option) + FormatControl.handle_mutual_excludes( + value, existing.only_binary, existing.no_binary, + ) + + +def no_binary(): + # type: () -> Option + format_control = FormatControl(set(), set()) + return Option( + "--no-binary", dest="format_control", action="callback", + callback=_handle_no_binary, type="str", + default=format_control, + help='Do not use binary packages. Can be supplied multiple times, and ' + 'each time adds to the existing value. Accepts either ":all:" to ' + 'disable all binary packages, ":none:" to empty the set (notice ' + 'the colons), or one or more package names with commas between ' + 'them (no colons). Note that some packages are tricky to compile ' + 'and may fail to install when this option is used on them.', + ) + + +def only_binary(): + # type: () -> Option + format_control = FormatControl(set(), set()) + return Option( + "--only-binary", dest="format_control", action="callback", + callback=_handle_only_binary, type="str", + default=format_control, + help='Do not use source packages. Can be supplied multiple times, and ' + 'each time adds to the existing value. Accepts either ":all:" to ' + 'disable all source packages, ":none:" to empty the set, or one ' + 'or more package names with commas between them. Packages ' + 'without binary distributions will fail to install when this ' + 'option is used on them.', + ) + + +platforms = partial( + Option, + '--platform', + dest='platforms', + metavar='platform', + action='append', + default=None, + help=("Only use wheels compatible with . Defaults to the " + "platform of the running system. Use this option multiple times to " + "specify multiple platforms supported by the target interpreter."), +) # type: Callable[..., Option] + + +# This was made a separate function for unit-testing purposes. +def _convert_python_version(value): + # type: (str) -> Tuple[Tuple[int, ...], Optional[str]] + """ + Convert a version string like "3", "37", or "3.7.3" into a tuple of ints. + + :return: A 2-tuple (version_info, error_msg), where `error_msg` is + non-None if and only if there was a parsing error. + """ + if not value: + # The empty string is the same as not providing a value. + return (None, None) + + parts = value.split('.') + if len(parts) > 3: + return ((), 'at most three version parts are allowed') + + if len(parts) == 1: + # Then we are in the case of "3" or "37". + value = parts[0] + if len(value) > 1: + parts = [value[0], value[1:]] + + try: + version_info = tuple(int(part) for part in parts) + except ValueError: + return ((), 'each version part must be an integer') + + return (version_info, None) + + +def _handle_python_version(option, opt_str, value, parser): + # type: (Option, str, str, OptionParser) -> None + """ + Handle a provided --python-version value. + """ + version_info, error_msg = _convert_python_version(value) + if error_msg is not None: + msg = ( + 'invalid --python-version value: {!r}: {}'.format( + value, error_msg, + ) + ) + raise_option_error(parser, option=option, msg=msg) + + parser.values.python_version = version_info + + +python_version = partial( + Option, + '--python-version', + dest='python_version', + metavar='python_version', + action='callback', + callback=_handle_python_version, type='str', + default=None, + help=dedent("""\ + The Python interpreter version to use for wheel and "Requires-Python" + compatibility checks. Defaults to a version derived from the running + interpreter. The version can be specified using up to three dot-separated + integers (e.g. "3" for 3.0.0, "3.7" for 3.7.0, or "3.7.3"). A major-minor + version can also be given as a string without dots (e.g. "37" for 3.7.0). + """), +) # type: Callable[..., Option] + + +implementation = partial( + Option, + '--implementation', + dest='implementation', + metavar='implementation', + default=None, + help=("Only use wheels compatible with Python " + "implementation , e.g. 'pp', 'jy', 'cp', " + " or 'ip'. If not specified, then the current " + "interpreter implementation is used. Use 'py' to force " + "implementation-agnostic wheels."), +) # type: Callable[..., Option] + + +abis = partial( + Option, + '--abi', + dest='abis', + metavar='abi', + action='append', + default=None, + help=("Only use wheels compatible with Python abi , e.g. 'pypy_41'. " + "If not specified, then the current interpreter abi tag is used. " + "Use this option multiple times to specify multiple abis supported " + "by the target interpreter. Generally you will need to specify " + "--implementation, --platform, and --python-version when using this " + "option."), +) # type: Callable[..., Option] + + +def add_target_python_options(cmd_opts): + # type: (OptionGroup) -> None + cmd_opts.add_option(platforms()) + cmd_opts.add_option(python_version()) + cmd_opts.add_option(implementation()) + cmd_opts.add_option(abis()) + + +def make_target_python(options): + # type: (Values) -> TargetPython + target_python = TargetPython( + platforms=options.platforms, + py_version_info=options.python_version, + abis=options.abis, + implementation=options.implementation, + ) + + return target_python + + +def prefer_binary(): + # type: () -> Option + return Option( + "--prefer-binary", + dest="prefer_binary", + action="store_true", + default=False, + help="Prefer older binary packages over newer source packages." + ) + + +cache_dir = partial( + PipOption, + "--cache-dir", + dest="cache_dir", + default=USER_CACHE_DIR, + metavar="dir", + type='path', + help="Store the cache data in ." +) # type: Callable[..., Option] + + +def _handle_no_cache_dir(option, opt, value, parser): + # type: (Option, str, str, OptionParser) -> None + """ + Process a value provided for the --no-cache-dir option. + + This is an optparse.Option callback for the --no-cache-dir option. + """ + # The value argument will be None if --no-cache-dir is passed via the + # command-line, since the option doesn't accept arguments. However, + # the value can be non-None if the option is triggered e.g. by an + # environment variable, like PIP_NO_CACHE_DIR=true. + if value is not None: + # Then parse the string value to get argument error-checking. + try: + strtobool(value) + except ValueError as exc: + raise_option_error(parser, option=option, msg=str(exc)) + + # Originally, setting PIP_NO_CACHE_DIR to a value that strtobool() + # converted to 0 (like "false" or "no") caused cache_dir to be disabled + # rather than enabled (logic would say the latter). Thus, we disable + # the cache directory not just on values that parse to True, but (for + # backwards compatibility reasons) also on values that parse to False. + # In other words, always set it to False if the option is provided in + # some (valid) form. + parser.values.cache_dir = False + + +no_cache = partial( + Option, + "--no-cache-dir", + dest="cache_dir", + action="callback", + callback=_handle_no_cache_dir, + help="Disable the cache.", +) # type: Callable[..., Option] + +no_deps = partial( + Option, + '--no-deps', '--no-dependencies', + dest='ignore_dependencies', + action='store_true', + default=False, + help="Don't install package dependencies.", +) # type: Callable[..., Option] + +build_dir = partial( + PipOption, + '-b', '--build', '--build-dir', '--build-directory', + dest='build_dir', + type='path', + metavar='dir', + help=SUPPRESS_HELP, +) # type: Callable[..., Option] + +ignore_requires_python = partial( + Option, + '--ignore-requires-python', + dest='ignore_requires_python', + action='store_true', + help='Ignore the Requires-Python information.' +) # type: Callable[..., Option] + +no_build_isolation = partial( + Option, + '--no-build-isolation', + dest='build_isolation', + action='store_false', + default=True, + help='Disable isolation when building a modern source distribution. ' + 'Build dependencies specified by PEP 518 must be already installed ' + 'if this option is used.' +) # type: Callable[..., Option] + + +def _handle_no_use_pep517(option, opt, value, parser): + # type: (Option, str, str, OptionParser) -> None + """ + Process a value provided for the --no-use-pep517 option. + + This is an optparse.Option callback for the no_use_pep517 option. + """ + # Since --no-use-pep517 doesn't accept arguments, the value argument + # will be None if --no-use-pep517 is passed via the command-line. + # However, the value can be non-None if the option is triggered e.g. + # by an environment variable, for example "PIP_NO_USE_PEP517=true". + if value is not None: + msg = """A value was passed for --no-use-pep517, + probably using either the PIP_NO_USE_PEP517 environment variable + or the "no-use-pep517" config file option. Use an appropriate value + of the PIP_USE_PEP517 environment variable or the "use-pep517" + config file option instead. + """ + raise_option_error(parser, option=option, msg=msg) + + # Otherwise, --no-use-pep517 was passed via the command-line. + parser.values.use_pep517 = False + + +use_pep517 = partial( + Option, + '--use-pep517', + dest='use_pep517', + action='store_true', + default=None, + help='Use PEP 517 for building source distributions ' + '(use --no-use-pep517 to force legacy behaviour).' +) # type: Any + +no_use_pep517 = partial( + Option, + '--no-use-pep517', + dest='use_pep517', + action='callback', + callback=_handle_no_use_pep517, + default=None, + help=SUPPRESS_HELP +) # type: Any + +install_options = partial( + Option, + '--install-option', + dest='install_options', + action='append', + metavar='options', + help="Extra arguments to be supplied to the setup.py install " + "command (use like --install-option=\"--install-scripts=/usr/local/" + "bin\"). Use multiple --install-option options to pass multiple " + "options to setup.py install. If you are using an option with a " + "directory path, be sure to use absolute path.", +) # type: Callable[..., Option] + +global_options = partial( + Option, + '--global-option', + dest='global_options', + action='append', + metavar='options', + help="Extra global options to be supplied to the setup.py " + "call before the install command.", +) # type: Callable[..., Option] + +no_clean = partial( + Option, + '--no-clean', + action='store_true', + default=False, + help="Don't clean up build directories." +) # type: Callable[..., Option] + +pre = partial( + Option, + '--pre', + action='store_true', + default=False, + help="Include pre-release and development versions. By default, " + "pip only finds stable versions.", +) # type: Callable[..., Option] + +disable_pip_version_check = partial( + Option, + "--disable-pip-version-check", + dest="disable_pip_version_check", + action="store_true", + default=True, + help="Don't periodically check PyPI to determine whether a new version " + "of pip is available for download. Implied with --no-index.", +) # type: Callable[..., Option] + + +def _handle_merge_hash(option, opt_str, value, parser): + # type: (Option, str, str, OptionParser) -> None + """Given a value spelled "algo:digest", append the digest to a list + pointed to in a dict by the algo name.""" + if not parser.values.hashes: + parser.values.hashes = {} + try: + algo, digest = value.split(':', 1) + except ValueError: + parser.error('Arguments to {} must be a hash name ' # noqa + 'followed by a value, like --hash=sha256:' + 'abcde...'.format(opt_str)) + if algo not in STRONG_HASHES: + parser.error('Allowed hash algorithms for {} are {}.'.format( # noqa + opt_str, ', '.join(STRONG_HASHES))) + parser.values.hashes.setdefault(algo, []).append(digest) + + +hash = partial( + Option, + '--hash', + # Hash values eventually end up in InstallRequirement.hashes due to + # __dict__ copying in process_line(). + dest='hashes', + action='callback', + callback=_handle_merge_hash, + type='string', + help="Verify that the package's archive matches this " + 'hash before installing. Example: --hash=sha256:abcdef...', +) # type: Callable[..., Option] + + +require_hashes = partial( + Option, + '--require-hashes', + dest='require_hashes', + action='store_true', + default=False, + help='Require a hash to check each requirement against, for ' + 'repeatable installs. This option is implied when any package in a ' + 'requirements file has a --hash option.', +) # type: Callable[..., Option] + + +list_path = partial( + PipOption, + '--path', + dest='path', + type='path', + action='append', + help='Restrict to the specified installation path for listing ' + 'packages (can be used multiple times).' +) # type: Callable[..., Option] + + +def check_list_path_option(options): + # type: (Values) -> None + if options.path and (options.user or options.local): + raise CommandError( + "Cannot combine '--path' with '--user' or '--local'" + ) + + +list_exclude = partial( + PipOption, + '--exclude', + dest='excludes', + action='append', + metavar='package', + type='package_name', + help="Exclude specified package from the output", +) # type: Callable[..., Option] + + +no_python_version_warning = partial( + Option, + '--no-python-version-warning', + dest='no_python_version_warning', + action='store_true', + default=False, + help='Silence deprecation warnings for upcoming unsupported Pythons.', +) # type: Callable[..., Option] + + +use_new_feature = partial( + Option, + '--use-feature', + dest='features_enabled', + metavar='feature', + action='append', + default=[], + choices=['2020-resolver', 'fast-deps'], + help='Enable new functionality, that may be backward incompatible.', +) # type: Callable[..., Option] + +use_deprecated_feature = partial( + Option, + '--use-deprecated', + dest='deprecated_features_enabled', + metavar='feature', + action='append', + default=[], + choices=['legacy-resolver'], + help=( + 'Enable deprecated functionality, that will be removed in the future.' + ), +) # type: Callable[..., Option] + + +########## +# groups # +########## + +general_group = { + 'name': 'General Options', + 'options': [ + help_, + isolated_mode, + require_virtualenv, + verbose, + version, + quiet, + log, + no_input, + proxy, + retries, + timeout, + exists_action, + trusted_host, + cert, + client_cert, + cache_dir, + no_cache, + disable_pip_version_check, + no_color, + no_python_version_warning, + use_new_feature, + use_deprecated_feature, + ] +} # type: Dict[str, Any] + +index_group = { + 'name': 'Package Index Options', + 'options': [ + index_url, + extra_index_url, + no_index, + find_links, + ] +} # type: Dict[str, Any] diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/command_context.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/command_context.py new file mode 100644 index 0000000..669c777 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/command_context.py @@ -0,0 +1,36 @@ +from contextlib import contextmanager + +from pip._vendor.contextlib2 import ExitStack + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import ContextManager, Iterator, TypeVar + + _T = TypeVar('_T', covariant=True) + + +class CommandContextMixIn(object): + def __init__(self): + # type: () -> None + super(CommandContextMixIn, self).__init__() + self._in_main_context = False + self._main_context = ExitStack() + + @contextmanager + def main_context(self): + # type: () -> Iterator[None] + assert not self._in_main_context + + self._in_main_context = True + try: + with self._main_context: + yield + finally: + self._in_main_context = False + + def enter_context(self, context_provider): + # type: (ContextManager[_T]) -> _T + assert self._in_main_context + + return self._main_context.enter_context(context_provider) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/main.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/main.py new file mode 100644 index 0000000..172f30d --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/main.py @@ -0,0 +1,75 @@ +"""Primary application entrypoint. +""" +from __future__ import absolute_import + +import locale +import logging +import os +import sys + +from pip._internal.cli.autocompletion import autocomplete +from pip._internal.cli.main_parser import parse_command +from pip._internal.commands import create_command +from pip._internal.exceptions import PipError +from pip._internal.utils import deprecation +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional + +logger = logging.getLogger(__name__) + + +# Do not import and use main() directly! Using it directly is actively +# discouraged by pip's maintainers. The name, location and behavior of +# this function is subject to change, so calling it directly is not +# portable across different pip versions. + +# In addition, running pip in-process is unsupported and unsafe. This is +# elaborated in detail at +# https://pip.pypa.io/en/stable/user_guide/#using-pip-from-your-program. +# That document also provides suggestions that should work for nearly +# all users that are considering importing and using main() directly. + +# However, we know that certain users will still want to invoke pip +# in-process. If you understand and accept the implications of using pip +# in an unsupported manner, the best approach is to use runpy to avoid +# depending on the exact location of this entry point. + +# The following example shows how to use runpy to invoke pip in that +# case: +# +# sys.argv = ["pip", your, args, here] +# runpy.run_module("pip", run_name="__main__") +# +# Note that this will exit the process after running, unlike a direct +# call to main. As it is not safe to do any processing after calling +# main, this should not be an issue in practice. + +def main(args=None): + # type: (Optional[List[str]]) -> int + if args is None: + args = sys.argv[1:] + + # Configure our deprecation warnings to be sent through loggers + deprecation.install_warning_logger() + + autocomplete() + + try: + cmd_name, cmd_args = parse_command(args) + except PipError as exc: + sys.stderr.write("ERROR: {}".format(exc)) + sys.stderr.write(os.linesep) + sys.exit(1) + + # Needed for locale.getpreferredencoding(False) to work + # in pip._internal.utils.encoding.auto_decode + try: + locale.setlocale(locale.LC_ALL, '') + except locale.Error as e: + # setlocale can apparently crash if locale are uninitialized + logger.debug("Ignoring error %s when setting locale", e) + command = create_command(cmd_name, isolated=("--isolated" in cmd_args)) + + return command.main(cmd_args) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/main_parser.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/main_parser.py new file mode 100644 index 0000000..ba3cf68 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/main_parser.py @@ -0,0 +1,96 @@ +"""A single place for constructing and exposing the main parser +""" + +import os +import sys + +from pip._internal.cli import cmdoptions +from pip._internal.cli.parser import ConfigOptionParser, UpdatingDefaultsHelpFormatter +from pip._internal.commands import commands_dict, get_similar_commands +from pip._internal.exceptions import CommandError +from pip._internal.utils.misc import get_pip_version, get_prog +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Tuple + + +__all__ = ["create_main_parser", "parse_command"] + + +def create_main_parser(): + # type: () -> ConfigOptionParser + """Creates and returns the main parser for pip's CLI + """ + + parser_kw = { + 'usage': '\n%prog [options]', + 'add_help_option': False, + 'formatter': UpdatingDefaultsHelpFormatter(), + 'name': 'global', + 'prog': get_prog(), + } + + parser = ConfigOptionParser(**parser_kw) + parser.disable_interspersed_args() + + parser.version = get_pip_version() + + # add the general options + gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, parser) + parser.add_option_group(gen_opts) + + # so the help formatter knows + parser.main = True # type: ignore + + # create command listing for description + description = [''] + [ + '{name:27} {command_info.summary}'.format(**locals()) + for name, command_info in commands_dict.items() + ] + parser.description = '\n'.join(description) + + return parser + + +def parse_command(args): + # type: (List[str]) -> Tuple[str, List[str]] + parser = create_main_parser() + + # Note: parser calls disable_interspersed_args(), so the result of this + # call is to split the initial args into the general options before the + # subcommand and everything else. + # For example: + # args: ['--timeout=5', 'install', '--user', 'INITools'] + # general_options: ['--timeout==5'] + # args_else: ['install', '--user', 'INITools'] + general_options, args_else = parser.parse_args(args) + + # --version + if general_options.version: + sys.stdout.write(parser.version) # type: ignore + sys.stdout.write(os.linesep) + sys.exit() + + # pip || pip help -> print_help() + if not args_else or (args_else[0] == 'help' and len(args_else) == 1): + parser.print_help() + sys.exit() + + # the subcommand name + cmd_name = args_else[0] + + if cmd_name not in commands_dict: + guess = get_similar_commands(cmd_name) + + msg = ['unknown command "{}"'.format(cmd_name)] + if guess: + msg.append('maybe you meant "{}"'.format(guess)) + + raise CommandError(' - '.join(msg)) + + # all the args without the subcommand + cmd_args = args[:] + cmd_args.remove(cmd_name) + + return cmd_name, cmd_args diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/parser.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/parser.py new file mode 100644 index 0000000..7170bfd --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/parser.py @@ -0,0 +1,285 @@ +"""Base option parser setup""" + +# The following comment should be removed at some point in the future. +# mypy: disallow-untyped-defs=False + +from __future__ import absolute_import + +import logging +import optparse +import sys +import textwrap +from distutils.util import strtobool + +from pip._vendor.contextlib2 import suppress +from pip._vendor.six import string_types + +from pip._internal.cli.status_codes import UNKNOWN_ERROR +from pip._internal.configuration import Configuration, ConfigurationError +from pip._internal.utils.compat import get_terminal_size +from pip._internal.utils.misc import redact_auth_from_url + +logger = logging.getLogger(__name__) + + +class PrettyHelpFormatter(optparse.IndentedHelpFormatter): + """A prettier/less verbose help formatter for optparse.""" + + def __init__(self, *args, **kwargs): + # help position must be aligned with __init__.parseopts.description + kwargs['max_help_position'] = 30 + kwargs['indent_increment'] = 1 + kwargs['width'] = get_terminal_size()[0] - 2 + optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs) + + def format_option_strings(self, option): + return self._format_option_strings(option) + + def _format_option_strings(self, option, mvarfmt=' <{}>', optsep=', '): + """ + Return a comma-separated list of option strings and metavars. + + :param option: tuple of (short opt, long opt), e.g: ('-f', '--format') + :param mvarfmt: metavar format string + :param optsep: separator + """ + opts = [] + + if option._short_opts: + opts.append(option._short_opts[0]) + if option._long_opts: + opts.append(option._long_opts[0]) + if len(opts) > 1: + opts.insert(1, optsep) + + if option.takes_value(): + metavar = option.metavar or option.dest.lower() + opts.append(mvarfmt.format(metavar.lower())) + + return ''.join(opts) + + def format_heading(self, heading): + if heading == 'Options': + return '' + return heading + ':\n' + + def format_usage(self, usage): + """ + Ensure there is only one newline between usage and the first heading + if there is no description. + """ + msg = '\nUsage: {}\n'.format( + self.indent_lines(textwrap.dedent(usage), " ")) + return msg + + def format_description(self, description): + # leave full control over description to us + if description: + if hasattr(self.parser, 'main'): + label = 'Commands' + else: + label = 'Description' + # some doc strings have initial newlines, some don't + description = description.lstrip('\n') + # some doc strings have final newlines and spaces, some don't + description = description.rstrip() + # dedent, then reindent + description = self.indent_lines(textwrap.dedent(description), " ") + description = '{}:\n{}\n'.format(label, description) + return description + else: + return '' + + def format_epilog(self, epilog): + # leave full control over epilog to us + if epilog: + return epilog + else: + return '' + + def indent_lines(self, text, indent): + new_lines = [indent + line for line in text.split('\n')] + return "\n".join(new_lines) + + +class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter): + """Custom help formatter for use in ConfigOptionParser. + + This is updates the defaults before expanding them, allowing + them to show up correctly in the help listing. + + Also redact auth from url type options + """ + + def expand_default(self, option): + default_values = None + if self.parser is not None: + self.parser._update_defaults(self.parser.defaults) + default_values = self.parser.defaults.get(option.dest) + help_text = optparse.IndentedHelpFormatter.expand_default(self, option) + + if default_values and option.metavar == 'URL': + if isinstance(default_values, string_types): + default_values = [default_values] + + # If its not a list, we should abort and just return the help text + if not isinstance(default_values, list): + default_values = [] + + for val in default_values: + help_text = help_text.replace( + val, redact_auth_from_url(val)) + + return help_text + + +class CustomOptionParser(optparse.OptionParser): + + def insert_option_group(self, idx, *args, **kwargs): + """Insert an OptionGroup at a given position.""" + group = self.add_option_group(*args, **kwargs) + + self.option_groups.pop() + self.option_groups.insert(idx, group) + + return group + + @property + def option_list_all(self): + """Get a list of all options, including those in option groups.""" + res = self.option_list[:] + for i in self.option_groups: + res.extend(i.option_list) + + return res + + +class ConfigOptionParser(CustomOptionParser): + """Custom option parser which updates its defaults by checking the + configuration files and environmental variables""" + + def __init__(self, *args, **kwargs): + self.name = kwargs.pop('name') + + isolated = kwargs.pop("isolated", False) + self.config = Configuration(isolated) + + assert self.name + optparse.OptionParser.__init__(self, *args, **kwargs) + + def check_default(self, option, key, val): + try: + return option.check_value(key, val) + except optparse.OptionValueError as exc: + print("An error occurred during configuration: {}".format(exc)) + sys.exit(3) + + def _get_ordered_configuration_items(self): + # Configuration gives keys in an unordered manner. Order them. + override_order = ["global", self.name, ":env:"] + + # Pool the options into different groups + section_items = {name: [] for name in override_order} + for section_key, val in self.config.items(): + # ignore empty values + if not val: + logger.debug( + "Ignoring configuration key '%s' as it's value is empty.", + section_key + ) + continue + + section, key = section_key.split(".", 1) + if section in override_order: + section_items[section].append((key, val)) + + # Yield each group in their override order + for section in override_order: + for key, val in section_items[section]: + yield key, val + + def _update_defaults(self, defaults): + """Updates the given defaults with values from the config files and + the environ. Does a little special handling for certain types of + options (lists).""" + + # Accumulate complex default state. + self.values = optparse.Values(self.defaults) + late_eval = set() + # Then set the options with those values + for key, val in self._get_ordered_configuration_items(): + # '--' because configuration supports only long names + option = self.get_option('--' + key) + + # Ignore options not present in this parser. E.g. non-globals put + # in [global] by users that want them to apply to all applicable + # commands. + if option is None: + continue + + if option.action in ('store_true', 'store_false'): + try: + val = strtobool(val) + except ValueError: + self.error( + '{} is not a valid value for {} option, ' # noqa + 'please specify a boolean value like yes/no, ' + 'true/false or 1/0 instead.'.format(val, key) + ) + elif option.action == 'count': + with suppress(ValueError): + val = strtobool(val) + with suppress(ValueError): + val = int(val) + if not isinstance(val, int) or val < 0: + self.error( + '{} is not a valid value for {} option, ' # noqa + 'please instead specify either a non-negative integer ' + 'or a boolean value like yes/no or false/true ' + 'which is equivalent to 1/0.'.format(val, key) + ) + elif option.action == 'append': + val = val.split() + val = [self.check_default(option, key, v) for v in val] + elif option.action == 'callback': + late_eval.add(option.dest) + opt_str = option.get_opt_string() + val = option.convert_value(opt_str, val) + # From take_action + args = option.callback_args or () + kwargs = option.callback_kwargs or {} + option.callback(option, opt_str, val, self, *args, **kwargs) + else: + val = self.check_default(option, key, val) + + defaults[option.dest] = val + + for key in late_eval: + defaults[key] = getattr(self.values, key) + self.values = None + return defaults + + def get_default_values(self): + """Overriding to make updating the defaults after instantiation of + the option parser possible, _update_defaults() does the dirty work.""" + if not self.process_default_values: + # Old, pre-Optik 1.5 behaviour. + return optparse.Values(self.defaults) + + # Load the configuration, or error out in case of an error + try: + self.config.load() + except ConfigurationError as err: + self.exit(UNKNOWN_ERROR, str(err)) + + defaults = self._update_defaults(self.defaults.copy()) # ours + for option in self._get_all_options(): + default = defaults.get(option.dest) + if isinstance(default, string_types): + opt_str = option.get_opt_string() + defaults[option.dest] = option.check_value(opt_str, default) + return optparse.Values(defaults) + + def error(self, msg): + self.print_usage(sys.stderr) + self.exit(UNKNOWN_ERROR, "{}\n".format(msg)) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/progress_bars.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/progress_bars.py new file mode 100644 index 0000000..6933855 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/progress_bars.py @@ -0,0 +1,280 @@ +from __future__ import division + +import itertools +import sys +from signal import SIGINT, default_int_handler, signal + +from pip._vendor import six +from pip._vendor.progress.bar import Bar, FillingCirclesBar, IncrementalBar +from pip._vendor.progress.spinner import Spinner + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.logging import get_indentation +from pip._internal.utils.misc import format_size +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, List + +try: + from pip._vendor import colorama +# Lots of different errors can come from this, including SystemError and +# ImportError. +except Exception: + colorama = None + + +def _select_progress_class(preferred, fallback): + # type: (Bar, Bar) -> Bar + encoding = getattr(preferred.file, "encoding", None) + + # If we don't know what encoding this file is in, then we'll just assume + # that it doesn't support unicode and use the ASCII bar. + if not encoding: + return fallback + + # Collect all of the possible characters we want to use with the preferred + # bar. + characters = [ + getattr(preferred, "empty_fill", six.text_type()), + getattr(preferred, "fill", six.text_type()), + ] + characters += list(getattr(preferred, "phases", [])) + + # Try to decode the characters we're using for the bar using the encoding + # of the given file, if this works then we'll assume that we can use the + # fancier bar and if not we'll fall back to the plaintext bar. + try: + six.text_type().join(characters).encode(encoding) + except UnicodeEncodeError: + return fallback + else: + return preferred + + +_BaseBar = _select_progress_class(IncrementalBar, Bar) # type: Any + + +class InterruptibleMixin(object): + """ + Helper to ensure that self.finish() gets called on keyboard interrupt. + + This allows downloads to be interrupted without leaving temporary state + (like hidden cursors) behind. + + This class is similar to the progress library's existing SigIntMixin + helper, but as of version 1.2, that helper has the following problems: + + 1. It calls sys.exit(). + 2. It discards the existing SIGINT handler completely. + 3. It leaves its own handler in place even after an uninterrupted finish, + which will have unexpected delayed effects if the user triggers an + unrelated keyboard interrupt some time after a progress-displaying + download has already completed, for example. + """ + + def __init__(self, *args, **kwargs): + # type: (List[Any], Dict[Any, Any]) -> None + """ + Save the original SIGINT handler for later. + """ + # https://github.com/python/mypy/issues/5887 + super(InterruptibleMixin, self).__init__( # type: ignore + *args, + **kwargs + ) + + self.original_handler = signal(SIGINT, self.handle_sigint) + + # If signal() returns None, the previous handler was not installed from + # Python, and we cannot restore it. This probably should not happen, + # but if it does, we must restore something sensible instead, at least. + # The least bad option should be Python's default SIGINT handler, which + # just raises KeyboardInterrupt. + if self.original_handler is None: + self.original_handler = default_int_handler + + def finish(self): + # type: () -> None + """ + Restore the original SIGINT handler after finishing. + + This should happen regardless of whether the progress display finishes + normally, or gets interrupted. + """ + super(InterruptibleMixin, self).finish() # type: ignore + signal(SIGINT, self.original_handler) + + def handle_sigint(self, signum, frame): # type: ignore + """ + Call self.finish() before delegating to the original SIGINT handler. + + This handler should only be in place while the progress display is + active. + """ + self.finish() + self.original_handler(signum, frame) + + +class SilentBar(Bar): + + def update(self): + # type: () -> None + pass + + +class BlueEmojiBar(IncrementalBar): + + suffix = "%(percent)d%%" + bar_prefix = " " + bar_suffix = " " + phases = (u"\U0001F539", u"\U0001F537", u"\U0001F535") # type: Any + + +class DownloadProgressMixin(object): + + def __init__(self, *args, **kwargs): + # type: (List[Any], Dict[Any, Any]) -> None + # https://github.com/python/mypy/issues/5887 + super(DownloadProgressMixin, self).__init__( # type: ignore + *args, + **kwargs + ) + self.message = (" " * ( + get_indentation() + 2 + )) + self.message # type: str + + @property + def downloaded(self): + # type: () -> str + return format_size(self.index) # type: ignore + + @property + def download_speed(self): + # type: () -> str + # Avoid zero division errors... + if self.avg == 0.0: # type: ignore + return "..." + return format_size(1 / self.avg) + "/s" # type: ignore + + @property + def pretty_eta(self): + # type: () -> str + if self.eta: # type: ignore + return "eta {}".format(self.eta_td) # type: ignore + return "" + + def iter(self, it): # type: ignore + for x in it: + yield x + # B305 is incorrectly raised here + # https://github.com/PyCQA/flake8-bugbear/issues/59 + self.next(len(x)) # noqa: B305 + self.finish() + + +class WindowsMixin(object): + + def __init__(self, *args, **kwargs): + # type: (List[Any], Dict[Any, Any]) -> None + # The Windows terminal does not support the hide/show cursor ANSI codes + # even with colorama. So we'll ensure that hide_cursor is False on + # Windows. + # This call needs to go before the super() call, so that hide_cursor + # is set in time. The base progress bar class writes the "hide cursor" + # code to the terminal in its init, so if we don't set this soon + # enough, we get a "hide" with no corresponding "show"... + if WINDOWS and self.hide_cursor: # type: ignore + self.hide_cursor = False + + # https://github.com/python/mypy/issues/5887 + super(WindowsMixin, self).__init__(*args, **kwargs) # type: ignore + + # Check if we are running on Windows and we have the colorama module, + # if we do then wrap our file with it. + if WINDOWS and colorama: + self.file = colorama.AnsiToWin32(self.file) # type: ignore + # The progress code expects to be able to call self.file.isatty() + # but the colorama.AnsiToWin32() object doesn't have that, so we'll + # add it. + self.file.isatty = lambda: self.file.wrapped.isatty() + # The progress code expects to be able to call self.file.flush() + # but the colorama.AnsiToWin32() object doesn't have that, so we'll + # add it. + self.file.flush = lambda: self.file.wrapped.flush() + + +class BaseDownloadProgressBar(WindowsMixin, InterruptibleMixin, + DownloadProgressMixin): + + file = sys.stdout + message = "%(percent)d%%" + suffix = "%(downloaded)s %(download_speed)s %(pretty_eta)s" + + +class DefaultDownloadProgressBar(BaseDownloadProgressBar, + _BaseBar): + pass + + +class DownloadSilentBar(BaseDownloadProgressBar, SilentBar): + pass + + +class DownloadBar(BaseDownloadProgressBar, + Bar): + pass + + +class DownloadFillingCirclesBar(BaseDownloadProgressBar, + FillingCirclesBar): + pass + + +class DownloadBlueEmojiProgressBar(BaseDownloadProgressBar, + BlueEmojiBar): + pass + + +class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin, + DownloadProgressMixin, Spinner): + + file = sys.stdout + suffix = "%(downloaded)s %(download_speed)s" + + def next_phase(self): + # type: () -> str + if not hasattr(self, "_phaser"): + self._phaser = itertools.cycle(self.phases) + return next(self._phaser) + + def update(self): + # type: () -> None + message = self.message % self + phase = self.next_phase() + suffix = self.suffix % self + line = ''.join([ + message, + " " if message else "", + phase, + " " if suffix else "", + suffix, + ]) + + self.writeln(line) + + +BAR_TYPES = { + "off": (DownloadSilentBar, DownloadSilentBar), + "on": (DefaultDownloadProgressBar, DownloadProgressSpinner), + "ascii": (DownloadBar, DownloadProgressSpinner), + "pretty": (DownloadFillingCirclesBar, DownloadProgressSpinner), + "emoji": (DownloadBlueEmojiProgressBar, DownloadProgressSpinner) +} + + +def DownloadProgressProvider(progress_bar, max=None): # type: ignore + if max is None or max == 0: + return BAR_TYPES[progress_bar][1]().iter + else: + return BAR_TYPES[progress_bar][0](max=max).iter diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/req_command.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/req_command.py new file mode 100644 index 0000000..008066a --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/req_command.py @@ -0,0 +1,436 @@ +"""Contains the Command base classes that depend on PipSession. + +The classes in this module are in a separate module so the commands not +needing download / PackageFinder capability don't unnecessarily import the +PackageFinder machinery and all its vendored dependencies, etc. +""" + +import logging +import os +from functools import partial + +from pip._vendor.six import PY2 + +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.cli.command_context import CommandContextMixIn +from pip._internal.exceptions import CommandError, PreviousBuildDirError +from pip._internal.index.collector import LinkCollector +from pip._internal.index.package_finder import PackageFinder +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.network.session import PipSession +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req.constructors import ( + install_req_from_editable, + install_req_from_line, + install_req_from_parsed_requirement, + install_req_from_req_string, +) +from pip._internal.req.req_file import parse_requirements +from pip._internal.self_outdated_check import pip_self_version_check +from pip._internal.utils.temp_dir import tempdir_kinds +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import Any, List, Optional, Tuple + + from pip._internal.cache import WheelCache + from pip._internal.models.target_python import TargetPython + from pip._internal.req.req_install import InstallRequirement + from pip._internal.req.req_tracker import RequirementTracker + from pip._internal.resolution.base import BaseResolver + from pip._internal.utils.temp_dir import TempDirectory, TempDirectoryTypeRegistry + + +logger = logging.getLogger(__name__) + + +class SessionCommandMixin(CommandContextMixIn): + + """ + A class mixin for command classes needing _build_session(). + """ + def __init__(self): + # type: () -> None + super(SessionCommandMixin, self).__init__() + self._session = None # Optional[PipSession] + + @classmethod + def _get_index_urls(cls, options): + # type: (Values) -> Optional[List[str]] + """Return a list of index urls from user-provided options.""" + index_urls = [] + if not getattr(options, "no_index", False): + url = getattr(options, "index_url", None) + if url: + index_urls.append(url) + urls = getattr(options, "extra_index_urls", None) + if urls: + index_urls.extend(urls) + # Return None rather than an empty list + return index_urls or None + + def get_default_session(self, options): + # type: (Values) -> PipSession + """Get a default-managed session.""" + if self._session is None: + self._session = self.enter_context(self._build_session(options)) + # there's no type annotation on requests.Session, so it's + # automatically ContextManager[Any] and self._session becomes Any, + # then https://github.com/python/mypy/issues/7696 kicks in + assert self._session is not None + return self._session + + def _build_session(self, options, retries=None, timeout=None): + # type: (Values, Optional[int], Optional[int]) -> PipSession + assert not options.cache_dir or os.path.isabs(options.cache_dir) + session = PipSession( + cache=( + os.path.join(options.cache_dir, "http") + if options.cache_dir else None + ), + retries=retries if retries is not None else options.retries, + trusted_hosts=options.trusted_hosts, + index_urls=self._get_index_urls(options), + ) + + # Handle custom ca-bundles from the user + if options.cert: + session.verify = options.cert + + # Handle SSL client certificate + if options.client_cert: + session.cert = options.client_cert + + # Handle timeouts + if options.timeout or timeout: + session.timeout = ( + timeout if timeout is not None else options.timeout + ) + + # Handle configured proxies + if options.proxy: + session.proxies = { + "http": options.proxy, + "https": options.proxy, + } + + # Determine if we can prompt the user for authentication or not + session.auth.prompting = not options.no_input + + return session + + +class IndexGroupCommand(Command, SessionCommandMixin): + + """ + Abstract base class for commands with the index_group options. + + This also corresponds to the commands that permit the pip version check. + """ + + def handle_pip_version_check(self, options): + # type: (Values) -> None + """ + Do the pip version check if not disabled. + + This overrides the default behavior of not doing the check. + """ + # Make sure the index_group options are present. + assert hasattr(options, 'no_index') + + if options.disable_pip_version_check or options.no_index: + return + + # Otherwise, check if we're using the latest version of pip available. + session = self._build_session( + options, + retries=0, + timeout=min(5, options.timeout) + ) + with session: + pip_self_version_check(session, options) + + +KEEPABLE_TEMPDIR_TYPES = [ + tempdir_kinds.BUILD_ENV, + tempdir_kinds.EPHEM_WHEEL_CACHE, + tempdir_kinds.REQ_BUILD, +] + + +def with_cleanup(func): + # type: (Any) -> Any + """Decorator for common logic related to managing temporary + directories. + """ + def configure_tempdir_registry(registry): + # type: (TempDirectoryTypeRegistry) -> None + for t in KEEPABLE_TEMPDIR_TYPES: + registry.set_delete(t, False) + + def wrapper(self, options, args): + # type: (RequirementCommand, Values, List[Any]) -> Optional[int] + assert self.tempdir_registry is not None + if options.no_clean: + configure_tempdir_registry(self.tempdir_registry) + + try: + return func(self, options, args) + except PreviousBuildDirError: + # This kind of conflict can occur when the user passes an explicit + # build directory with a pre-existing folder. In that case we do + # not want to accidentally remove it. + configure_tempdir_registry(self.tempdir_registry) + raise + + return wrapper + + +class RequirementCommand(IndexGroupCommand): + + def __init__(self, *args, **kw): + # type: (Any, Any) -> None + super(RequirementCommand, self).__init__(*args, **kw) + + self.cmd_opts.add_option(cmdoptions.no_clean()) + + @staticmethod + def determine_resolver_variant(options): + # type: (Values) -> str + """Determines which resolver should be used, based on the given options.""" + # We didn't want to change things for Python 2, since it's nearly done with + # and we're using performance improvements that only work on Python 3. + if PY2: + if '2020-resolver' in options.features_enabled: + return "2020-resolver" + else: + return "legacy" + + if "legacy-resolver" in options.deprecated_features_enabled: + return "legacy" + + return "2020-resolver" + + @classmethod + def make_requirement_preparer( + cls, + temp_build_dir, # type: TempDirectory + options, # type: Values + req_tracker, # type: RequirementTracker + session, # type: PipSession + finder, # type: PackageFinder + use_user_site, # type: bool + download_dir=None, # type: str + ): + # type: (...) -> RequirementPreparer + """ + Create a RequirementPreparer instance for the given parameters. + """ + temp_build_dir_path = temp_build_dir.path + assert temp_build_dir_path is not None + + resolver_variant = cls.determine_resolver_variant(options) + if resolver_variant == "2020-resolver": + lazy_wheel = 'fast-deps' in options.features_enabled + if lazy_wheel: + logger.warning( + 'pip is using lazily downloaded wheels using HTTP ' + 'range requests to obtain dependency information. ' + 'This experimental feature is enabled through ' + '--use-feature=fast-deps and it is not ready for ' + 'production.' + ) + else: + lazy_wheel = False + if 'fast-deps' in options.features_enabled: + logger.warning( + 'fast-deps has no effect when used with the legacy resolver.' + ) + + return RequirementPreparer( + build_dir=temp_build_dir_path, + src_dir=options.src_dir, + download_dir=download_dir, + build_isolation=options.build_isolation, + req_tracker=req_tracker, + session=session, + progress_bar=options.progress_bar, + finder=finder, + require_hashes=options.require_hashes, + use_user_site=use_user_site, + lazy_wheel=lazy_wheel, + ) + + @classmethod + def make_resolver( + cls, + preparer, # type: RequirementPreparer + finder, # type: PackageFinder + options, # type: Values + wheel_cache=None, # type: Optional[WheelCache] + use_user_site=False, # type: bool + ignore_installed=True, # type: bool + ignore_requires_python=False, # type: bool + force_reinstall=False, # type: bool + upgrade_strategy="to-satisfy-only", # type: str + use_pep517=None, # type: Optional[bool] + py_version_info=None, # type: Optional[Tuple[int, ...]] + ): + # type: (...) -> BaseResolver + """ + Create a Resolver instance for the given parameters. + """ + make_install_req = partial( + install_req_from_req_string, + isolated=options.isolated_mode, + use_pep517=use_pep517, + ) + resolver_variant = cls.determine_resolver_variant(options) + # The long import name and duplicated invocation is needed to convince + # Mypy into correctly typechecking. Otherwise it would complain the + # "Resolver" class being redefined. + if resolver_variant == "2020-resolver": + import pip._internal.resolution.resolvelib.resolver + + return pip._internal.resolution.resolvelib.resolver.Resolver( + preparer=preparer, + finder=finder, + wheel_cache=wheel_cache, + make_install_req=make_install_req, + use_user_site=use_user_site, + ignore_dependencies=options.ignore_dependencies, + ignore_installed=ignore_installed, + ignore_requires_python=ignore_requires_python, + force_reinstall=force_reinstall, + upgrade_strategy=upgrade_strategy, + py_version_info=py_version_info, + ) + import pip._internal.resolution.legacy.resolver + return pip._internal.resolution.legacy.resolver.Resolver( + preparer=preparer, + finder=finder, + wheel_cache=wheel_cache, + make_install_req=make_install_req, + use_user_site=use_user_site, + ignore_dependencies=options.ignore_dependencies, + ignore_installed=ignore_installed, + ignore_requires_python=ignore_requires_python, + force_reinstall=force_reinstall, + upgrade_strategy=upgrade_strategy, + py_version_info=py_version_info, + ) + + def get_requirements( + self, + args, # type: List[str] + options, # type: Values + finder, # type: PackageFinder + session, # type: PipSession + ): + # type: (...) -> List[InstallRequirement] + """ + Parse command-line arguments into the corresponding requirements. + """ + requirements = [] # type: List[InstallRequirement] + for filename in options.constraints: + for parsed_req in parse_requirements( + filename, + constraint=True, finder=finder, options=options, + session=session): + req_to_add = install_req_from_parsed_requirement( + parsed_req, + isolated=options.isolated_mode, + user_supplied=False, + ) + requirements.append(req_to_add) + + for req in args: + req_to_add = install_req_from_line( + req, None, isolated=options.isolated_mode, + use_pep517=options.use_pep517, + user_supplied=True, + ) + requirements.append(req_to_add) + + for req in options.editables: + req_to_add = install_req_from_editable( + req, + user_supplied=True, + isolated=options.isolated_mode, + use_pep517=options.use_pep517, + ) + requirements.append(req_to_add) + + # NOTE: options.require_hashes may be set if --require-hashes is True + for filename in options.requirements: + for parsed_req in parse_requirements( + filename, + finder=finder, options=options, session=session): + req_to_add = install_req_from_parsed_requirement( + parsed_req, + isolated=options.isolated_mode, + use_pep517=options.use_pep517, + user_supplied=True, + ) + requirements.append(req_to_add) + + # If any requirement has hash options, enable hash checking. + if any(req.has_hash_options for req in requirements): + options.require_hashes = True + + if not (args or options.editables or options.requirements): + opts = {'name': self.name} + if options.find_links: + raise CommandError( + 'You must give at least one requirement to {name} ' + '(maybe you meant "pip {name} {links}"?)'.format( + **dict(opts, links=' '.join(options.find_links)))) + else: + raise CommandError( + 'You must give at least one requirement to {name} ' + '(see "pip help {name}")'.format(**opts)) + + return requirements + + @staticmethod + def trace_basic_info(finder): + # type: (PackageFinder) -> None + """ + Trace basic information about the provided objects. + """ + # Display where finder is looking for packages + search_scope = finder.search_scope + locations = search_scope.get_formatted_locations() + if locations: + logger.info(locations) + + def _build_package_finder( + self, + options, # type: Values + session, # type: PipSession + target_python=None, # type: Optional[TargetPython] + ignore_requires_python=None, # type: Optional[bool] + ): + # type: (...) -> PackageFinder + """ + Create a package finder appropriate to this requirement command. + + :param ignore_requires_python: Whether to ignore incompatible + "Requires-Python" values in links. Defaults to False. + """ + link_collector = LinkCollector.create(session, options=options) + selection_prefs = SelectionPreferences( + allow_yanked=True, + format_control=options.format_control, + allow_all_prereleases=options.pre, + prefer_binary=options.prefer_binary, + ignore_requires_python=ignore_requires_python, + ) + + return PackageFinder.create( + link_collector=link_collector, + selection_prefs=selection_prefs, + target_python=target_python, + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/spinners.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/spinners.py new file mode 100644 index 0000000..65c3c23 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/spinners.py @@ -0,0 +1,173 @@ +from __future__ import absolute_import, division + +import contextlib +import itertools +import logging +import sys +import time + +from pip._vendor.progress import HIDE_CURSOR, SHOW_CURSOR + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.logging import get_indentation +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import IO, Iterator + +logger = logging.getLogger(__name__) + + +class SpinnerInterface(object): + def spin(self): + # type: () -> None + raise NotImplementedError() + + def finish(self, final_status): + # type: (str) -> None + raise NotImplementedError() + + +class InteractiveSpinner(SpinnerInterface): + def __init__(self, message, file=None, spin_chars="-\\|/", + # Empirically, 8 updates/second looks nice + min_update_interval_seconds=0.125): + # type: (str, IO[str], str, float) -> None + self._message = message + if file is None: + file = sys.stdout + self._file = file + self._rate_limiter = RateLimiter(min_update_interval_seconds) + self._finished = False + + self._spin_cycle = itertools.cycle(spin_chars) + + self._file.write(" " * get_indentation() + self._message + " ... ") + self._width = 0 + + def _write(self, status): + # type: (str) -> None + assert not self._finished + # Erase what we wrote before by backspacing to the beginning, writing + # spaces to overwrite the old text, and then backspacing again + backup = "\b" * self._width + self._file.write(backup + " " * self._width + backup) + # Now we have a blank slate to add our status + self._file.write(status) + self._width = len(status) + self._file.flush() + self._rate_limiter.reset() + + def spin(self): + # type: () -> None + if self._finished: + return + if not self._rate_limiter.ready(): + return + self._write(next(self._spin_cycle)) + + def finish(self, final_status): + # type: (str) -> None + if self._finished: + return + self._write(final_status) + self._file.write("\n") + self._file.flush() + self._finished = True + + +# Used for dumb terminals, non-interactive installs (no tty), etc. +# We still print updates occasionally (once every 60 seconds by default) to +# act as a keep-alive for systems like Travis-CI that take lack-of-output as +# an indication that a task has frozen. +class NonInteractiveSpinner(SpinnerInterface): + def __init__(self, message, min_update_interval_seconds=60): + # type: (str, float) -> None + self._message = message + self._finished = False + self._rate_limiter = RateLimiter(min_update_interval_seconds) + self._update("started") + + def _update(self, status): + # type: (str) -> None + assert not self._finished + self._rate_limiter.reset() + logger.info("%s: %s", self._message, status) + + def spin(self): + # type: () -> None + if self._finished: + return + if not self._rate_limiter.ready(): + return + self._update("still running...") + + def finish(self, final_status): + # type: (str) -> None + if self._finished: + return + self._update( + "finished with status '{final_status}'".format(**locals())) + self._finished = True + + +class RateLimiter(object): + def __init__(self, min_update_interval_seconds): + # type: (float) -> None + self._min_update_interval_seconds = min_update_interval_seconds + self._last_update = 0 # type: float + + def ready(self): + # type: () -> bool + now = time.time() + delta = now - self._last_update + return delta >= self._min_update_interval_seconds + + def reset(self): + # type: () -> None + self._last_update = time.time() + + +@contextlib.contextmanager +def open_spinner(message): + # type: (str) -> Iterator[SpinnerInterface] + # Interactive spinner goes directly to sys.stdout rather than being routed + # through the logging system, but it acts like it has level INFO, + # i.e. it's only displayed if we're at level INFO or better. + # Non-interactive spinner goes through the logging system, so it is always + # in sync with logging configuration. + if sys.stdout.isatty() and logger.getEffectiveLevel() <= logging.INFO: + spinner = InteractiveSpinner(message) # type: SpinnerInterface + else: + spinner = NonInteractiveSpinner(message) + try: + with hidden_cursor(sys.stdout): + yield spinner + except KeyboardInterrupt: + spinner.finish("canceled") + raise + except Exception: + spinner.finish("error") + raise + else: + spinner.finish("done") + + +@contextlib.contextmanager +def hidden_cursor(file): + # type: (IO[str]) -> Iterator[None] + # The Windows terminal does not support the hide/show cursor ANSI codes, + # even via colorama. So don't even try. + if WINDOWS: + yield + # We don't want to clutter the output with control characters if we're + # writing to a file, or if the user is running with --quiet. + # See https://github.com/pypa/pip/issues/3418 + elif not file.isatty() or logger.getEffectiveLevel() > logging.INFO: + yield + else: + file.write(HIDE_CURSOR) + try: + yield + finally: + file.write(SHOW_CURSOR) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/status_codes.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/status_codes.py new file mode 100644 index 0000000..275360a --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/cli/status_codes.py @@ -0,0 +1,8 @@ +from __future__ import absolute_import + +SUCCESS = 0 +ERROR = 1 +UNKNOWN_ERROR = 2 +VIRTUALENV_NOT_FOUND = 3 +PREVIOUS_BUILD_DIR_ERROR = 4 +NO_MATCHES_FOUND = 23 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__init__.py new file mode 100644 index 0000000..4f0c4ba --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__init__.py @@ -0,0 +1,123 @@ +""" +Package containing all pip commands +""" + +# The following comment should be removed at some point in the future. +# mypy: disallow-untyped-defs=False +# There is currently a bug in python/typeshed mentioned at +# https://github.com/python/typeshed/issues/3906 which causes the +# return type of difflib.get_close_matches to be reported +# as List[Sequence[str]] whereas it should have been List[str] + +from __future__ import absolute_import + +import importlib +from collections import OrderedDict, namedtuple + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any + + from pip._internal.cli.base_command import Command + + +CommandInfo = namedtuple('CommandInfo', 'module_path, class_name, summary') + +# The ordering matters for help display. +# Also, even though the module path starts with the same +# "pip._internal.commands" prefix in each case, we include the full path +# because it makes testing easier (specifically when modifying commands_dict +# in test setup / teardown by adding info for a FakeCommand class defined +# in a test-related module). +# Finally, we need to pass an iterable of pairs here rather than a dict +# so that the ordering won't be lost when using Python 2.7. +commands_dict = OrderedDict([ + ('install', CommandInfo( + 'pip._internal.commands.install', 'InstallCommand', + 'Install packages.', + )), + ('download', CommandInfo( + 'pip._internal.commands.download', 'DownloadCommand', + 'Download packages.', + )), + ('uninstall', CommandInfo( + 'pip._internal.commands.uninstall', 'UninstallCommand', + 'Uninstall packages.', + )), + ('freeze', CommandInfo( + 'pip._internal.commands.freeze', 'FreezeCommand', + 'Output installed packages in requirements format.', + )), + ('list', CommandInfo( + 'pip._internal.commands.list', 'ListCommand', + 'List installed packages.', + )), + ('show', CommandInfo( + 'pip._internal.commands.show', 'ShowCommand', + 'Show information about installed packages.', + )), + ('check', CommandInfo( + 'pip._internal.commands.check', 'CheckCommand', + 'Verify installed packages have compatible dependencies.', + )), + ('config', CommandInfo( + 'pip._internal.commands.configuration', 'ConfigurationCommand', + 'Manage local and global configuration.', + )), + ('search', CommandInfo( + 'pip._internal.commands.search', 'SearchCommand', + 'Search PyPI for packages.', + )), + ('cache', CommandInfo( + 'pip._internal.commands.cache', 'CacheCommand', + "Inspect and manage pip's wheel cache.", + )), + ('wheel', CommandInfo( + 'pip._internal.commands.wheel', 'WheelCommand', + 'Build wheels from your requirements.', + )), + ('hash', CommandInfo( + 'pip._internal.commands.hash', 'HashCommand', + 'Compute hashes of package archives.', + )), + ('completion', CommandInfo( + 'pip._internal.commands.completion', 'CompletionCommand', + 'A helper command used for command completion.', + )), + ('debug', CommandInfo( + 'pip._internal.commands.debug', 'DebugCommand', + 'Show information useful for debugging.', + )), + ('help', CommandInfo( + 'pip._internal.commands.help', 'HelpCommand', + 'Show help for commands.', + )), +]) # type: OrderedDict[str, CommandInfo] + + +def create_command(name, **kwargs): + # type: (str, **Any) -> Command + """ + Create an instance of the Command class with the given name. + """ + module_path, class_name, summary = commands_dict[name] + module = importlib.import_module(module_path) + command_class = getattr(module, class_name) + command = command_class(name=name, summary=summary, **kwargs) + + return command + + +def get_similar_commands(name): + """Command name auto-correct.""" + from difflib import get_close_matches + + name = name.lower() + + close_commands = get_close_matches(name, commands_dict.keys()) + + if close_commands: + return close_commands[0] + else: + return False diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..55850352356d4cfb90a446d649ae2417c3a30772 GIT binary patch literal 3000 zcmcguNpsvp6qYoa#j|)x42iQUWStPt5VDblkYpTV6XLjV1u9cisbsyLk#I{Ix}~^g zYUX6l6hDANQpJT|!hh&1C+?g$P`qwQE(bhUG&QaM`n~@8ZQU)W(Wq+pc#}V!;=HE) zF2TWP5y2z;^EF-5KDr^(w zB{~ySyHzDC(^^pP)=^f13e4;o-3BQ_l{BCRb!hArdIroQnuB>*Q0NGvqp%3?DfB*~ zV{jan6gq+EB%FfN3Y|f87A!cY&Z+$n#g5uk6m+)6O&dtCt%a>l>frXyI`< z#8B$O|L{5>TqsL&TAG=&=@upWk2LGS~xm`Cbn!pj0p=J z+RBY>WpXjQo+@VaqlFAxgVbZ*5*3JcLmD|SIy;3dR}gb6nQBgVBp*1yHT88Axy=hv8vQ^s_QS3c#y8b?Clv?6P zq2+8xhZ^4!Mb{(l&gj$>GnG`-J5nj9zwP?DRIJZaukZi&Ow+je(AXr%I!rX*P#~fCaX`QZS1Dp*<@Uc6NkCp z)HJ7J(b!UIIr~xytQn#!!CqW+DXk~3d;lK2!-8mu@L1=cW1*gJ)Yb>lhQn_4$gC~9li=B($j zgGEj-joc&Lih8;KmW-wUS|+jTq7o%CMWb_56Pc@s1<9GJ=gTZVwmd=ygyjdKm2lip zGTg{5Pe@fl=_CvfknN;DH9Sfx>MK$yU*Xb!HUO^BOQ>2yP3YsfECYmgOb-wWF+kYn zyvG!;oOIAy-g5C0-G3_BE8_nd{`oy@Vr{G~Y2Owm#-uPYWBrXWHs0!!Vq6#($Avv( zQW}?fs53S}|JfMpzvw^elk&KX7m6`jty=hW7;!K!PMB`G&?PcCu}7@TwDf4VcKz5> z!+lIvXvvelr3mn1F(ne^?A&jfqLD?L+aT|nne+~#{H1D6Zd#s1~Ot|+Z+cD{_Q6ht{&^;eDEK()X2+FlfpHlfsy;`qDB3wac_ zIdj{L3?klkb_qv?WxxO|gO6t{$I@%}Nl5UZAng`9`nru)w+F-6i^3bNyKU~HZhkGb zu}Itd_gXu5x^3f_AKP|oFch<{3b36CT{MiV52)g-Ud7*{!EWK$J9#ePfQkQ(RKAUk z`h?N~eWL4_%{RtdZK93!u@)EJm~S=AGv=MO#s=t1+Lk6i7{J6F7e^;LS=q}BSxyp1 z%WlLNo*XSED+_P;1xx`3Fyh3<%LR`OzPiyYiZb}U9{SGY`l3jqUBXyX_RSqKw1Ibl(*!2Q6d4$I@f2PolnY&4^8RE$}})GG$NkGQ!Y%C-%WYuln~ z+r1=C7_n_;pp0F`M%3JhQuG0{#hDBilhG0<-aRvt*r&V|4+pp*ncOy_l!1~2|NbbU zerwyoAY@*!vgDOJPI;}8q|7_uovbpZT&z4uOY)%%D*p)^vxaWz^XQzZ*Nu9iS~YYN Rf5zXY`9HsZD?O?-{sEX1!59Dl literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/cache.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/cache.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..57c081d96b0d13b547cc70701ed41cb201a50c71 GIT binary patch literal 5899 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 LMYuim%!2tpHkjZ5 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/check.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/check.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..450379ba2c1e2f9d52d2bf5ae00a74b1bd6086ff GIT binary patch literal 1616 zcmZuy-HYTz5bu0vGFja(7k51+_i*5dn+OUbh@6beDW0S3at9ah2$^*6Om;gT+uhk^ zh71UEPlDise}IB7{!9JplkYzHAXaB*_vYk!rfaIItI}1!s>-Ar8yQpQASl1M9P@^zov#?^TlTB(DPV5wJ>~^w6dxaN!9dFZq z;m5v)2>Nw{y!M+GzfOF12~Tn8X0a7-byhCjE_ULbVmIE^&;x{f*n5t!NA#r;zk#(A zH0b{Y@u1N_lg_XzinPQ7U0O%S$KM`H=j73Fcyw|CnyqX~vh$=)v-5O95>AA?n=z6K zvaU-`Syd!?$wf*j!SGQ3isfKaHKJ|=$lKpM`R++F{PJk{b#nY@H2P}v0JQewls1IJ zJ;vwdOqvgKE;1F@`qDwT51ZcsLQt$>6zf=v4Xno|Hn8~|#TK?8CtLbM749mb`Nxk5 z%TH&)ZD7GF4<1a@OA=&NQKupwQxafOlM<6M%LxzXdtT73do`;j!S_`y@~Y&|G6N#G zSsTFgU=LyQ-+>6UL{IgFu`q?!8cPj$Yhkz67wB2Ia9X2v_R*QXa9c}ppxs;agn_lz zY2CJm^?kH7HFWX8#X)Ps=|?a5*ejnqPmP7Q=r4TmgeQWh-+FC-X@e)e7_}DvxwT=N z>=$94Ah0r*nuY|xgAqVvjppy&;{kjbxoC1m6#ss3HO;eWkn^Cd#0$7Wra@lw!)u3W zdh1k>QgnXfMg+5}xrVbd3+Hc-s$k5jb5h>iq0D)3S~VpO2R4H-LCgXoolC+vK+7DZ zQs^=@FM|zfazam~vqD~)DVuQFUu(m7qfWuMoFq`AF_%t}b0x}tR+XnT&x8_uI6Nbn zNXoPzOqEP}x22v*7x?Z-_7%5^MjC+4ABgRP`9D8I)2bj5p){|AIIE^5ugZwCEMlat zc$8id4hDx9M&c0Xkg7^3nvjw(P(|S-DK8_MkE41frd9c2_({ZJG!AcCF{<-Ag4q#- zl_`y&C)F_Ws2jYno@B#ogJO*wD4h>v2R2vrbm3Oh z=yZcU>CkF2QTV?D$%VJcg&EDmamq=u%95$sew7itNJPWI3={sMFaB>?)e2)Znqh}l z*Hm45$v0oVxDh$!A+$)=wVFJ5)v=h>5HoXCOuY#a4dJXtzYNq%u5LfrLO>NWkp`xB{LPa-?{{V#g!+Zb$ literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/completion.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/completion.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f0d3e6ac0c353d737e005d477eb644efe928d9e8 GIT binary patch literal 3222 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/debug.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/debug.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b8ec70f6af4ea85c9e06754b98c854bab51a4f5 GIT binary patch literal 7496 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/download.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/download.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd5410e3170de0953ea59635481d95c98c5e865b GIT binary patch literal 4004 zcmbVPTW{mW6(%W)q^OH;yY{a4QX*)8xTqy0X&N+ew*kCqns#d};v_&AYzdk(mgwbe zXGl9TA*zLL+ zextL$hVQRw+Mgsd|1-gSh=>0X4bh06XsPb&x}=T7@D25D_zk=piJ3P2rjnV7mD;|o z=w{-iEx(nzzN>gEX{Q~(qi8$nraix>XeU`pm;L2*#a~HR{Z-Z1O4ia_{w+nj$?bIA zU)MFd&VG;e+Q~+G$G@Xwo#bx1>2E@2T->AgFLnRH#~SI9-b;=2XzRS;KP1M!wzc$U zoI~5v#Zq{{^Q0OUjxjCc=%grsOIZLg9mkZ&+tvsAm&TWZ&HgiiS<%D z*L|DVu$d#49_J@nl80n^;_!*CX|9LgOyCtbRyd^GJ7jtKfvbeu-qZ2ZPrSEaBQGyU zlzDMR=-1ewSMfL-dUJ;HctNB1Fs6+6r<1?f-S-NXAK}nm#geQ3CwUYmR}z>{StX_m z19AraX@;83y zos8mWB-cNV3011X%%dS6dne)8E1^&wW$c9*nkUqw*>TMBOoogUAJD6nD5(z{-kTZJ z^WKE!q4(7^5TAKFbDMZ=rAOXZQT7kFoZZ!Pfd0^eTXI}3bwf$uHwOAGw+0>AQ_KhlX#44JbsTg%m>HDVLzm7{C0 z!!2n6X$jD`OXFxA{Klnmrpx!m9nzZUmxi)a&B@W=iH2-<_fCy%a%ydF6UxiemHHiL zp~S^)WZUV+jjkG&L}!*j3ey^L?1P&C5ogGO9S9%ww@hKmRfL_=GCU5Mun9d3tE3d> zh$aP-Zr{2q8~}5G0O!IDiK4IyfbFkJ zb!ycZw~I2Fa4QZ}r^S13zc0Fw&#^|%g%wo{#t?Vq$*$ctSDRc>H&MOiV94^S5N(z8 zQ^qPn#winPafVkpomUHSWtp5Nhr+FANGtw9V{gND-<}Ufc}fQ~N#eXLkMdE*^K5{l z4j3(RJ_t`J$AE1TmS|$&7l+XXLz+>Bu0j78$TmpggF$^gzT5xFfaBiUo?Qk5VC*1( zYbeXYWDwQ&B_GV{aimYky=QrNn>IX<5lCVi4ktuK1Uj!S!DsR(!3zFqYOZK66h1jpmGZ(X0Crt%)?$O%BfmY|0an>GcXPrs= z=+?#UOYO1t?47gjqj4{UEG;;m4?p6T`80Fi*F{K-|1|# z+$1gHUfi2>F7&WpAkVI9SFzfXalZ(3wFXpf? znAt~kry`&ej3at=;?4{umSuTL0cAXnl+}cd)2OkVa#ibC6_}#Kfo&Ys8VL@@!py>y ziVYqf(;$hn=jfeVTv%aI(2TIQ)L&&(#mgbg%NlW3*0uXL$K&Y^;Zr+ho8?4IqK=9w7(M+ph8LrXMU9^q_ z6#4(BWpxZgx2E(m07mtz7WCgNch+P6!?IloK>xN(Q}5~S^s)41<8*BijO5xVsGT5? zHVXpb20@yWDv@+22wqfSGL_gtK=KIP&59#i*t^&*vt;v3HWI<-8hJFfjAk7Vmtlv) zbWGd%zM-rBt?$XT4y#gra|BElQNm90;Skj>livgW3edWLh1UHjiB)X-_iyy~UwyNf literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e25e7e98c2a4c4a8fb760ccf81c9b1bc19a868d1 GIT binary patch literal 3339 zcmZu!-ESMm5x+Ygk4K7>^<~K)O?*WVv_wVHbsyRqK@e1STqCKH#&wEZkseOBOY)?> z5AQB*i3bjgH}p@q*FN>VKmjK}`xQ)*7w;q2_(-0aS8W>#^h z)3Wf4PyZd?zG7Mbq{;H*V)6lo`a1}-m@TZ#4sDxwM>wH_-oRbYT*s$JhHm$|AO~c*RHO_ z2dWSg&7(9c3#s=ZYyEc2x!8-7F{fFQv7*#zkt@s^dqtMTIV1MbTd|1dV z)_X;+Wg#H&hLZCsy}qI}6X`)z9*yYz7UQMlNvt`U*!a~KpMDYT{qp|aN6}}G_xB&} zKX|_m$EF>q_as-vL?&ESEyeYu)I}jwRewg_RkboL!xl@Gmgxcfr;mOfiwUQ%xF18F z&=!{;2a^vl)DJ zSmU`$b^4SC3emt~AsLr_^X_!p`~<rePN};RtZ#Woo%qq zmjL(N))u>Jq}!0zXVNoUJ7=|5)+?mQTx*A2gVyykm)$t4Ywwl)%4RoTB3Mo$BGAf z%xC9IA)v_!2Y)$w&<+6jAVnw>fZxOv7|eqa&$*0snva6QprIf9W}K>E78gV`4-R-R zQHWwT5jrhlNv9cC{cgQ-8CM!kC6rlJgYjVuovM*>9Y2j_<&L>1v8&;<-Rlk0ob^PS zA0ZWpk7j)B@n;`T-vc3x1++lEEFiWUJR7IUICz!{L5{?X!4qA~wmowg9}v?z94kIabn~or zg8GKqW*@FdrrW5uxF}G?rHZFJkgw7j#ubb;jCG8S6ZeGdZ?gK!=BcN*hE{5wcwgIp zvhP`6Zk;yt)x+(xos$Ohc1&%3@@IVwm9Vity}ev77R3m;g5Us-)RqGjsW*MNKXvc? zxPK?j-T^vm)e68M;>0wssxc~ZTn+N7o+>rrXogrmudwnaj;U&ysu2}P)~ZPfIb-XD zVpaJm?ibYVs}<9@qlE4i048!$5(Fx{)x9no#MRK|CB>v_8m)+>Qc};70SUcHNzjx( zpou@v05waTZ5U0CP#5Rvv&bs)P|}SK1vgE!+@$$iL~a?ONwvSm^rlN3`CUx8TZ+kBV#o=$$t$--376nRl9Bbz;+AS(RPTQXUMl+!$HQp`J)y0KVEyo-ms_Z7x50O z`(3~CqbQFv9z|6vqHRtD@$D#jf}%cOX+#k#5{T;)g{w@pB8pLj3l@(vCHrtnJ|sfL zWQmaTavg*!x}vl8ZP#-h*YR%~dG{uLb2!lxbd^ZbHB9~jq}l`|`{(tdZ(?rZAFf|o z5$P<Qg4H_9p7mKW*7b-b4gPBAH?R$djJ3c literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/hash.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/hash.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a30f062b652744fd284b4834494c6d9de937c295 GIT binary patch literal 2183 zcmZuyOLH7G5FTls`?8%l??4!+7+AnNKrWC9sRU!<6k$WzPN)o(nvzHI&N%b3q>0J0 zE)LFtONzf>AGz>@bmhdIQ!b%3yCDu0O{t|;cWc$%U-yz;uWi6c_WvPQT*LTFGslMo z%ng|0PaxEwC^K>tBBb{?!y#@~Gc=pk3N2X8%+8(AX>_d2&ArgeTVbo=?W~=5!cN`| zyAAJTy?id5%jd)ShIg}t{6u&H8SDiA4es)?llfw}*vMMhsr+lvyoVl;%~*1`cm4L}YP5E9V@>roHrMYCZ#B%SmUlQKG>VhDcqCMJ zkEd{TS<9-HaP!IUAN=qjT3K6N`7T<&Hyqv`-hxx-KFMk(U}xP)g^cynjt>mX4VdCX zAj}96H6XYM0*fK2W@uB3+TfZ)9qPjBQV(2gsm>Y^$;_AWv$hWdICu&3iJySXFSlWr zl`+Zuio}n|2qZjC(#LGjZuB=3CYT?S!rx+kEg1FpQknS6%Z+(jfH`Nob;?=J3Mu^U zG-JLjeOkhK#fT(Z8EbAz3n59Ci9y4SFDzBO9Qi+$l}yV*JoK+=)9e0VFxZR{`1x|^ zeHZ2mOmP*+#Mm)*5JePIQ(|gKliG(Cbq;NbkI)gK?lTu@E$0vdp|y{&#)uBdaEzD9 zxU;-WvQY`CNpjVCwY7yTIU8RFr>EihPo!M}@2~o0!F14m*&pLi{JyO$%7j#IoRn$I zgmOr%-BB)O+oaBH@Xlo#hT0*8fa6WZ)RmqTe8+ySDT?ULsNjCRVjP)T6u#p57Lw}R@4Ov>WQ;LAV&a+hbQ5J8nzL6jDf@q%PQ zJS`9rXc!EtC#v(xA@L5pNSpy;UqNO{|G2T}==0frX4+U+QYW!|}qB zxZ0i~_bb>giGGWphnrQW;^0|S3&6iJ#S_S*kd$%Gb&KP3nzXcHFVg--<#wdO%Jm!j zHovGv?hMGvB77to8)a2QCQX8-ZyG!+ldiVh#|b zW^NzSacE5}ownUeKf?cmWmv|6iHu_5Gedm+sezjB0Z`Dik94(~<9FAYta;(fmjy}F z5!BnXZRr#Y6y{sQzN4(NVo-KEJ%D0m7Hp4e_$a5YH0V_;VLwl;A!AD*nWo5{wL2(O zFjaQbxBnlP_dxv%m`z*^vy0lOi#|eJpZ727oNU+dPRI$@QQ`p*p7~%)(Ch%ZT@~9!9LEet|PV8S{SD@7BU{ zz=zooqsNFwwD%g(9&@kV?108IH0u8i5zz>nLvp5N+0-mAcqLU0u5cnbCxTja_G~ga zoy|ZU?7XK+Nd@+M-#!2Sc|Lh^I{7C5;n{Thbov;)!B3=Ym*F}- z#^;rii{!!1|M17T3qkh7b|Qi~fvNuhK`~$qcyCjct}oZKH4j=xTI0edSl ze?b;Zr+`WN29tD;Nop$@S1aSHMjSyV`V$byISL$SfCo5sA{>F{;d{;j=&`dtyu;fu zoSFicqr59I&rO`?T+*gwpbzr=WkX6^JXm3#Q#l94Z!~0N-Y*tHDwZquvMJziD^Q<8 z@D7nX!e*p;AciotC3=KC$9|o6Iy$sb&zrh|TXJRJq513`3Y5k8jOaI9Q}+4%-zHs? zy3xQs%Jh~LAH01Ndo^dY0>LTd)QHCslP{+&WC d6O^siL=UzgKC~}K-vcq|+5s(bJZQ_n{SSaIfwuqv literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/install.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/install.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9e6b94dc199609521aeb99566b9e8a6a07c9e1d8 GIT binary patch literal 17356 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 B0Js1E literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/list.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/list.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b53944dc8e16c07bc4563ddd6925c35b18e8933 GIT binary patch literal 9117 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/show.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/show.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8157272806b243aaf9dfb635b94bd1e086ad5ca7 GIT binary patch literal 6458 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0850db45bd49bb5d4ad4f572c53dcc76ac0ef48 GIT binary patch literal 5220 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 WLDV{k{wgAr+UYOFKPcoxIsZQ^Zxwg| literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/cache.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/cache.py new file mode 100644 index 0000000..ec21be6 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/cache.py @@ -0,0 +1,234 @@ +from __future__ import absolute_import + +import logging +import os +import textwrap + +import pip._internal.utils.filesystem as filesystem +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.exceptions import CommandError, PipError +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import Any, List + + +logger = logging.getLogger(__name__) + + +class CacheCommand(Command): + """ + Inspect and manage pip's wheel cache. + + Subcommands: + + - dir: Show the cache directory. + - info: Show information about the cache. + - list: List filenames of packages stored in the cache. + - remove: Remove one or more package from the cache. + - purge: Remove all items from the cache. + + ```` can be a glob expression or a package name. + """ + + ignore_require_venv = True + usage = """ + %prog dir + %prog info + %prog list [] [--format=[human, abspath]] + %prog remove + %prog purge + """ + + def add_options(self): + # type: () -> None + + self.cmd_opts.add_option( + '--format', + action='store', + dest='list_format', + default="human", + choices=('human', 'abspath'), + help="Select the output format among: human (default) or abspath" + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + # type: (Values, List[Any]) -> int + handlers = { + "dir": self.get_cache_dir, + "info": self.get_cache_info, + "list": self.list_cache_items, + "remove": self.remove_cache_items, + "purge": self.purge_cache, + } + + if not options.cache_dir: + logger.error("pip cache commands can not " + "function since cache is disabled.") + return ERROR + + # Determine action + if not args or args[0] not in handlers: + logger.error( + "Need an action (%s) to perform.", + ", ".join(sorted(handlers)), + ) + return ERROR + + action = args[0] + + # Error handling happens here, not in the action-handlers. + try: + handlers[action](options, args[1:]) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + return SUCCESS + + def get_cache_dir(self, options, args): + # type: (Values, List[Any]) -> None + if args: + raise CommandError('Too many arguments') + + logger.info(options.cache_dir) + + def get_cache_info(self, options, args): + # type: (Values, List[Any]) -> None + if args: + raise CommandError('Too many arguments') + + num_http_files = len(self._find_http_files(options)) + num_packages = len(self._find_wheels(options, '*')) + + http_cache_location = self._cache_dir(options, 'http') + wheels_cache_location = self._cache_dir(options, 'wheels') + http_cache_size = filesystem.format_directory_size(http_cache_location) + wheels_cache_size = filesystem.format_directory_size( + wheels_cache_location + ) + + message = textwrap.dedent(""" + Package index page cache location: {http_cache_location} + Package index page cache size: {http_cache_size} + Number of HTTP files: {num_http_files} + Wheels location: {wheels_cache_location} + Wheels size: {wheels_cache_size} + Number of wheels: {package_count} + """).format( + http_cache_location=http_cache_location, + http_cache_size=http_cache_size, + num_http_files=num_http_files, + wheels_cache_location=wheels_cache_location, + package_count=num_packages, + wheels_cache_size=wheels_cache_size, + ).strip() + + logger.info(message) + + def list_cache_items(self, options, args): + # type: (Values, List[Any]) -> None + if len(args) > 1: + raise CommandError('Too many arguments') + + if args: + pattern = args[0] + else: + pattern = '*' + + files = self._find_wheels(options, pattern) + if options.list_format == 'human': + self.format_for_human(files) + else: + self.format_for_abspath(files) + + def format_for_human(self, files): + # type: (List[str]) -> None + if not files: + logger.info('Nothing cached.') + return + + results = [] + for filename in files: + wheel = os.path.basename(filename) + size = filesystem.format_file_size(filename) + results.append(' - {} ({})'.format(wheel, size)) + logger.info('Cache contents:\n') + logger.info('\n'.join(sorted(results))) + + def format_for_abspath(self, files): + # type: (List[str]) -> None + if not files: + return + + results = [] + for filename in files: + results.append(filename) + + logger.info('\n'.join(sorted(results))) + + def remove_cache_items(self, options, args): + # type: (Values, List[Any]) -> None + if len(args) > 1: + raise CommandError('Too many arguments') + + if not args: + raise CommandError('Please provide a pattern') + + files = self._find_wheels(options, args[0]) + + # Only fetch http files if no specific pattern given + if args[0] == '*': + files += self._find_http_files(options) + + if not files: + raise CommandError('No matching packages') + + for filename in files: + os.unlink(filename) + logger.debug('Removed %s', filename) + logger.info('Files removed: %s', len(files)) + + def purge_cache(self, options, args): + # type: (Values, List[Any]) -> None + if args: + raise CommandError('Too many arguments') + + return self.remove_cache_items(options, ['*']) + + def _cache_dir(self, options, subdir): + # type: (Values, str) -> str + return os.path.join(options.cache_dir, subdir) + + def _find_http_files(self, options): + # type: (Values) -> List[str] + http_dir = self._cache_dir(options, 'http') + return filesystem.find_files(http_dir, '*') + + def _find_wheels(self, options, pattern): + # type: (Values, str) -> List[str] + wheel_dir = self._cache_dir(options, 'wheels') + + # The wheel filename format, as specified in PEP 427, is: + # {distribution}-{version}(-{build})?-{python}-{abi}-{platform}.whl + # + # Additionally, non-alphanumeric values in the distribution are + # normalized to underscores (_), meaning hyphens can never occur + # before `-{version}`. + # + # Given that information: + # - If the pattern we're given contains a hyphen (-), the user is + # providing at least the version. Thus, we can just append `*.whl` + # to match the rest of it. + # - If the pattern we're given doesn't contain a hyphen (-), the + # user is only providing the name. Thus, we append `-*.whl` to + # match the hyphen before the version, followed by anything else. + # + # PEP 427: https://www.python.org/dev/peps/pep-0427/ + pattern = pattern + ("*.whl" if "-" in pattern else "-*.whl") + + return filesystem.find_files(wheel_dir, pattern) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/check.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/check.py new file mode 100644 index 0000000..e066bb6 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/check.py @@ -0,0 +1,51 @@ +import logging + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.operations.check import ( + check_package_set, + create_package_set_from_installed, +) +from pip._internal.utils.misc import write_output +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +logger = logging.getLogger(__name__) + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import Any, List + + +class CheckCommand(Command): + """Verify installed packages have compatible dependencies.""" + + usage = """ + %prog [options]""" + + def run(self, options, args): + # type: (Values, List[Any]) -> int + + package_set, parsing_probs = create_package_set_from_installed() + missing, conflicting = check_package_set(package_set) + + for project_name in missing: + version = package_set[project_name].version + for dependency in missing[project_name]: + write_output( + "%s %s requires %s, which is not installed.", + project_name, version, dependency[0], + ) + + for project_name in conflicting: + version = package_set[project_name].version + for dep_name, dep_version, req in conflicting[project_name]: + write_output( + "%s %s has requirement %s, but you have %s %s.", + project_name, version, req, dep_name, dep_version, + ) + + if missing or conflicting or parsing_probs: + return ERROR + else: + write_output("No broken requirements found.") + return SUCCESS diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/completion.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/completion.py new file mode 100644 index 0000000..b19f1ed --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/completion.py @@ -0,0 +1,98 @@ +from __future__ import absolute_import + +import sys +import textwrap + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.utils.misc import get_prog +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import List + +BASE_COMPLETION = """ +# pip {shell} completion start{script}# pip {shell} completion end +""" + +COMPLETION_SCRIPTS = { + 'bash': """ + _pip_completion() + {{ + COMPREPLY=( $( COMP_WORDS="${{COMP_WORDS[*]}}" \\ + COMP_CWORD=$COMP_CWORD \\ + PIP_AUTO_COMPLETE=1 $1 2>/dev/null ) ) + }} + complete -o default -F _pip_completion {prog} + """, + 'zsh': """ + function _pip_completion {{ + local words cword + read -Ac words + read -cn cword + reply=( $( COMP_WORDS="$words[*]" \\ + COMP_CWORD=$(( cword-1 )) \\ + PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null )) + }} + compctl -K _pip_completion {prog} + """, + 'fish': """ + function __fish_complete_pip + set -lx COMP_WORDS (commandline -o) "" + set -lx COMP_CWORD ( \\ + math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\ + ) + set -lx PIP_AUTO_COMPLETE 1 + string split \\ -- (eval $COMP_WORDS[1]) + end + complete -fa "(__fish_complete_pip)" -c {prog} + """, +} + + +class CompletionCommand(Command): + """A helper command to be used for command completion.""" + + ignore_require_venv = True + + def add_options(self): + # type: () -> None + self.cmd_opts.add_option( + '--bash', '-b', + action='store_const', + const='bash', + dest='shell', + help='Emit completion code for bash') + self.cmd_opts.add_option( + '--zsh', '-z', + action='store_const', + const='zsh', + dest='shell', + help='Emit completion code for zsh') + self.cmd_opts.add_option( + '--fish', '-f', + action='store_const', + const='fish', + dest='shell', + help='Emit completion code for fish') + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + # type: (Values, List[str]) -> int + """Prints the completion code of the given shell""" + shells = COMPLETION_SCRIPTS.keys() + shell_options = ['--' + shell for shell in sorted(shells)] + if options.shell in shells: + script = textwrap.dedent( + COMPLETION_SCRIPTS.get(options.shell, '').format( + prog=get_prog()) + ) + print(BASE_COMPLETION.format(script=script, shell=options.shell)) + return SUCCESS + else: + sys.stderr.write( + 'ERROR: You must pass {}\n' .format(' or '.join(shell_options)) + ) + return SUCCESS diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/configuration.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/configuration.py new file mode 100644 index 0000000..1ab90b4 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/configuration.py @@ -0,0 +1,280 @@ +import logging +import os +import subprocess + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.configuration import Configuration, get_configuration_files, kinds +from pip._internal.exceptions import PipError +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import get_prog, write_output +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import Any, List, Optional + + from pip._internal.configuration import Kind + +logger = logging.getLogger(__name__) + + +class ConfigurationCommand(Command): + """ + Manage local and global configuration. + + Subcommands: + + - list: List the active configuration (or from the file specified) + - edit: Edit the configuration file in an editor + - get: Get the value associated with name + - set: Set the name=value + - unset: Unset the value associated with name + - debug: List the configuration files and values defined under them + + If none of --user, --global and --site are passed, a virtual + environment configuration file is used if one is active and the file + exists. Otherwise, all modifications happen on the to the user file by + default. + """ + + ignore_require_venv = True + usage = """ + %prog [] list + %prog [] [--editor ] edit + + %prog [] get name + %prog [] set name value + %prog [] unset name + %prog [] debug + """ + + def add_options(self): + # type: () -> None + self.cmd_opts.add_option( + '--editor', + dest='editor', + action='store', + default=None, + help=( + 'Editor to use to edit the file. Uses VISUAL or EDITOR ' + 'environment variables if not provided.' + ) + ) + + self.cmd_opts.add_option( + '--global', + dest='global_file', + action='store_true', + default=False, + help='Use the system-wide configuration file only' + ) + + self.cmd_opts.add_option( + '--user', + dest='user_file', + action='store_true', + default=False, + help='Use the user configuration file only' + ) + + self.cmd_opts.add_option( + '--site', + dest='site_file', + action='store_true', + default=False, + help='Use the current environment configuration file only' + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + # type: (Values, List[str]) -> int + handlers = { + "list": self.list_values, + "edit": self.open_in_editor, + "get": self.get_name, + "set": self.set_name_value, + "unset": self.unset_name, + "debug": self.list_config_values, + } + + # Determine action + if not args or args[0] not in handlers: + logger.error( + "Need an action (%s) to perform.", + ", ".join(sorted(handlers)), + ) + return ERROR + + action = args[0] + + # Determine which configuration files are to be loaded + # Depends on whether the command is modifying. + try: + load_only = self._determine_file( + options, need_value=(action in ["get", "set", "unset", "edit"]) + ) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + # Load a new configuration + self.configuration = Configuration( + isolated=options.isolated_mode, load_only=load_only + ) + self.configuration.load() + + # Error handling happens here, not in the action-handlers. + try: + handlers[action](options, args[1:]) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + return SUCCESS + + def _determine_file(self, options, need_value): + # type: (Values, bool) -> Optional[Kind] + file_options = [key for key, value in ( + (kinds.USER, options.user_file), + (kinds.GLOBAL, options.global_file), + (kinds.SITE, options.site_file), + ) if value] + + if not file_options: + if not need_value: + return None + # Default to user, unless there's a site file. + elif any( + os.path.exists(site_config_file) + for site_config_file in get_configuration_files()[kinds.SITE] + ): + return kinds.SITE + else: + return kinds.USER + elif len(file_options) == 1: + return file_options[0] + + raise PipError( + "Need exactly one file to operate upon " + "(--user, --site, --global) to perform." + ) + + def list_values(self, options, args): + # type: (Values, List[str]) -> None + self._get_n_args(args, "list", n=0) + + for key, value in sorted(self.configuration.items()): + write_output("%s=%r", key, value) + + def get_name(self, options, args): + # type: (Values, List[str]) -> None + key = self._get_n_args(args, "get [name]", n=1) + value = self.configuration.get_value(key) + + write_output("%s", value) + + def set_name_value(self, options, args): + # type: (Values, List[str]) -> None + key, value = self._get_n_args(args, "set [name] [value]", n=2) + self.configuration.set_value(key, value) + + self._save_configuration() + + def unset_name(self, options, args): + # type: (Values, List[str]) -> None + key = self._get_n_args(args, "unset [name]", n=1) + self.configuration.unset_value(key) + + self._save_configuration() + + def list_config_values(self, options, args): + # type: (Values, List[str]) -> None + """List config key-value pairs across different config files""" + self._get_n_args(args, "debug", n=0) + + self.print_env_var_values() + # Iterate over config files and print if they exist, and the + # key-value pairs present in them if they do + for variant, files in sorted(self.configuration.iter_config_files()): + write_output("%s:", variant) + for fname in files: + with indent_log(): + file_exists = os.path.exists(fname) + write_output("%s, exists: %r", + fname, file_exists) + if file_exists: + self.print_config_file_values(variant) + + def print_config_file_values(self, variant): + # type: (Kind) -> None + """Get key-value pairs from the file of a variant""" + for name, value in self.configuration.\ + get_values_in_config(variant).items(): + with indent_log(): + write_output("%s: %s", name, value) + + def print_env_var_values(self): + # type: () -> None + """Get key-values pairs present as environment variables""" + write_output("%s:", 'env_var') + with indent_log(): + for key, value in sorted(self.configuration.get_environ_vars()): + env_var = 'PIP_{}'.format(key.upper()) + write_output("%s=%r", env_var, value) + + def open_in_editor(self, options, args): + # type: (Values, List[str]) -> None + editor = self._determine_editor(options) + + fname = self.configuration.get_file_to_edit() + if fname is None: + raise PipError("Could not determine appropriate file.") + + try: + subprocess.check_call([editor, fname]) + except subprocess.CalledProcessError as e: + raise PipError( + "Editor Subprocess exited with exit code {}" + .format(e.returncode) + ) + + def _get_n_args(self, args, example, n): + # type: (List[str], str, int) -> Any + """Helper to make sure the command got the right number of arguments + """ + if len(args) != n: + msg = ( + 'Got unexpected number of arguments, expected {}. ' + '(example: "{} config {}")' + ).format(n, get_prog(), example) + raise PipError(msg) + + if n == 1: + return args[0] + else: + return args + + def _save_configuration(self): + # type: () -> None + # We successfully ran a modifying command. Need to save the + # configuration. + try: + self.configuration.save() + except Exception: + logger.exception( + "Unable to save configuration. Please report this as a bug." + ) + raise PipError("Internal Error.") + + def _determine_editor(self, options): + # type: (Values) -> str + if options.editor is not None: + return options.editor + elif "VISUAL" in os.environ: + return os.environ["VISUAL"] + elif "EDITOR" in os.environ: + return os.environ["EDITOR"] + else: + raise PipError("Could not determine editor to use.") diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/debug.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/debug.py new file mode 100644 index 0000000..0ccc63a --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/debug.py @@ -0,0 +1,251 @@ +from __future__ import absolute_import + +import locale +import logging +import os +import sys + +import pip._vendor +from pip._vendor import pkg_resources +from pip._vendor.certifi import where + +from pip import __file__ as pip_location +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.cli.cmdoptions import make_target_python +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import get_pip_version +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from types import ModuleType + from typing import Dict, List, Optional + + from pip._internal.configuration import Configuration + +logger = logging.getLogger(__name__) + + +def show_value(name, value): + # type: (str, Optional[str]) -> None + logger.info('%s: %s', name, value) + + +def show_sys_implementation(): + # type: () -> None + logger.info('sys.implementation:') + if hasattr(sys, 'implementation'): + implementation = sys.implementation # type: ignore + implementation_name = implementation.name + else: + implementation_name = '' + + with indent_log(): + show_value('name', implementation_name) + + +def create_vendor_txt_map(): + # type: () -> Dict[str, str] + vendor_txt_path = os.path.join( + os.path.dirname(pip_location), + '_vendor', + 'vendor.txt' + ) + + with open(vendor_txt_path) as f: + # Purge non version specifying lines. + # Also, remove any space prefix or suffixes (including comments). + lines = [line.strip().split(' ', 1)[0] + for line in f.readlines() if '==' in line] + + # Transform into "module" -> version dict. + return dict(line.split('==', 1) for line in lines) # type: ignore + +def create_debundle_txt_map(): + # type: () -> Dict[str, str] + wheels = [fn for fn in os.listdir(pip._vendor.WHEEL_DIR)] + # Transform into "module" -> version dict. + return dict((wheel.split('-')[0], wheel.split('-')[1]) for wheel in wheels) # type: ignore + +def get_module_from_module_name(module_name): + # type: (str) -> ModuleType + # Module name can be uppercase in vendor.txt for some reason... + module_name = module_name.lower() + # PATCH: setuptools is actually only pkg_resources. + if module_name == 'setuptools': + module_name = 'pkg_resources' + + __import__( + 'pip._vendor.{}'.format(module_name), + globals(), + locals(), + level=0 + ) + return getattr(pip._vendor, module_name) + + +def get_vendor_version_from_module(module_name): + # type: (str) -> Optional[str] + module = get_module_from_module_name(module_name) + version = getattr(module, '__version__', None) + + if not version: + # Try to find version in debundled module info + # The type for module.__file__ is Optional[str] in + # Python 2, and str in Python 3. The type: ignore is + # added to account for Python 2, instead of a cast + # and should be removed once we drop Python 2 support + pkg_set = pkg_resources.WorkingSet( + [os.path.dirname(module.__file__)] # type: ignore + ) + package = pkg_set.find(pkg_resources.Requirement.parse(module_name)) + version = getattr(package, 'version', None) + + return version + + +def show_actual_vendor_versions(vendor_txt_versions): + # type: (Dict[str, str]) -> None + """Log the actual version and print extra info if there is + a conflict or if the actual version could not be imported. + """ + for module_name, expected_version in vendor_txt_versions.items(): + extra_message = '' + actual_version = get_vendor_version_from_module(module_name) + if not actual_version: + extra_message = ' (Unable to locate actual module version, using'\ + ' vendor.txt specified version)' + actual_version = expected_version + elif actual_version != expected_version: + extra_message = ' (CONFLICT: vendor.txt suggests version should'\ + ' be {})'.format(expected_version) + logger.info('%s==%s%s', module_name, actual_version, extra_message) + + +def show_vendor_versions(): + # type: () -> None + logger.info('vendored library versions:') + + vendor_txt_versions = create_vendor_txt_map() + with indent_log(): + show_actual_vendor_versions(vendor_txt_versions) + +def show_debundled_versions(): + # type: () -> None + logger.info('debundled wheel versions:') + debundle_txt_versions = create_debundle_txt_map() + for module_name, installed_version in sorted(debundle_txt_versions.items()): + with indent_log(): + logger.info( + '{name}=={actual}'.format( + name=module_name, + actual=installed_version, + ) + ) + +def show_tags(options): + # type: (Values) -> None + tag_limit = 10 + + target_python = make_target_python(options) + tags = target_python.get_tags() + + # Display the target options that were explicitly provided. + formatted_target = target_python.format_given() + suffix = '' + if formatted_target: + suffix = ' (target: {})'.format(formatted_target) + + msg = 'Compatible tags: {}{}'.format(len(tags), suffix) + logger.info(msg) + + if options.verbose < 1 and len(tags) > tag_limit: + tags_limited = True + tags = tags[:tag_limit] + else: + tags_limited = False + + with indent_log(): + for tag in tags: + logger.info(str(tag)) + + if tags_limited: + msg = ( + '...\n' + '[First {tag_limit} tags shown. Pass --verbose to show all.]' + ).format(tag_limit=tag_limit) + logger.info(msg) + + +def ca_bundle_info(config): + # type: (Configuration) -> str + levels = set() + for key, _ in config.items(): + levels.add(key.split('.')[0]) + + if not levels: + return "Not specified" + + levels_that_override_global = ['install', 'wheel', 'download'] + global_overriding_level = [ + level for level in levels if level in levels_that_override_global + ] + if not global_overriding_level: + return 'global' + + if 'global' in levels: + levels.remove('global') + return ", ".join(levels) + + +class DebugCommand(Command): + """ + Display debug information. + """ + + usage = """ + %prog """ + ignore_require_venv = True + + def add_options(self): + # type: () -> None + cmdoptions.add_target_python_options(self.cmd_opts) + self.parser.insert_option_group(0, self.cmd_opts) + self.parser.config.load() + + def run(self, options, args): + # type: (Values, List[str]) -> int + logger.warning( + "This command is only meant for debugging. " + "Do not use this with automation for parsing and getting these " + "details, since the output and options of this command may " + "change without notice." + ) + show_value('pip version', get_pip_version()) + show_value('sys.version', sys.version) + show_value('sys.executable', sys.executable) + show_value('sys.getdefaultencoding', sys.getdefaultencoding()) + show_value('sys.getfilesystemencoding', sys.getfilesystemencoding()) + show_value( + 'locale.getpreferredencoding', locale.getpreferredencoding(), + ) + show_value('sys.platform', sys.platform) + show_sys_implementation() + + show_value("'cert' config value", ca_bundle_info(self.parser.config)) + show_value("REQUESTS_CA_BUNDLE", os.environ.get('REQUESTS_CA_BUNDLE')) + show_value("CURL_CA_BUNDLE", os.environ.get('CURL_CA_BUNDLE')) + show_value("pip._vendor.certifi.where()", where()) + show_value("pip._vendor.DEBUNDLED", pip._vendor.DEBUNDLED) + + if not pip._vendor.DEBUNDLED: + show_vendor_versions() + else: + show_value("pip._vendor.WHEEL_DIR", pip._vendor.WHEEL_DIR) + show_debundled_versions() + + show_tags(options) + + return SUCCESS diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/download.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/download.py new file mode 100644 index 0000000..7405870 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/download.py @@ -0,0 +1,143 @@ +from __future__ import absolute_import + +import logging +import os + +from pip._internal.cli import cmdoptions +from pip._internal.cli.cmdoptions import make_target_python +from pip._internal.cli.req_command import RequirementCommand, with_cleanup +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.req.req_tracker import get_requirement_tracker +from pip._internal.utils.misc import ensure_dir, normalize_path, write_output +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import List + +logger = logging.getLogger(__name__) + + +class DownloadCommand(RequirementCommand): + """ + Download packages from: + + - PyPI (and other indexes) using requirement specifiers. + - VCS project urls. + - Local project directories. + - Local or remote source archives. + + pip also supports downloading from "requirements files", which provide + an easy way to specify a whole environment to be downloaded. + """ + + usage = """ + %prog [options] [package-index-options] ... + %prog [options] -r [package-index-options] ... + %prog [options] ... + %prog [options] ... + %prog [options] ...""" + + def add_options(self): + # type: () -> None + self.cmd_opts.add_option(cmdoptions.constraints()) + self.cmd_opts.add_option(cmdoptions.requirements()) + self.cmd_opts.add_option(cmdoptions.build_dir()) + self.cmd_opts.add_option(cmdoptions.no_deps()) + self.cmd_opts.add_option(cmdoptions.global_options()) + self.cmd_opts.add_option(cmdoptions.no_binary()) + self.cmd_opts.add_option(cmdoptions.only_binary()) + self.cmd_opts.add_option(cmdoptions.prefer_binary()) + self.cmd_opts.add_option(cmdoptions.src()) + self.cmd_opts.add_option(cmdoptions.pre()) + self.cmd_opts.add_option(cmdoptions.require_hashes()) + self.cmd_opts.add_option(cmdoptions.progress_bar()) + self.cmd_opts.add_option(cmdoptions.no_build_isolation()) + self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) + + self.cmd_opts.add_option( + '-d', '--dest', '--destination-dir', '--destination-directory', + dest='download_dir', + metavar='dir', + default=os.curdir, + help=("Download packages into ."), + ) + + cmdoptions.add_target_python_options(self.cmd_opts) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + @with_cleanup + def run(self, options, args): + # type: (Values, List[str]) -> int + + options.ignore_installed = True + # editable doesn't really make sense for `pip download`, but the bowels + # of the RequirementSet code require that property. + options.editables = [] + + cmdoptions.check_dist_restriction(options) + + options.download_dir = normalize_path(options.download_dir) + ensure_dir(options.download_dir) + + session = self.get_default_session(options) + + target_python = make_target_python(options) + finder = self._build_package_finder( + options=options, + session=session, + target_python=target_python, + ) + + req_tracker = self.enter_context(get_requirement_tracker()) + + directory = TempDirectory( + delete=not options.no_clean, + kind="download", + globally_managed=True, + ) + + reqs = self.get_requirements(args, options, finder, session) + + preparer = self.make_requirement_preparer( + temp_build_dir=directory, + options=options, + req_tracker=req_tracker, + session=session, + finder=finder, + download_dir=options.download_dir, + use_user_site=False, + ) + + resolver = self.make_resolver( + preparer=preparer, + finder=finder, + options=options, + py_version_info=options.python_version, + ) + + self.trace_basic_info(finder) + + requirement_set = resolver.resolve( + reqs, check_supported_wheels=True + ) + + downloaded = [] # type: List[str] + for req in requirement_set.requirements.values(): + if req.satisfied_by is None: + assert req.name is not None + preparer.save_linked_requirement(req) + downloaded.append(req.name) + if downloaded: + write_output('Successfully downloaded %s', ' '.join(downloaded)) + + return SUCCESS diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/freeze.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/freeze.py new file mode 100644 index 0000000..5f71bd3 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/freeze.py @@ -0,0 +1,116 @@ +from __future__ import absolute_import + +import sys + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.models.format_control import FormatControl +from pip._internal.operations.freeze import freeze +from pip._internal.utils.compat import stdlib_pkgs +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +DEV_PKGS = {'pip', 'setuptools', 'distribute', 'wheel', 'pkg-resources'} + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import List + + +class FreezeCommand(Command): + """ + Output installed packages in requirements format. + + packages are listed in a case-insensitive sorted order. + """ + + usage = """ + %prog [options]""" + log_streams = ("ext://sys.stderr", "ext://sys.stderr") + + def add_options(self): + # type: () -> None + self.cmd_opts.add_option( + '-r', '--requirement', + dest='requirements', + action='append', + default=[], + metavar='file', + help="Use the order in the given requirements file and its " + "comments when generating output. This option can be " + "used multiple times.") + self.cmd_opts.add_option( + '-f', '--find-links', + dest='find_links', + action='append', + default=[], + metavar='URL', + help='URL for finding packages, which will be added to the ' + 'output.') + self.cmd_opts.add_option( + '-l', '--local', + dest='local', + action='store_true', + default=False, + help='If in a virtualenv that has global access, do not output ' + 'globally-installed packages.') + self.cmd_opts.add_option( + '--user', + dest='user', + action='store_true', + default=False, + help='Only output packages installed in user-site.') + self.cmd_opts.add_option(cmdoptions.list_path()) + self.cmd_opts.add_option( + '--all', + dest='freeze_all', + action='store_true', + help='Do not skip these packages in the output:' + ' {}'.format(', '.join(DEV_PKGS))) + self.cmd_opts.add_option( + '--exclude-editable', + dest='exclude_editable', + action='store_true', + help='Exclude editable package from output.') + self.cmd_opts.add_option(cmdoptions.list_exclude()) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + # type: (Values, List[str]) -> int + format_control = FormatControl(set(), set()) + wheel_cache = WheelCache(options.cache_dir, format_control) + skip = set(stdlib_pkgs) + if not options.freeze_all: + skip.update(DEV_PKGS) + + if options.excludes: + skip.update(options.excludes) + + cmdoptions.check_list_path_option(options) + + if options.find_links: + deprecated( + "--find-links option in pip freeze is deprecated.", + replacement=None, + gone_in="21.2", + issue=9069, + ) + + freeze_kwargs = dict( + requirement=options.requirements, + find_links=options.find_links, + local_only=options.local, + user_only=options.user, + paths=options.path, + isolated=options.isolated_mode, + wheel_cache=wheel_cache, + skip=skip, + exclude_editable=options.exclude_editable, + ) + + for line in freeze(**freeze_kwargs): + sys.stdout.write(line + '\n') + return SUCCESS diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/hash.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/hash.py new file mode 100644 index 0000000..37831c3 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/hash.py @@ -0,0 +1,63 @@ +from __future__ import absolute_import + +import hashlib +import logging +import sys + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.utils.hashes import FAVORITE_HASH, STRONG_HASHES +from pip._internal.utils.misc import read_chunks, write_output +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import List + +logger = logging.getLogger(__name__) + + +class HashCommand(Command): + """ + Compute a hash of a local package archive. + + These can be used with --hash in a requirements file to do repeatable + installs. + """ + + usage = '%prog [options] ...' + ignore_require_venv = True + + def add_options(self): + # type: () -> None + self.cmd_opts.add_option( + '-a', '--algorithm', + dest='algorithm', + choices=STRONG_HASHES, + action='store', + default=FAVORITE_HASH, + help='The hash algorithm to use: one of {}'.format( + ', '.join(STRONG_HASHES))) + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + # type: (Values, List[str]) -> int + if not args: + self.parser.print_usage(sys.stderr) + return ERROR + + algorithm = options.algorithm + for path in args: + write_output('%s:\n--hash=%s:%s', + path, algorithm, _hash_of_file(path, algorithm)) + return SUCCESS + + +def _hash_of_file(path, algorithm): + # type: (str, str) -> str + """Return the hash digest of a file.""" + with open(path, 'rb') as archive: + hash = hashlib.new(algorithm) + for chunk in read_chunks(archive): + hash.update(chunk) + return hash.hexdigest() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/help.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/help.py new file mode 100644 index 0000000..2ab2b6d --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/help.py @@ -0,0 +1,46 @@ +from __future__ import absolute_import + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import CommandError +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import List + + +class HelpCommand(Command): + """Show help for commands""" + + usage = """ + %prog """ + ignore_require_venv = True + + def run(self, options, args): + # type: (Values, List[str]) -> int + from pip._internal.commands import ( + commands_dict, + create_command, + get_similar_commands, + ) + + try: + # 'pip help' with no args is handled by pip.__init__.parseopt() + cmd_name = args[0] # the command we need help for + except IndexError: + return SUCCESS + + if cmd_name not in commands_dict: + guess = get_similar_commands(cmd_name) + + msg = ['unknown command "{}"'.format(cmd_name)] + if guess: + msg.append('maybe you meant "{}"'.format(guess)) + + raise CommandError(' - '.join(msg)) + + command = create_command(cmd_name) + command.parser.print_help() + + return SUCCESS diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/install.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/install.py new file mode 100644 index 0000000..d91af88 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/install.py @@ -0,0 +1,763 @@ +from __future__ import absolute_import + +import errno +import logging +import operator +import os +import shutil +import site +from optparse import SUPPRESS_HELP + +from pip._vendor import pkg_resources +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.cmdoptions import make_target_python +from pip._internal.cli.req_command import RequirementCommand, with_cleanup +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.exceptions import CommandError, InstallationError +from pip._internal.locations import distutils_scheme +from pip._internal.operations.check import check_install_conflicts +from pip._internal.req import install_given_reqs +from pip._internal.req.req_tracker import get_requirement_tracker +from pip._internal.utils.distutils_args import parse_distutils_args +from pip._internal.utils.filesystem import test_writable_dir +from pip._internal.utils.misc import ( + ensure_dir, + get_installed_version, + get_pip_version, + protect_pip_from_modification_on_windows, + write_output, +) +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.virtualenv import virtualenv_no_global +from pip._internal.wheel_builder import build, should_build_for_install_command + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import Iterable, List, Optional + + from pip._internal.models.format_control import FormatControl + from pip._internal.operations.check import ConflictDetails + from pip._internal.req.req_install import InstallRequirement + from pip._internal.wheel_builder import BinaryAllowedPredicate + +from pip._internal.locations import running_under_virtualenv + +logger = logging.getLogger(__name__) + + +def get_check_binary_allowed(format_control): + # type: (FormatControl) -> BinaryAllowedPredicate + def check_binary_allowed(req): + # type: (InstallRequirement) -> bool + if req.use_pep517: + return True + canonical_name = canonicalize_name(req.name) + allowed_formats = format_control.get_allowed_formats(canonical_name) + return "binary" in allowed_formats + + return check_binary_allowed + + +class InstallCommand(RequirementCommand): + """ + Install packages from: + + - PyPI (and other indexes) using requirement specifiers. + - VCS project urls. + - Local project directories. + - Local or remote source archives. + + pip also supports installing from "requirements files", which provide + an easy way to specify a whole environment to be installed. + """ + + usage = """ + %prog [options] [package-index-options] ... + %prog [options] -r [package-index-options] ... + %prog [options] [-e] ... + %prog [options] [-e] ... + %prog [options] ...""" + + def add_options(self): + # type: () -> None + self.cmd_opts.add_option(cmdoptions.requirements()) + self.cmd_opts.add_option(cmdoptions.constraints()) + self.cmd_opts.add_option(cmdoptions.no_deps()) + self.cmd_opts.add_option(cmdoptions.pre()) + + self.cmd_opts.add_option(cmdoptions.editable()) + self.cmd_opts.add_option( + '-t', '--target', + dest='target_dir', + metavar='dir', + default=None, + help='Install packages into . ' + 'By default this will not replace existing files/folders in ' + '. Use --upgrade to replace existing packages in ' + 'with new versions.' + ) + cmdoptions.add_target_python_options(self.cmd_opts) + + self.cmd_opts.add_option( + '--user', + dest='use_user_site', + action='store_true', + help="Install to the Python user install directory for your " + "platform. Typically ~/.local/, or %APPDATA%\\Python on " + "Windows. (See the Python documentation for site.USER_BASE " + "for full details.) On Debian systems, this is the " + "default when running outside of a virtual environment " + "and not as root.") + + self.cmd_opts.add_option( + '--no-user', + dest='use_system_location', + action='store_true', + help=SUPPRESS_HELP) + self.cmd_opts.add_option( + '--root', + dest='root_path', + metavar='dir', + default=None, + help="Install everything relative to this alternate root " + "directory.") + self.cmd_opts.add_option( + '--prefix', + dest='prefix_path', + metavar='dir', + default=None, + help="Installation prefix where lib, bin and other top-level " + "folders are placed") + + self.cmd_opts.add_option( + '--system', + dest='use_system_location', + action='store_true', + help="Install using the system scheme (overrides --user on " + "Debian systems)") + + self.cmd_opts.add_option(cmdoptions.build_dir()) + + self.cmd_opts.add_option(cmdoptions.src()) + + self.cmd_opts.add_option( + '-U', '--upgrade', + dest='upgrade', + action='store_true', + help='Upgrade all specified packages to the newest available ' + 'version. The handling of dependencies depends on the ' + 'upgrade-strategy used.' + ) + + self.cmd_opts.add_option( + '--upgrade-strategy', + dest='upgrade_strategy', + default='only-if-needed', + choices=['only-if-needed', 'eager'], + help='Determines how dependency upgrading should be handled ' + '[default: %default]. ' + '"eager" - dependencies are upgraded regardless of ' + 'whether the currently installed version satisfies the ' + 'requirements of the upgraded package(s). ' + '"only-if-needed" - are upgraded only when they do not ' + 'satisfy the requirements of the upgraded package(s).' + ) + + self.cmd_opts.add_option( + '--force-reinstall', + dest='force_reinstall', + action='store_true', + help='Reinstall all packages even if they are already ' + 'up-to-date.') + + self.cmd_opts.add_option( + '-I', '--ignore-installed', + dest='ignore_installed', + action='store_true', + help='Ignore the installed packages, overwriting them. ' + 'This can break your system if the existing package ' + 'is of a different version or was installed ' + 'with a different package manager!' + ) + + self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) + self.cmd_opts.add_option(cmdoptions.no_build_isolation()) + self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) + + self.cmd_opts.add_option(cmdoptions.install_options()) + self.cmd_opts.add_option(cmdoptions.global_options()) + + self.cmd_opts.add_option( + "--compile", + action="store_true", + dest="compile", + default=True, + help="Compile Python source files to bytecode", + ) + + self.cmd_opts.add_option( + "--no-compile", + action="store_false", + dest="compile", + help="Do not compile Python source files to bytecode", + ) + + self.cmd_opts.add_option( + "--no-warn-script-location", + action="store_false", + dest="warn_script_location", + default=True, + help="Do not warn when installing scripts outside PATH", + ) + self.cmd_opts.add_option( + "--no-warn-conflicts", + action="store_false", + dest="warn_about_conflicts", + default=True, + help="Do not warn about broken dependencies", + ) + + self.cmd_opts.add_option(cmdoptions.no_binary()) + self.cmd_opts.add_option(cmdoptions.only_binary()) + self.cmd_opts.add_option(cmdoptions.prefer_binary()) + self.cmd_opts.add_option(cmdoptions.require_hashes()) + self.cmd_opts.add_option(cmdoptions.progress_bar()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + @with_cleanup + def run(self, options, args): + # type: (Values, List[str]) -> int + if options.use_user_site and options.target_dir is not None: + raise CommandError("Can not combine '--user' and '--target'") + + cmdoptions.check_install_build_global(options) + upgrade_strategy = "to-satisfy-only" + if options.upgrade: + upgrade_strategy = options.upgrade_strategy + + cmdoptions.check_dist_restriction(options, check_target=True) + + if options.python_version: + python_versions = [options.python_version] + else: + python_versions = None + + # compute install location defaults + if (not options.use_user_site and not options.prefix_path and not + options.target_dir and not options.use_system_location): + if not running_under_virtualenv() and os.geteuid() != 0: + options.use_user_site = True + + if options.use_system_location: + options.use_user_site = False + + options.src_dir = os.path.abspath(options.src_dir) + install_options = options.install_options or [] + + logger.debug("Using %s", get_pip_version()) + options.use_user_site = decide_user_install( + options.use_user_site, + prefix_path=options.prefix_path, + target_dir=options.target_dir, + root_path=options.root_path, + isolated_mode=options.isolated_mode, + ) + + target_temp_dir = None # type: Optional[TempDirectory] + target_temp_dir_path = None # type: Optional[str] + if options.target_dir: + options.ignore_installed = True + options.target_dir = os.path.abspath(options.target_dir) + if (os.path.exists(options.target_dir) and not + os.path.isdir(options.target_dir)): + raise CommandError( + "Target path exists but is not a directory, will not " + "continue." + ) + + # Create a target directory for using with the target option + target_temp_dir = TempDirectory(kind="target") + target_temp_dir_path = target_temp_dir.path + self.enter_context(target_temp_dir) + + global_options = options.global_options or [] + + session = self.get_default_session(options) + + target_python = make_target_python(options) + finder = self._build_package_finder( + options=options, + session=session, + target_python=target_python, + ignore_requires_python=options.ignore_requires_python, + ) + wheel_cache = WheelCache(options.cache_dir, options.format_control) + + req_tracker = self.enter_context(get_requirement_tracker()) + + directory = TempDirectory( + delete=not options.no_clean, + kind="install", + globally_managed=True, + ) + + try: + reqs = self.get_requirements(args, options, finder, session) + + reject_location_related_install_options( + reqs, options.install_options + ) + + preparer = self.make_requirement_preparer( + temp_build_dir=directory, + options=options, + req_tracker=req_tracker, + session=session, + finder=finder, + use_user_site=options.use_user_site, + ) + resolver = self.make_resolver( + preparer=preparer, + finder=finder, + options=options, + wheel_cache=wheel_cache, + use_user_site=options.use_user_site, + ignore_installed=options.ignore_installed, + ignore_requires_python=options.ignore_requires_python, + force_reinstall=options.force_reinstall, + upgrade_strategy=upgrade_strategy, + use_pep517=options.use_pep517, + ) + + self.trace_basic_info(finder) + + requirement_set = resolver.resolve( + reqs, check_supported_wheels=not options.target_dir + ) + + try: + pip_req = requirement_set.get_requirement("pip") + except KeyError: + modifying_pip = False + else: + # If we're not replacing an already installed pip, + # we're not modifying it. + modifying_pip = pip_req.satisfied_by is None + protect_pip_from_modification_on_windows( + modifying_pip=modifying_pip + ) + + check_binary_allowed = get_check_binary_allowed( + finder.format_control + ) + + reqs_to_build = [ + r for r in requirement_set.requirements.values() + if should_build_for_install_command( + r, check_binary_allowed + ) + ] + + _, build_failures = build( + reqs_to_build, + wheel_cache=wheel_cache, + verify=True, + build_options=[], + global_options=[], + ) + + # If we're using PEP 517, we cannot do a direct install + # so we fail here. + pep517_build_failure_names = [ + r.name # type: ignore + for r in build_failures if r.use_pep517 + ] # type: List[str] + if pep517_build_failure_names: + raise InstallationError( + "Could not build wheels for {} which use" + " PEP 517 and cannot be installed directly".format( + ", ".join(pep517_build_failure_names) + ) + ) + + # For now, we just warn about failures building legacy + # requirements, as we'll fall through to a direct + # install for those. + for r in build_failures: + if not r.use_pep517: + r.legacy_install_reason = 8368 + + to_install = resolver.get_installation_order( + requirement_set + ) + + # Check for conflicts in the package set we're installing. + conflicts = None # type: Optional[ConflictDetails] + should_warn_about_conflicts = ( + not options.ignore_dependencies and + options.warn_about_conflicts + ) + if should_warn_about_conflicts: + conflicts = self._determine_conflicts(to_install) + + # Don't warn about script install locations if + # --target has been specified + warn_script_location = options.warn_script_location + if options.target_dir: + warn_script_location = False + + installed = install_given_reqs( + to_install, + install_options, + global_options, + root=options.root_path, + home=target_temp_dir_path, + prefix=options.prefix_path, + warn_script_location=warn_script_location, + use_user_site=options.use_user_site, + pycompile=options.compile, + ) + + lib_locations = get_lib_location_guesses( + user=options.use_user_site, + home=target_temp_dir_path, + root=options.root_path, + prefix=options.prefix_path, + isolated=options.isolated_mode, + ) + working_set = pkg_resources.WorkingSet(lib_locations) + + installed.sort(key=operator.attrgetter('name')) + items = [] + for result in installed: + item = result.name + try: + installed_version = get_installed_version( + result.name, working_set=working_set + ) + if installed_version: + item += '-' + installed_version + except Exception: + pass + items.append(item) + + if conflicts is not None: + self._warn_about_conflicts( + conflicts, + resolver_variant=self.determine_resolver_variant(options), + ) + + installed_desc = ' '.join(items) + if installed_desc: + write_output( + 'Successfully installed %s', installed_desc, + ) + except EnvironmentError as error: + show_traceback = (self.verbosity >= 1) + + message = create_env_error_message( + error, show_traceback, options.use_user_site, + ) + logger.error(message, exc_info=show_traceback) # noqa + + return ERROR + + if options.target_dir: + assert target_temp_dir + self._handle_target_dir( + options.target_dir, target_temp_dir, options.upgrade + ) + + return SUCCESS + + def _handle_target_dir(self, target_dir, target_temp_dir, upgrade): + # type: (str, TempDirectory, bool) -> None + ensure_dir(target_dir) + + # Checking both purelib and platlib directories for installed + # packages to be moved to target directory + lib_dir_list = [] + + # Checking both purelib and platlib directories for installed + # packages to be moved to target directory + scheme = distutils_scheme('', home=target_temp_dir.path) + purelib_dir = scheme['purelib'] + platlib_dir = scheme['platlib'] + data_dir = scheme['data'] + + if os.path.exists(purelib_dir): + lib_dir_list.append(purelib_dir) + if os.path.exists(platlib_dir) and platlib_dir != purelib_dir: + lib_dir_list.append(platlib_dir) + if os.path.exists(data_dir): + lib_dir_list.append(data_dir) + + for lib_dir in lib_dir_list: + for item in os.listdir(lib_dir): + if lib_dir == data_dir: + ddir = os.path.join(data_dir, item) + if any(s.startswith(ddir) for s in lib_dir_list[:-1]): + continue + target_item_dir = os.path.join(target_dir, item) + if os.path.exists(target_item_dir): + if not upgrade: + logger.warning( + 'Target directory %s already exists. Specify ' + '--upgrade to force replacement.', + target_item_dir + ) + continue + if os.path.islink(target_item_dir): + logger.warning( + 'Target directory %s already exists and is ' + 'a link. pip will not automatically replace ' + 'links, please remove if replacement is ' + 'desired.', + target_item_dir + ) + continue + if os.path.isdir(target_item_dir): + shutil.rmtree(target_item_dir) + else: + os.remove(target_item_dir) + + shutil.move( + os.path.join(lib_dir, item), + target_item_dir + ) + + def _determine_conflicts(self, to_install): + # type: (List[InstallRequirement]) -> Optional[ConflictDetails] + try: + return check_install_conflicts(to_install) + except Exception: + logger.exception( + "Error while checking for conflicts. Please file an issue on " + "pip's issue tracker: https://github.com/pypa/pip/issues/new" + ) + return None + + def _warn_about_conflicts(self, conflict_details, resolver_variant): + # type: (ConflictDetails, str) -> None + package_set, (missing, conflicting) = conflict_details + if not missing and not conflicting: + return + + parts = [] # type: List[str] + if resolver_variant == "legacy": + parts.append( + "pip's legacy dependency resolver does not consider dependency " + "conflicts when selecting packages. This behaviour is the " + "source of the following dependency conflicts." + ) + else: + assert resolver_variant == "2020-resolver" + parts.append( + "pip's dependency resolver does not currently take into account " + "all the packages that are installed. This behaviour is the " + "source of the following dependency conflicts." + ) + + # NOTE: There is some duplication here, with commands/check.py + for project_name in missing: + version = package_set[project_name][0] + for dependency in missing[project_name]: + message = ( + "{name} {version} requires {requirement}, " + "which is not installed." + ).format( + name=project_name, + version=version, + requirement=dependency[1], + ) + parts.append(message) + + for project_name in conflicting: + version = package_set[project_name][0] + for dep_name, dep_version, req in conflicting[project_name]: + message = ( + "{name} {version} requires {requirement}, but {you} have " + "{dep_name} {dep_version} which is incompatible." + ).format( + name=project_name, + version=version, + requirement=req, + dep_name=dep_name, + dep_version=dep_version, + you=("you" if resolver_variant == "2020-resolver" else "you'll") + ) + parts.append(message) + + logger.critical("\n".join(parts)) + + +def get_lib_location_guesses( + user=False, # type: bool + home=None, # type: Optional[str] + root=None, # type: Optional[str] + isolated=False, # type: bool + prefix=None # type: Optional[str] +): + # type:(...) -> List[str] + scheme = distutils_scheme('', user=user, home=home, root=root, + isolated=isolated, prefix=prefix) + return [scheme['purelib'], scheme['platlib']] + + +def site_packages_writable(root, isolated): + # type: (Optional[str], bool) -> bool + return all( + test_writable_dir(d) for d in set( + get_lib_location_guesses(root=root, isolated=isolated)) + ) + + +def decide_user_install( + use_user_site, # type: Optional[bool] + prefix_path=None, # type: Optional[str] + target_dir=None, # type: Optional[str] + root_path=None, # type: Optional[str] + isolated_mode=False, # type: bool +): + # type: (...) -> bool + """Determine whether to do a user install based on the input options. + + If use_user_site is False, no additional checks are done. + If use_user_site is True, it is checked for compatibility with other + options. + If use_user_site is None, the default behaviour depends on the environment, + which is provided by the other arguments. + """ + # In some cases (config from tox), use_user_site can be set to an integer + # rather than a bool, which 'use_user_site is False' wouldn't catch. + if (use_user_site is not None) and (not use_user_site): + logger.debug("Non-user install by explicit request") + return False + + if use_user_site: + if prefix_path: + raise CommandError( + "Can not combine '--user' and '--prefix' as they imply " + "different installation locations" + ) + if virtualenv_no_global(): + raise InstallationError( + "Can not perform a '--user' install. User site-packages " + "are not visible in this virtualenv." + ) + logger.debug("User install by explicit request") + return True + + # If we are here, user installs have not been explicitly requested/avoided + assert use_user_site is None + + # user install incompatible with --prefix/--target + if prefix_path or target_dir: + logger.debug("Non-user install due to --prefix or --target option") + return False + + # If user installs are not enabled, choose a non-user install + if not site.ENABLE_USER_SITE: + logger.debug("Non-user install because user site-packages disabled") + return False + + # If we have permission for a non-user install, do that, + # otherwise do a user install. + if site_packages_writable(root=root_path, isolated=isolated_mode): + logger.debug("Non-user install because site-packages writeable") + return False + + logger.info("Defaulting to user installation because normal site-packages " + "is not writeable") + return True + + +def reject_location_related_install_options(requirements, options): + # type: (List[InstallRequirement], Optional[List[str]]) -> None + """If any location-changing --install-option arguments were passed for + requirements or on the command-line, then show a deprecation warning. + """ + def format_options(option_names): + # type: (Iterable[str]) -> List[str] + return ["--{}".format(name.replace("_", "-")) for name in option_names] + + offenders = [] + + for requirement in requirements: + install_options = requirement.install_options + location_options = parse_distutils_args(install_options) + if location_options: + offenders.append( + "{!r} from {}".format( + format_options(location_options.keys()), requirement + ) + ) + + if options: + location_options = parse_distutils_args(options) + if location_options: + offenders.append( + "{!r} from command line".format( + format_options(location_options.keys()) + ) + ) + + if not offenders: + return + + raise CommandError( + "Location-changing options found in --install-option: {}." + " This is unsupported, use pip-level options like --user," + " --prefix, --root, and --target instead.".format( + "; ".join(offenders) + ) + ) + + +def create_env_error_message(error, show_traceback, using_user_site): + # type: (EnvironmentError, bool, bool) -> str + """Format an error message for an EnvironmentError + + It may occur anytime during the execution of the install command. + """ + parts = [] + + # Mention the error if we are not going to show a traceback + parts.append("Could not install packages due to an EnvironmentError") + if not show_traceback: + parts.append(": ") + parts.append(str(error)) + else: + parts.append(".") + + # Spilt the error indication from a helper message (if any) + parts[-1] += "\n" + + # Suggest useful actions to the user: + # (1) using user site-packages or (2) verifying the permissions + if error.errno == errno.EACCES: + user_option_part = "Consider using the `--user` option" + permissions_part = "Check the permissions" + + if not using_user_site: + parts.extend([ + user_option_part, " or ", + permissions_part.lower(), + ]) + else: + parts.append(permissions_part) + parts.append(".\n") + + return "".join(parts).strip() + "\n" diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/list.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/list.py new file mode 100644 index 0000000..10720b2 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/list.py @@ -0,0 +1,329 @@ +from __future__ import absolute_import + +import json +import logging + +from pip._vendor import six + +from pip._internal.cli import cmdoptions +from pip._internal.cli.req_command import IndexGroupCommand +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import CommandError +from pip._internal.index.collector import LinkCollector +from pip._internal.index.package_finder import PackageFinder +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.utils.compat import stdlib_pkgs +from pip._internal.utils.misc import ( + dist_is_editable, + get_installed_distributions, + tabulate, + write_output, +) +from pip._internal.utils.packaging import get_installer +from pip._internal.utils.parallel import map_multithread +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import Iterator, List, Set, Tuple + + from pip._vendor.pkg_resources import Distribution + + from pip._internal.network.session import PipSession + +from pip._vendor.packaging.version import parse + +logger = logging.getLogger(__name__) + + +class ListCommand(IndexGroupCommand): + """ + List installed packages, including editables. + + Packages are listed in a case-insensitive sorted order. + """ + + ignore_require_venv = True + usage = """ + %prog [options]""" + + def add_options(self): + # type: () -> None + self.cmd_opts.add_option( + '-o', '--outdated', + action='store_true', + default=False, + help='List outdated packages') + self.cmd_opts.add_option( + '-u', '--uptodate', + action='store_true', + default=False, + help='List uptodate packages') + self.cmd_opts.add_option( + '-e', '--editable', + action='store_true', + default=False, + help='List editable projects.') + self.cmd_opts.add_option( + '-l', '--local', + action='store_true', + default=False, + help=('If in a virtualenv that has global access, do not list ' + 'globally-installed packages.'), + ) + self.cmd_opts.add_option( + '--user', + dest='user', + action='store_true', + default=False, + help='Only output packages installed in user-site.') + self.cmd_opts.add_option(cmdoptions.list_path()) + self.cmd_opts.add_option( + '--pre', + action='store_true', + default=False, + help=("Include pre-release and development versions. By default, " + "pip only finds stable versions."), + ) + + self.cmd_opts.add_option( + '--format', + action='store', + dest='list_format', + default="columns", + choices=('columns', 'freeze', 'json'), + help="Select the output format among: columns (default), freeze, " + "or json", + ) + + self.cmd_opts.add_option( + '--not-required', + action='store_true', + dest='not_required', + help="List packages that are not dependencies of " + "installed packages.", + ) + + self.cmd_opts.add_option( + '--exclude-editable', + action='store_false', + dest='include_editable', + help='Exclude editable package from output.', + ) + self.cmd_opts.add_option( + '--include-editable', + action='store_true', + dest='include_editable', + help='Include editable package from output.', + default=True, + ) + self.cmd_opts.add_option(cmdoptions.list_exclude()) + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, self.parser + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + def _build_package_finder(self, options, session): + # type: (Values, PipSession) -> PackageFinder + """ + Create a package finder appropriate to this list command. + """ + link_collector = LinkCollector.create(session, options=options) + + # Pass allow_yanked=False to ignore yanked versions. + selection_prefs = SelectionPreferences( + allow_yanked=False, + allow_all_prereleases=options.pre, + ) + + return PackageFinder.create( + link_collector=link_collector, + selection_prefs=selection_prefs, + ) + + def run(self, options, args): + # type: (Values, List[str]) -> int + if options.outdated and options.uptodate: + raise CommandError( + "Options --outdated and --uptodate cannot be combined.") + + cmdoptions.check_list_path_option(options) + + skip = set(stdlib_pkgs) + if options.excludes: + skip.update(options.excludes) + + packages = get_installed_distributions( + local_only=options.local, + user_only=options.user, + editables_only=options.editable, + include_editables=options.include_editable, + paths=options.path, + skip=skip, + ) + + # get_not_required must be called firstly in order to find and + # filter out all dependencies correctly. Otherwise a package + # can't be identified as requirement because some parent packages + # could be filtered out before. + if options.not_required: + packages = self.get_not_required(packages, options) + + if options.outdated: + packages = self.get_outdated(packages, options) + elif options.uptodate: + packages = self.get_uptodate(packages, options) + + self.output_package_listing(packages, options) + return SUCCESS + + def get_outdated(self, packages, options): + # type: (List[Distribution], Values) -> List[Distribution] + return [ + dist for dist in self.iter_packages_latest_infos(packages, options) + if parse(str(dist.latest_version)) > parse(str(dist.parsed_version)) + ] + + def get_uptodate(self, packages, options): + # type: (List[Distribution], Values) -> List[Distribution] + return [ + dist for dist in self.iter_packages_latest_infos(packages, options) + if parse(str(dist.latest_version)) == parse(str(dist.parsed_version)) + ] + + def get_not_required(self, packages, options): + # type: (List[Distribution], Values) -> List[Distribution] + dep_keys = set() # type: Set[Distribution] + for dist in packages: + dep_keys.update(requirement.key for requirement in dist.requires()) + + # Create a set to remove duplicate packages, and cast it to a list + # to keep the return type consistent with get_outdated and + # get_uptodate + return list({pkg for pkg in packages if pkg.key not in dep_keys}) + + def iter_packages_latest_infos(self, packages, options): + # type: (List[Distribution], Values) -> Iterator[Distribution] + with self._build_session(options) as session: + finder = self._build_package_finder(options, session) + + def latest_info(dist): + # type: (Distribution) -> Distribution + all_candidates = finder.find_all_candidates(dist.key) + if not options.pre: + # Remove prereleases + all_candidates = [candidate for candidate in all_candidates + if not candidate.version.is_prerelease] + + evaluator = finder.make_candidate_evaluator( + project_name=dist.project_name, + ) + best_candidate = evaluator.sort_best_candidate(all_candidates) + if best_candidate is None: + return None + + remote_version = best_candidate.version + if best_candidate.link.is_wheel: + typ = 'wheel' + else: + typ = 'sdist' + # This is dirty but makes the rest of the code much cleaner + dist.latest_version = remote_version + dist.latest_filetype = typ + return dist + + for dist in map_multithread(latest_info, packages): + if dist is not None: + yield dist + + def output_package_listing(self, packages, options): + # type: (List[Distribution], Values) -> None + packages = sorted( + packages, + key=lambda dist: dist.project_name.lower(), + ) + if options.list_format == 'columns' and packages: + data, header = format_for_columns(packages, options) + self.output_package_listing_columns(data, header) + elif options.list_format == 'freeze': + for dist in packages: + if options.verbose >= 1: + write_output("%s==%s (%s)", dist.project_name, + dist.version, dist.location) + else: + write_output("%s==%s", dist.project_name, dist.version) + elif options.list_format == 'json': + write_output(format_for_json(packages, options)) + + def output_package_listing_columns(self, data, header): + # type: (List[List[str]], List[str]) -> None + # insert the header first: we need to know the size of column names + if len(data) > 0: + data.insert(0, header) + + pkg_strings, sizes = tabulate(data) + + # Create and add a separator. + if len(data) > 0: + pkg_strings.insert(1, " ".join(map(lambda x: '-' * x, sizes))) + + for val in pkg_strings: + write_output(val) + + +def format_for_columns(pkgs, options): + # type: (List[Distribution], Values) -> Tuple[List[List[str]], List[str]] + """ + Convert the package data into something usable + by output_package_listing_columns. + """ + running_outdated = options.outdated + # Adjust the header for the `pip list --outdated` case. + if running_outdated: + header = ["Package", "Version", "Latest", "Type"] + else: + header = ["Package", "Version"] + + data = [] + if options.verbose >= 1 or any(dist_is_editable(x) for x in pkgs): + header.append("Location") + if options.verbose >= 1: + header.append("Installer") + + for proj in pkgs: + # if we're working on the 'outdated' list, separate out the + # latest_version and type + row = [proj.project_name, proj.version] + + if running_outdated: + row.append(proj.latest_version) + row.append(proj.latest_filetype) + + if options.verbose >= 1 or dist_is_editable(proj): + row.append(proj.location) + if options.verbose >= 1: + row.append(get_installer(proj)) + + data.append(row) + + return data, header + + +def format_for_json(packages, options): + # type: (List[Distribution], Values) -> str + data = [] + for dist in packages: + info = { + 'name': dist.project_name, + 'version': six.text_type(dist.version), + } + if options.verbose >= 1: + info['location'] = dist.location + info['installer'] = get_installer(dist) + if options.outdated: + info['latest_version'] = six.text_type(dist.latest_version) + info['latest_filetype'] = dist.latest_filetype + data.append(info) + return json.dumps(data) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/search.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/search.py new file mode 100644 index 0000000..185495e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/search.py @@ -0,0 +1,169 @@ +from __future__ import absolute_import + +import logging +import sys +import textwrap +from collections import OrderedDict + +from pip._vendor import pkg_resources +from pip._vendor.packaging.version import parse as parse_version + +# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is +# why we ignore the type on this import +from pip._vendor.six.moves import xmlrpc_client # type: ignore + +from pip._internal.cli.base_command import Command +from pip._internal.cli.req_command import SessionCommandMixin +from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS +from pip._internal.exceptions import CommandError +from pip._internal.models.index import PyPI +from pip._internal.network.xmlrpc import PipXmlrpcTransport +from pip._internal.utils.compat import get_terminal_size +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import get_distribution, write_output +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import Dict, List, Optional + + from typing_extensions import TypedDict + TransformedHit = TypedDict( + 'TransformedHit', + {'name': str, 'summary': str, 'versions': List[str]}, + ) + +logger = logging.getLogger(__name__) + + +class SearchCommand(Command, SessionCommandMixin): + """Search for PyPI packages whose name or summary contains .""" + + usage = """ + %prog [options] """ + ignore_require_venv = True + + def add_options(self): + # type: () -> None + self.cmd_opts.add_option( + '-i', '--index', + dest='index', + metavar='URL', + default=PyPI.pypi_url, + help='Base URL of Python Package Index (default %default)') + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + # type: (Values, List[str]) -> int + if not args: + raise CommandError('Missing required argument (search query).') + query = args + pypi_hits = self.search(query, options) + hits = transform_hits(pypi_hits) + + terminal_width = None + if sys.stdout.isatty(): + terminal_width = get_terminal_size()[0] + + print_results(hits, terminal_width=terminal_width) + if pypi_hits: + return SUCCESS + return NO_MATCHES_FOUND + + def search(self, query, options): + # type: (List[str], Values) -> List[Dict[str, str]] + index_url = options.index + + session = self.get_default_session(options) + + transport = PipXmlrpcTransport(index_url, session) + pypi = xmlrpc_client.ServerProxy(index_url, transport) + try: + hits = pypi.search({'name': query, 'summary': query}, 'or') + except xmlrpc_client.Fault as fault: + message = "XMLRPC request failed [code: {code}]\n{string}".format( + code=fault.faultCode, + string=fault.faultString, + ) + raise CommandError(message) + return hits + + +def transform_hits(hits): + # type: (List[Dict[str, str]]) -> List[TransformedHit] + """ + The list from pypi is really a list of versions. We want a list of + packages with the list of versions stored inline. This converts the + list from pypi into one we can use. + """ + packages = OrderedDict() # type: OrderedDict[str, TransformedHit] + for hit in hits: + name = hit['name'] + summary = hit['summary'] + version = hit['version'] + + if name not in packages.keys(): + packages[name] = { + 'name': name, + 'summary': summary, + 'versions': [version], + } + else: + packages[name]['versions'].append(version) + + # if this is the highest version, replace summary and score + if version == highest_version(packages[name]['versions']): + packages[name]['summary'] = summary + + return list(packages.values()) + + +def print_results(hits, name_column_width=None, terminal_width=None): + # type: (List[TransformedHit], Optional[int], Optional[int]) -> None + if not hits: + return + if name_column_width is None: + name_column_width = max([ + len(hit['name']) + len(highest_version(hit.get('versions', ['-']))) + for hit in hits + ]) + 4 + + installed_packages = [p.project_name for p in pkg_resources.working_set] + for hit in hits: + name = hit['name'] + summary = hit['summary'] or '' + latest = highest_version(hit.get('versions', ['-'])) + if terminal_width is not None: + target_width = terminal_width - name_column_width - 5 + if target_width > 10: + # wrap and indent summary to fit terminal + summary_lines = textwrap.wrap(summary, target_width) + summary = ('\n' + ' ' * (name_column_width + 3)).join( + summary_lines) + + line = '{name_latest:{name_column_width}} - {summary}'.format( + name_latest='{name} ({latest})'.format(**locals()), + **locals()) + try: + write_output(line) + if name in installed_packages: + dist = get_distribution(name) + assert dist is not None + with indent_log(): + if dist.version == latest: + write_output('INSTALLED: %s (latest)', dist.version) + else: + write_output('INSTALLED: %s', dist.version) + if parse_version(latest).pre: + write_output('LATEST: %s (pre-release; install' + ' with "pip install --pre")', latest) + else: + write_output('LATEST: %s', latest) + except UnicodeEncodeError: + pass + + +def highest_version(versions): + # type: (List[str]) -> str + return max(versions, key=parse_version) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/show.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/show.py new file mode 100644 index 0000000..b0b3f3a --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/show.py @@ -0,0 +1,186 @@ +from __future__ import absolute_import + +import logging +import os +from email.parser import FeedParser + +from pip._vendor import pkg_resources +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.utils.misc import write_output +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import Dict, Iterator, List + +logger = logging.getLogger(__name__) + + +class ShowCommand(Command): + """ + Show information about one or more installed packages. + + The output is in RFC-compliant mail header format. + """ + + usage = """ + %prog [options] ...""" + ignore_require_venv = True + + def add_options(self): + # type: () -> None + self.cmd_opts.add_option( + '-f', '--files', + dest='files', + action='store_true', + default=False, + help='Show the full list of installed files for each package.') + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + # type: (Values, List[str]) -> int + if not args: + logger.warning('ERROR: Please provide a package name or names.') + return ERROR + query = args + + results = search_packages_info(query) + if not print_results( + results, list_files=options.files, verbose=options.verbose): + return ERROR + return SUCCESS + + +def search_packages_info(query): + # type: (List[str]) -> Iterator[Dict[str, str]] + """ + Gather details from installed distributions. Print distribution name, + version, location, and installed files. Installed files requires a + pip generated 'installed-files.txt' in the distributions '.egg-info' + directory. + """ + installed = {} + for p in pkg_resources.working_set: + installed[canonicalize_name(p.project_name)] = p + + query_names = [canonicalize_name(name) for name in query] + missing = sorted( + [name for name, pkg in zip(query, query_names) if pkg not in installed] + ) + if missing: + logger.warning('Package(s) not found: %s', ', '.join(missing)) + + def get_requiring_packages(package_name): + # type: (str) -> List[str] + canonical_name = canonicalize_name(package_name) + return [ + pkg.project_name for pkg in pkg_resources.working_set + if canonical_name in + [canonicalize_name(required.name) for required in + pkg.requires()] + ] + + for dist in [installed[pkg] for pkg in query_names if pkg in installed]: + package = { + 'name': dist.project_name, + 'version': dist.version, + 'location': dist.location, + 'requires': [dep.project_name for dep in dist.requires()], + 'required_by': get_requiring_packages(dist.project_name) + } + file_list = None + metadata = '' + if isinstance(dist, pkg_resources.DistInfoDistribution): + # RECORDs should be part of .dist-info metadatas + if dist.has_metadata('RECORD'): + lines = dist.get_metadata_lines('RECORD') + paths = [line.split(',')[0] for line in lines] + paths = [os.path.join(dist.location, p) for p in paths] + file_list = [os.path.relpath(p, dist.location) for p in paths] + + if dist.has_metadata('METADATA'): + metadata = dist.get_metadata('METADATA') + else: + # Otherwise use pip's log for .egg-info's + if dist.has_metadata('installed-files.txt'): + paths = dist.get_metadata_lines('installed-files.txt') + paths = [os.path.join(dist.egg_info, p) for p in paths] + file_list = [os.path.relpath(p, dist.location) for p in paths] + + if dist.has_metadata('PKG-INFO'): + metadata = dist.get_metadata('PKG-INFO') + + if dist.has_metadata('entry_points.txt'): + entry_points = dist.get_metadata_lines('entry_points.txt') + package['entry_points'] = entry_points + + if dist.has_metadata('INSTALLER'): + for line in dist.get_metadata_lines('INSTALLER'): + if line.strip(): + package['installer'] = line.strip() + break + + # @todo: Should pkg_resources.Distribution have a + # `get_pkg_info` method? + feed_parser = FeedParser() + feed_parser.feed(metadata) + pkg_info_dict = feed_parser.close() + for key in ('metadata-version', 'summary', + 'home-page', 'author', 'author-email', 'license'): + package[key] = pkg_info_dict.get(key) + + # It looks like FeedParser cannot deal with repeated headers + classifiers = [] + for line in metadata.splitlines(): + if line.startswith('Classifier: '): + classifiers.append(line[len('Classifier: '):]) + package['classifiers'] = classifiers + + if file_list: + package['files'] = sorted(file_list) + yield package + + +def print_results(distributions, list_files=False, verbose=False): + # type: (Iterator[Dict[str, str]], bool, bool) -> bool + """ + Print the information from installed distributions found. + """ + results_printed = False + for i, dist in enumerate(distributions): + results_printed = True + if i > 0: + write_output("---") + + write_output("Name: %s", dist.get('name', '')) + write_output("Version: %s", dist.get('version', '')) + write_output("Summary: %s", dist.get('summary', '')) + write_output("Home-page: %s", dist.get('home-page', '')) + write_output("Author: %s", dist.get('author', '')) + write_output("Author-email: %s", dist.get('author-email', '')) + write_output("License: %s", dist.get('license', '')) + write_output("Location: %s", dist.get('location', '')) + write_output("Requires: %s", ', '.join(dist.get('requires', []))) + write_output("Required-by: %s", ', '.join(dist.get('required_by', []))) + + if verbose: + write_output("Metadata-Version: %s", + dist.get('metadata-version', '')) + write_output("Installer: %s", dist.get('installer', '')) + write_output("Classifiers:") + for classifier in dist.get('classifiers', []): + write_output(" %s", classifier) + write_output("Entry-points:") + for entry in dist.get('entry_points', []): + write_output(" %s", entry.strip()) + if list_files: + write_output("Files:") + for line in dist.get('files', []): + write_output(" %s", line.strip()) + if "files" not in dist: + write_output("Cannot locate installed-files.txt") + return results_printed diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/uninstall.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/uninstall.py new file mode 100644 index 0000000..3371fe4 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/uninstall.py @@ -0,0 +1,95 @@ +from __future__ import absolute_import + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.base_command import Command +from pip._internal.cli.req_command import SessionCommandMixin +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import InstallationError +from pip._internal.req import parse_requirements +from pip._internal.req.constructors import ( + install_req_from_line, + install_req_from_parsed_requirement, +) +from pip._internal.utils.misc import protect_pip_from_modification_on_windows +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import List + + +class UninstallCommand(Command, SessionCommandMixin): + """ + Uninstall packages. + + pip is able to uninstall most installed packages. Known exceptions are: + + - Pure distutils packages installed with ``python setup.py install``, which + leave behind no metadata to determine what files were installed. + - Script wrappers installed by ``python setup.py develop``. + """ + + usage = """ + %prog [options] ... + %prog [options] -r ...""" + + def add_options(self): + # type: () -> None + self.cmd_opts.add_option( + '-r', '--requirement', + dest='requirements', + action='append', + default=[], + metavar='file', + help='Uninstall all the packages listed in the given requirements ' + 'file. This option can be used multiple times.', + ) + self.cmd_opts.add_option( + '-y', '--yes', + dest='yes', + action='store_true', + help="Don't ask for confirmation of uninstall deletions.") + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + # type: (Values, List[str]) -> int + session = self.get_default_session(options) + + reqs_to_uninstall = {} + for name in args: + req = install_req_from_line( + name, isolated=options.isolated_mode, + ) + if req.name: + reqs_to_uninstall[canonicalize_name(req.name)] = req + for filename in options.requirements: + for parsed_req in parse_requirements( + filename, + options=options, + session=session): + req = install_req_from_parsed_requirement( + parsed_req, + isolated=options.isolated_mode + ) + if req.name: + reqs_to_uninstall[canonicalize_name(req.name)] = req + if not reqs_to_uninstall: + raise InstallationError( + 'You must give at least one requirement to {self.name} (see ' + '"pip help {self.name}")'.format(**locals()) + ) + + protect_pip_from_modification_on_windows( + modifying_pip="pip" in reqs_to_uninstall + ) + + for req in reqs_to_uninstall.values(): + uninstall_pathset = req.uninstall( + auto_confirm=options.yes, verbose=self.verbosity > 0, + ) + if uninstall_pathset: + uninstall_pathset.commit() + + return SUCCESS diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/wheel.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/wheel.py new file mode 100644 index 0000000..a9f6625 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/commands/wheel.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- + +from __future__ import absolute_import + +import logging +import os +import shutil + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.req_command import RequirementCommand, with_cleanup +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import CommandError +from pip._internal.req.req_tracker import get_requirement_tracker +from pip._internal.utils.misc import ensure_dir, normalize_path +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.wheel_builder import build, should_build_for_wheel_command + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import List + + from pip._internal.req.req_install import InstallRequirement + +logger = logging.getLogger(__name__) + + +class WheelCommand(RequirementCommand): + """ + Build Wheel archives for your requirements and dependencies. + + Wheel is a built-package format, and offers the advantage of not + recompiling your software during every install. For more details, see the + wheel docs: https://wheel.readthedocs.io/en/latest/ + + Requirements: setuptools>=0.8, and wheel. + + 'pip wheel' uses the bdist_wheel setuptools extension from the wheel + package to build individual wheels. + + """ + + usage = """ + %prog [options] ... + %prog [options] -r ... + %prog [options] [-e] ... + %prog [options] [-e] ... + %prog [options] ...""" + + def add_options(self): + # type: () -> None + + self.cmd_opts.add_option( + '-w', '--wheel-dir', + dest='wheel_dir', + metavar='dir', + default=os.curdir, + help=("Build wheels into , where the default is the " + "current working directory."), + ) + self.cmd_opts.add_option(cmdoptions.no_binary()) + self.cmd_opts.add_option(cmdoptions.only_binary()) + self.cmd_opts.add_option(cmdoptions.prefer_binary()) + self.cmd_opts.add_option( + '--build-option', + dest='build_options', + metavar='options', + action='append', + help="Extra arguments to be supplied to 'setup.py bdist_wheel'.", + ) + self.cmd_opts.add_option(cmdoptions.no_build_isolation()) + self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) + self.cmd_opts.add_option(cmdoptions.constraints()) + self.cmd_opts.add_option(cmdoptions.editable()) + self.cmd_opts.add_option(cmdoptions.requirements()) + self.cmd_opts.add_option(cmdoptions.src()) + self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) + self.cmd_opts.add_option(cmdoptions.no_deps()) + self.cmd_opts.add_option(cmdoptions.build_dir()) + self.cmd_opts.add_option(cmdoptions.progress_bar()) + + self.cmd_opts.add_option( + '--no-verify', + dest='no_verify', + action='store_true', + default=False, + help="Don't verify if built wheel is valid.", + ) + + self.cmd_opts.add_option( + '--global-option', + dest='global_options', + action='append', + metavar='options', + help="Extra global options to be supplied to the setup.py " + "call before the 'bdist_wheel' command.") + + self.cmd_opts.add_option( + '--pre', + action='store_true', + default=False, + help=("Include pre-release and development versions. By default, " + "pip only finds stable versions."), + ) + + self.cmd_opts.add_option(cmdoptions.require_hashes()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + @with_cleanup + def run(self, options, args): + # type: (Values, List[str]) -> int + cmdoptions.check_install_build_global(options) + + session = self.get_default_session(options) + + finder = self._build_package_finder(options, session) + wheel_cache = WheelCache(options.cache_dir, options.format_control) + + options.wheel_dir = normalize_path(options.wheel_dir) + ensure_dir(options.wheel_dir) + + req_tracker = self.enter_context(get_requirement_tracker()) + + directory = TempDirectory( + delete=not options.no_clean, + kind="wheel", + globally_managed=True, + ) + + reqs = self.get_requirements(args, options, finder, session) + + preparer = self.make_requirement_preparer( + temp_build_dir=directory, + options=options, + req_tracker=req_tracker, + session=session, + finder=finder, + download_dir=options.wheel_dir, + use_user_site=False, + ) + + resolver = self.make_resolver( + preparer=preparer, + finder=finder, + options=options, + wheel_cache=wheel_cache, + ignore_requires_python=options.ignore_requires_python, + use_pep517=options.use_pep517, + ) + + self.trace_basic_info(finder) + + requirement_set = resolver.resolve( + reqs, check_supported_wheels=True + ) + + reqs_to_build = [] # type: List[InstallRequirement] + for req in requirement_set.requirements.values(): + if req.is_wheel: + preparer.save_linked_requirement(req) + elif should_build_for_wheel_command(req): + reqs_to_build.append(req) + + # build wheels + build_successes, build_failures = build( + reqs_to_build, + wheel_cache=wheel_cache, + verify=(not options.no_verify), + build_options=options.build_options or [], + global_options=options.global_options or [], + ) + for req in build_successes: + assert req.link and req.link.is_wheel + assert req.local_file_path + # copy from cache to target directory + try: + shutil.copy(req.local_file_path, options.wheel_dir) + except OSError as e: + logger.warning( + "Building wheel for %s failed: %s", + req.name, e, + ) + build_failures.append(req) + if len(build_failures) != 0: + raise CommandError( + "Failed to build one or more wheels" + ) + + return SUCCESS diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/configuration.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/configuration.py new file mode 100644 index 0000000..23614fd --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/configuration.py @@ -0,0 +1,407 @@ +"""Configuration management setup + +Some terminology: +- name + As written in config files. +- value + Value associated with a name +- key + Name combined with it's section (section.name) +- variant + A single word describing where the configuration key-value pair came from +""" + +import locale +import logging +import os +import sys + +from pip._vendor.six.moves import configparser + +from pip._internal.exceptions import ( + ConfigurationError, + ConfigurationFileCouldNotBeLoaded, +) +from pip._internal.utils import appdirs +from pip._internal.utils.compat import WINDOWS, expanduser +from pip._internal.utils.misc import ensure_dir, enum +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, Iterable, List, NewType, Optional, Tuple + + RawConfigParser = configparser.RawConfigParser # Shorthand + Kind = NewType("Kind", str) + +CONFIG_BASENAME = 'pip.ini' if WINDOWS else 'pip.conf' +ENV_NAMES_IGNORED = "version", "help" + +# The kinds of configurations there are. +kinds = enum( + USER="user", # User Specific + GLOBAL="global", # System Wide + SITE="site", # [Virtual] Environment Specific + ENV="env", # from PIP_CONFIG_FILE + ENV_VAR="env-var", # from Environment Variables +) +OVERRIDE_ORDER = kinds.GLOBAL, kinds.USER, kinds.SITE, kinds.ENV, kinds.ENV_VAR +VALID_LOAD_ONLY = kinds.USER, kinds.GLOBAL, kinds.SITE + +logger = logging.getLogger(__name__) + + +# NOTE: Maybe use the optionx attribute to normalize keynames. +def _normalize_name(name): + # type: (str) -> str + """Make a name consistent regardless of source (environment or file) + """ + name = name.lower().replace('_', '-') + if name.startswith('--'): + name = name[2:] # only prefer long opts + return name + + +def _disassemble_key(name): + # type: (str) -> List[str] + if "." not in name: + error_message = ( + "Key does not contain dot separated section and key. " + "Perhaps you wanted to use 'global.{}' instead?" + ).format(name) + raise ConfigurationError(error_message) + return name.split(".", 1) + + +def get_configuration_files(): + # type: () -> Dict[Kind, List[str]] + global_config_files = [ + os.path.join(path, CONFIG_BASENAME) + for path in appdirs.site_config_dirs('pip') + ] + + site_config_file = os.path.join(sys.prefix, CONFIG_BASENAME) + legacy_config_file = os.path.join( + expanduser('~'), + 'pip' if WINDOWS else '.pip', + CONFIG_BASENAME, + ) + new_config_file = os.path.join( + appdirs.user_config_dir("pip"), CONFIG_BASENAME + ) + return { + kinds.GLOBAL: global_config_files, + kinds.SITE: [site_config_file], + kinds.USER: [legacy_config_file, new_config_file], + } + + +class Configuration(object): + """Handles management of configuration. + + Provides an interface to accessing and managing configuration files. + + This class converts provides an API that takes "section.key-name" style + keys and stores the value associated with it as "key-name" under the + section "section". + + This allows for a clean interface wherein the both the section and the + key-name are preserved in an easy to manage form in the configuration files + and the data stored is also nice. + """ + + def __init__(self, isolated, load_only=None): + # type: (bool, Optional[Kind]) -> None + super(Configuration, self).__init__() + + if load_only is not None and load_only not in VALID_LOAD_ONLY: + raise ConfigurationError( + "Got invalid value for load_only - should be one of {}".format( + ", ".join(map(repr, VALID_LOAD_ONLY)) + ) + ) + self.isolated = isolated + self.load_only = load_only + + # Because we keep track of where we got the data from + self._parsers = { + variant: [] for variant in OVERRIDE_ORDER + } # type: Dict[Kind, List[Tuple[str, RawConfigParser]]] + self._config = { + variant: {} for variant in OVERRIDE_ORDER + } # type: Dict[Kind, Dict[str, Any]] + self._modified_parsers = [] # type: List[Tuple[str, RawConfigParser]] + + def load(self): + # type: () -> None + """Loads configuration from configuration files and environment + """ + self._load_config_files() + if not self.isolated: + self._load_environment_vars() + + def get_file_to_edit(self): + # type: () -> Optional[str] + """Returns the file with highest priority in configuration + """ + assert self.load_only is not None, \ + "Need to be specified a file to be editing" + + try: + return self._get_parser_to_modify()[0] + except IndexError: + return None + + def items(self): + # type: () -> Iterable[Tuple[str, Any]] + """Returns key-value pairs like dict.items() representing the loaded + configuration + """ + return self._dictionary.items() + + def get_value(self, key): + # type: (str) -> Any + """Get a value from the configuration. + """ + try: + return self._dictionary[key] + except KeyError: + raise ConfigurationError("No such key - {}".format(key)) + + def set_value(self, key, value): + # type: (str, Any) -> None + """Modify a value in the configuration. + """ + self._ensure_have_load_only() + + assert self.load_only + fname, parser = self._get_parser_to_modify() + + if parser is not None: + section, name = _disassemble_key(key) + + # Modify the parser and the configuration + if not parser.has_section(section): + parser.add_section(section) + parser.set(section, name, value) + + self._config[self.load_only][key] = value + self._mark_as_modified(fname, parser) + + def unset_value(self, key): + # type: (str) -> None + """Unset a value in the configuration.""" + self._ensure_have_load_only() + + assert self.load_only + if key not in self._config[self.load_only]: + raise ConfigurationError("No such key - {}".format(key)) + + fname, parser = self._get_parser_to_modify() + + if parser is not None: + section, name = _disassemble_key(key) + if not (parser.has_section(section) + and parser.remove_option(section, name)): + # The option was not removed. + raise ConfigurationError( + "Fatal Internal error [id=1]. Please report as a bug." + ) + + # The section may be empty after the option was removed. + if not parser.items(section): + parser.remove_section(section) + self._mark_as_modified(fname, parser) + + del self._config[self.load_only][key] + + def save(self): + # type: () -> None + """Save the current in-memory state. + """ + self._ensure_have_load_only() + + for fname, parser in self._modified_parsers: + logger.info("Writing to %s", fname) + + # Ensure directory exists. + ensure_dir(os.path.dirname(fname)) + + with open(fname, "w") as f: + parser.write(f) + + # + # Private routines + # + + def _ensure_have_load_only(self): + # type: () -> None + if self.load_only is None: + raise ConfigurationError("Needed a specific file to be modifying.") + logger.debug("Will be working with %s variant only", self.load_only) + + @property + def _dictionary(self): + # type: () -> Dict[str, Any] + """A dictionary representing the loaded configuration. + """ + # NOTE: Dictionaries are not populated if not loaded. So, conditionals + # are not needed here. + retval = {} + + for variant in OVERRIDE_ORDER: + retval.update(self._config[variant]) + + return retval + + def _load_config_files(self): + # type: () -> None + """Loads configuration from configuration files + """ + config_files = dict(self.iter_config_files()) + if config_files[kinds.ENV][0:1] == [os.devnull]: + logger.debug( + "Skipping loading configuration files due to " + "environment's PIP_CONFIG_FILE being os.devnull" + ) + return + + for variant, files in config_files.items(): + for fname in files: + # If there's specific variant set in `load_only`, load only + # that variant, not the others. + if self.load_only is not None and variant != self.load_only: + logger.debug( + "Skipping file '%s' (variant: %s)", fname, variant + ) + continue + + parser = self._load_file(variant, fname) + + # Keeping track of the parsers used + self._parsers[variant].append((fname, parser)) + + def _load_file(self, variant, fname): + # type: (Kind, str) -> RawConfigParser + logger.debug("For variant '%s', will try loading '%s'", variant, fname) + parser = self._construct_parser(fname) + + for section in parser.sections(): + items = parser.items(section) + self._config[variant].update(self._normalized_keys(section, items)) + + return parser + + def _construct_parser(self, fname): + # type: (str) -> RawConfigParser + parser = configparser.RawConfigParser() + # If there is no such file, don't bother reading it but create the + # parser anyway, to hold the data. + # Doing this is useful when modifying and saving files, where we don't + # need to construct a parser. + if os.path.exists(fname): + try: + parser.read(fname) + except UnicodeDecodeError: + # See https://github.com/pypa/pip/issues/4963 + raise ConfigurationFileCouldNotBeLoaded( + reason="contains invalid {} characters".format( + locale.getpreferredencoding(False) + ), + fname=fname, + ) + except configparser.Error as error: + # See https://github.com/pypa/pip/issues/4893 + raise ConfigurationFileCouldNotBeLoaded(error=error) + return parser + + def _load_environment_vars(self): + # type: () -> None + """Loads configuration from environment variables + """ + self._config[kinds.ENV_VAR].update( + self._normalized_keys(":env:", self.get_environ_vars()) + ) + + def _normalized_keys(self, section, items): + # type: (str, Iterable[Tuple[str, Any]]) -> Dict[str, Any] + """Normalizes items to construct a dictionary with normalized keys. + + This routine is where the names become keys and are made the same + regardless of source - configuration files or environment. + """ + normalized = {} + for name, val in items: + key = section + "." + _normalize_name(name) + normalized[key] = val + return normalized + + def get_environ_vars(self): + # type: () -> Iterable[Tuple[str, str]] + """Returns a generator with all environmental vars with prefix PIP_""" + for key, val in os.environ.items(): + if key.startswith("PIP_"): + name = key[4:].lower() + if name not in ENV_NAMES_IGNORED: + yield name, val + + # XXX: This is patched in the tests. + def iter_config_files(self): + # type: () -> Iterable[Tuple[Kind, List[str]]] + """Yields variant and configuration files associated with it. + + This should be treated like items of a dictionary. + """ + # SMELL: Move the conditions out of this function + + # environment variables have the lowest priority + config_file = os.environ.get('PIP_CONFIG_FILE', None) + if config_file is not None: + yield kinds.ENV, [config_file] + else: + yield kinds.ENV, [] + + config_files = get_configuration_files() + + # at the base we have any global configuration + yield kinds.GLOBAL, config_files[kinds.GLOBAL] + + # per-user configuration next + should_load_user_config = not self.isolated and not ( + config_file and os.path.exists(config_file) + ) + if should_load_user_config: + # The legacy config file is overridden by the new config file + yield kinds.USER, config_files[kinds.USER] + + # finally virtualenv configuration first trumping others + yield kinds.SITE, config_files[kinds.SITE] + + def get_values_in_config(self, variant): + # type: (Kind) -> Dict[str, Any] + """Get values present in a config file""" + return self._config[variant] + + def _get_parser_to_modify(self): + # type: () -> Tuple[str, RawConfigParser] + # Determine which parser to modify + assert self.load_only + parsers = self._parsers[self.load_only] + if not parsers: + # This should not happen if everything works correctly. + raise ConfigurationError( + "Fatal Internal error [id=2]. Please report as a bug." + ) + + # Use the highest priority parser. + return parsers[-1] + + # XXX: This is patched in the tests. + def _mark_as_modified(self, fname, parser): + # type: (str, RawConfigParser) -> None + file_parser_tuple = (fname, parser) + if file_parser_tuple not in self._modified_parsers: + self._modified_parsers.append(file_parser_tuple) + + def __repr__(self): + # type: () -> str + return "{}({!r})".format(self.__class__.__name__, self._dictionary) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__init__.py new file mode 100644 index 0000000..d5c1afc --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__init__.py @@ -0,0 +1,24 @@ +from pip._internal.distributions.sdist import SourceDistribution +from pip._internal.distributions.wheel import WheelDistribution +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from pip._internal.distributions.base import AbstractDistribution + from pip._internal.req.req_install import InstallRequirement + + +def make_distribution_for_install_requirement(install_req): + # type: (InstallRequirement) -> AbstractDistribution + """Returns a Distribution for the given InstallRequirement + """ + # Editable requirements will always be source distributions. They use the + # legacy logic until we create a modern standard for them. + if install_req.editable: + return SourceDistribution(install_req) + + # If it's a wheel, it's a WheelDistribution + if install_req.is_wheel: + return WheelDistribution(install_req) + + # Otherwise, a SourceDistribution + return SourceDistribution(install_req) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e737f6e868b1f8ceada5af71d7602c75b926000 GIT binary patch literal 876 zcmaJgFIBeN>m^gy>d@v8F2y;h@L%#_h!XjA0GY6SEm|^h&3K~UVmIEBmM3=he@n1->r$#C^Yz?3*-DOhQq;yK6Iga9Sd}ntxh_NrlXdq= zNek}Jg`@8PMljB4`Grk#r8Up3Jek9uTb8Qas;jA{%xyD#xBv~Ox&W(rElhGG>?|?d z*40`pcQ3F}Y19(n^7wag3cY6RovPX{v**$Q{1J0%ES+3HxZ?o1XbnUNj;K+kOP8+8 zEh|99c*TJ;WiGfGUX{EYj4k9cS*>uQCI^t7gdbPRI4E$`5(Ay6L#P4pno&zfUY!FW zE}D}a2VFNGz+jQZuhD7nNAM@Y=rzbBWM~ha3~8~3VNbc%k1>$-<@7p4&Mdt+sHi%R;N&e=n) z6+8oa0IT}?#c%_p=94M6qXp;#@Q+$ZE^P32;xLkLqjA-=FpNGEx-K^IRTP=2PEz6C(^`!FDS4Zme&Fd#F3kL1+8B qoyTzNoA&&1@DZ#8?Zfv>j33Oi`;DWBaa4$dKKvr=#y;+cG5!w;5;_b3 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ffc123721b1e70c209e42866e0d29dfe8c2d4ff6 GIT binary patch literal 1272 zcmaJ=&u`N(6n2_4&AJZ6FCmaX5w{*l4&#D^(9nP}AbLE%k_deV2eV@zL*1818 zV2|`ye&NZa?^L&63{9z7TD}zc6~k#Ma)t4m?>_E)q?>PEZN8zT>2QYpc?RU@jOZT1|Ne+4c?K~^De|&B$S2C=DmFTevEtms z>=PISJm#!KBQj71dx*!N0Na5$ItFzdOEHX#Svkqodh|3l0JAzkH$Ixc@%+H6 zV}t%`6{1|xgna=F)XmlW2hZk|Jhz$}8}B*2mWLC6?myEFYS{n) literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa7333db048310ed5ccc8f63e5b079d7585f74d6 GIT binary patch literal 3551 zcmbtXTW=f36`t8$E|(N#QL^l~PUB4N6ev@NwA-dPI7S-Vb<;M25Tz|lq+PFeM&!zS z^UTt+X!0d;5%-}@(O*D5`XBVAe`KBt^r`O!3KWRdb7o1Iw2h!Zm)P04oH=vOneSW} ztghAxJpJ*%f`6|O@(&y=J`N1thgbax8csNkNf*CXOcSeXQS95Xoj6^`^qshpxLw!u zD{(dPx}NE~aV@EL>y(JP%wbP8UP&6=MzY#nHS1n{Dp~8UnSL#9ChOgGpe2(Hae7L- zo3{zC^OeVhuL$SJ?w;XvhqN011ewTIi|XbFgDB>=(g%^u(nO>M%x(T;R~0e{i<=RA zquoIfWhuzQ7gYX_~|7nzRAwv{(@v&g=KD_E%&I4Tu0l_<>@O4xUwItT?>dW`p{_5SK zjXP%#`X`Q!y}kpTxxJ|A?OWOA$Qs)tTfQ|S6MICbv|O1uQ-a>MLu3QCwJLHIKKgW= z1>DaMbD8anu<(m4iFJLTgrAEXu2wgFbB}(cveJcgvxJoJ=g4U}5<&^l?w*0ZUfV_Q zT-b3+^|Qgrj4)SMHtV?WjXA?b>z;6b6G#j)h+VfE)S-22c;yvF{7NRFu|9CZ$Ah;9 zFWOOk00{h?d`|bk8M*b?8(UB4KG~;eLrw-%UHm!uj26}r!Fk^{tM4JXpEdAdSp#0 zu9Y0W_#IHK^4bv{m%LAn-H~gg`YTE`awlt}%9MU_4*0v1=9G-9zkxe;;CEzGk~Xgr z_4g}q@A$g|?@O!C7FXwbjH=Id_%oGngBJBtix~xK@9-7gK_4TkR{l7L}<;aP1xh5L5Vzu28#%q3K~RucOfvn$fY`(Yl6r^SZKbe#yfC^+JuJK*0JR{ z)S(tc1NWKxrRxpf`@c-2tJwn~kV3_SOZnJ~F5b^LF zrt;ZgOMa)_6fqqS-&{0QDb*5TYrVwF#)-a=9*wsuiQ!n+%y~X!V7)o>j5!7Rv(g)3 zUxfFT=guq&4e81^G}?``UQb9}JqTn9y2(p;f}I4pcAylH@+}xk^lg2r%xwNlIlZn1 zyO91u0Ht4+h5GB5k>|qtfMLHB)tIK`l}LRJIlhez0#jF$^3t_CV^Wqb{|cISzb}J=;M1*s)5eJ1`HBw>G|XygESNI(BT> z1;3lt2JD;f9$xw%Tw$wK)t>LCK_Yx#*L^?9_#no9!}sqGf_S!4^?ja&zAraGOnDv~ z6n!CZVIfxPv;sZ!Plci1qmJu2UPIz+>#VNg4Pg*?4N%)YDXH2gASgkBm|j?2ED2P5 zH&8-ikk;px$;87@n4qpqK++eMm*KxatlH1-xdg)bR}mG5@Nb|eT|C5{4XQAZs8jcA zW(yRJJd^FEf=^;ap)W48#Cqsqdsa*OWqBmA%GEVM*e?xa<$K5-OF3hyR~c4&*UH@~ literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a755b94e8e9ee261fcee49b9657ce2134ec0d4d3 GIT binary patch literal 1616 zcmaJ>&yUGD6T+Pyb~5F+#t)kA92b z;|_H5Js6HSmZ-ux#%>(QpbGQQk3$(%aUT0|BnMTJCm4xX-v_@~4y(O<&#w*SsJfJ2 z!ss622_HT~d?>>6Fdy^1hiE$b15QCx+$MS1+%2Vm;q_1F#%fmB&q{cg^R+Ei4fEH& zIeu_V55D;P;A?vL-E8*d>>kYCXdW%87DlagAq?fcJ#?WoJzEJO!EgLhw8;ZjJYq|6 zx2(C)g-fH~0{FNC-4HMW<(Q*9;5ZL?z{6)Kk9fpmc*lGIWhCv@BX>^!jP2>6Xdp3B zTSFM}d60g3>1afteY+|R;Yt`%D@$r2IAQgMz}ALo=4vO*blVLnSWV^v!e~)gxgqPi zfieV7eW(IMvd^2VUuzkrZiQnW{2csp<0-b$lM9b- z0pekVB6JS)KSUoOb9fVB{~UwmA)pX#f4#35H^i<4sf1;mSwA z1|{QQ99+WzzWn$0=F!V~ON*$4uwj)X_#n-?u zZO4?Ju9>`8Nhsy2pj2OlWAt@r9Kk)~64mZDxysA{%n(QM@QRp{C|f&J+c*Bp!4vN_nRn|TBd&D1BLVGlY~R`4 t@A&v3y-*iO-TnD=0*=0nUb(({PtNe;4zo`j-R3eF5D|tah@g+de*ibq%g+D+ literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/base.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/base.py new file mode 100644 index 0000000..3a789f8 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/base.py @@ -0,0 +1,46 @@ +import abc + +from pip._vendor.six import add_metaclass + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Optional + + from pip._vendor.pkg_resources import Distribution + + from pip._internal.index.package_finder import PackageFinder + from pip._internal.req import InstallRequirement + + +@add_metaclass(abc.ABCMeta) +class AbstractDistribution(object): + """A base class for handling installable artifacts. + + The requirements for anything installable are as follows: + + - we must be able to determine the requirement name + (or we can't correctly handle the non-upgrade case). + + - for packages with setup requirements, we must also be able + to determine their requirements without installing additional + packages (for the same reason as run-time dependencies) + + - we must be able to create a Distribution object exposing the + above metadata. + """ + + def __init__(self, req): + # type: (InstallRequirement) -> None + super(AbstractDistribution, self).__init__() + self.req = req + + @abc.abstractmethod + def get_pkg_resources_distribution(self): + # type: () -> Optional[Distribution] + raise NotImplementedError() + + @abc.abstractmethod + def prepare_distribution_metadata(self, finder, build_isolation): + # type: (PackageFinder, bool) -> None + raise NotImplementedError() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/installed.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/installed.py new file mode 100644 index 0000000..a813b21 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/installed.py @@ -0,0 +1,25 @@ +from pip._internal.distributions.base import AbstractDistribution +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Optional + + from pip._vendor.pkg_resources import Distribution + + from pip._internal.index.package_finder import PackageFinder + + +class InstalledDistribution(AbstractDistribution): + """Represents an installed package. + + This does not need any preparation as the required information has already + been computed. + """ + + def get_pkg_resources_distribution(self): + # type: () -> Optional[Distribution] + return self.req.satisfied_by + + def prepare_distribution_metadata(self, finder, build_isolation): + # type: (PackageFinder, bool) -> None + pass diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/sdist.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/sdist.py new file mode 100644 index 0000000..06b9df0 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/sdist.py @@ -0,0 +1,105 @@ +import logging + +from pip._internal.build_env import BuildEnvironment +from pip._internal.distributions.base import AbstractDistribution +from pip._internal.exceptions import InstallationError +from pip._internal.utils.subprocess import runner_with_spinner_message +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Set, Tuple + + from pip._vendor.pkg_resources import Distribution + + from pip._internal.index.package_finder import PackageFinder + + +logger = logging.getLogger(__name__) + + +class SourceDistribution(AbstractDistribution): + """Represents a source distribution. + + The preparation step for these needs metadata for the packages to be + generated, either using PEP 517 or using the legacy `setup.py egg_info`. + """ + + def get_pkg_resources_distribution(self): + # type: () -> Distribution + return self.req.get_dist() + + def prepare_distribution_metadata(self, finder, build_isolation): + # type: (PackageFinder, bool) -> None + # Load pyproject.toml, to determine whether PEP 517 is to be used + self.req.load_pyproject_toml() + + # Set up the build isolation, if this requirement should be isolated + should_isolate = self.req.use_pep517 and build_isolation + if should_isolate: + self._setup_isolation(finder) + + self.req.prepare_metadata() + + def _setup_isolation(self, finder): + # type: (PackageFinder) -> None + def _raise_conflicts(conflicting_with, conflicting_reqs): + # type: (str, Set[Tuple[str, str]]) -> None + format_string = ( + "Some build dependencies for {requirement} " + "conflict with {conflicting_with}: {description}." + ) + error_message = format_string.format( + requirement=self.req, + conflicting_with=conflicting_with, + description=', '.join( + '{} is incompatible with {}'.format(installed, wanted) + for installed, wanted in sorted(conflicting) + ) + ) + raise InstallationError(error_message) + + # Isolate in a BuildEnvironment and install the build-time + # requirements. + pyproject_requires = self.req.pyproject_requires + assert pyproject_requires is not None + + self.req.build_env = BuildEnvironment() + self.req.build_env.install_requirements( + finder, pyproject_requires, 'overlay', + "Installing build dependencies" + ) + conflicting, missing = self.req.build_env.check_requirements( + self.req.requirements_to_check + ) + if conflicting: + _raise_conflicts("PEP 517/518 supported requirements", + conflicting) + if missing: + logger.warning( + "Missing build requirements in pyproject.toml for %s.", + self.req, + ) + logger.warning( + "The project does not specify a build backend, and " + "pip cannot fall back to setuptools without %s.", + " and ".join(map(repr, sorted(missing))) + ) + # Install any extra build dependencies that the backend requests. + # This must be done in a second pass, as the pyproject.toml + # dependencies must be installed before we can call the backend. + with self.req.build_env: + runner = runner_with_spinner_message( + "Getting requirements to build wheel" + ) + backend = self.req.pep517_backend + assert backend is not None + with backend.subprocess_runner(runner): + reqs = backend.get_requires_for_build_wheel() + + conflicting, missing = self.req.build_env.check_requirements(reqs) + if conflicting: + _raise_conflicts("the backend dependencies", conflicting) + self.req.build_env.install_requirements( + finder, missing, 'normal', + "Installing backend dependencies" + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/wheel.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/wheel.py new file mode 100644 index 0000000..2adc228 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/distributions/wheel.py @@ -0,0 +1,37 @@ +from zipfile import ZipFile + +from pip._internal.distributions.base import AbstractDistribution +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.wheel import pkg_resources_distribution_for_wheel + +if MYPY_CHECK_RUNNING: + from pip._vendor.pkg_resources import Distribution + + from pip._internal.index.package_finder import PackageFinder + + +class WheelDistribution(AbstractDistribution): + """Represents a wheel distribution. + + This does not need any preparation as wheels can be directly unpacked. + """ + + def get_pkg_resources_distribution(self): + # type: () -> Distribution + """Loads the metadata from the wheel file into memory and returns a + Distribution that uses it, not relying on the wheel file or + requirement. + """ + # Set as part of preparation during download. + assert self.req.local_file_path + # Wheels are never unnamed. + assert self.req.name + + with ZipFile(self.req.local_file_path, allowZip64=True) as z: + return pkg_resources_distribution_for_wheel( + z, self.req.name, self.req.local_file_path + ) + + def prepare_distribution_metadata(self, finder, build_isolation): + # type: (PackageFinder, bool) -> None + pass diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/exceptions.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/exceptions.py new file mode 100644 index 0000000..8d7f7fa --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/exceptions.py @@ -0,0 +1,391 @@ +"""Exceptions used throughout package""" + +from __future__ import absolute_import + +from itertools import chain, groupby, repeat + +from pip._vendor.six import iteritems + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, List, Optional, Text + + from pip._vendor.pkg_resources import Distribution + from pip._vendor.requests.models import Request, Response + from pip._vendor.six import PY3 + from pip._vendor.six.moves import configparser + + from pip._internal.req.req_install import InstallRequirement + + if PY3: + from hashlib import _Hash + else: + from hashlib import _hash as _Hash + + +class PipError(Exception): + """Base pip exception""" + + +class ConfigurationError(PipError): + """General exception in configuration""" + + +class InstallationError(PipError): + """General exception during installation""" + + +class UninstallationError(PipError): + """General exception during uninstallation""" + + +class NoneMetadataError(PipError): + """ + Raised when accessing "METADATA" or "PKG-INFO" metadata for a + pip._vendor.pkg_resources.Distribution object and + `dist.has_metadata('METADATA')` returns True but + `dist.get_metadata('METADATA')` returns None (and similarly for + "PKG-INFO"). + """ + + def __init__(self, dist, metadata_name): + # type: (Distribution, str) -> None + """ + :param dist: A Distribution object. + :param metadata_name: The name of the metadata being accessed + (can be "METADATA" or "PKG-INFO"). + """ + self.dist = dist + self.metadata_name = metadata_name + + def __str__(self): + # type: () -> str + # Use `dist` in the error message because its stringification + # includes more information, like the version and location. + return ( + 'None {} metadata found for distribution: {}'.format( + self.metadata_name, self.dist, + ) + ) + + +class DistributionNotFound(InstallationError): + """Raised when a distribution cannot be found to satisfy a requirement""" + + +class RequirementsFileParseError(InstallationError): + """Raised when a general error occurs parsing a requirements file line.""" + + +class BestVersionAlreadyInstalled(PipError): + """Raised when the most up-to-date version of a package is already + installed.""" + + +class BadCommand(PipError): + """Raised when virtualenv or a command is not found""" + + +class CommandError(PipError): + """Raised when there is an error in command-line arguments""" + + +class PreviousBuildDirError(PipError): + """Raised when there's a previous conflicting build directory""" + + +class NetworkConnectionError(PipError): + """HTTP connection error""" + + def __init__(self, error_msg, response=None, request=None): + # type: (Text, Response, Request) -> None + """ + Initialize NetworkConnectionError with `request` and `response` + objects. + """ + self.response = response + self.request = request + self.error_msg = error_msg + if (self.response is not None and not self.request and + hasattr(response, 'request')): + self.request = self.response.request + super(NetworkConnectionError, self).__init__( + error_msg, response, request) + + def __str__(self): + # type: () -> str + return str(self.error_msg) + + +class InvalidWheelFilename(InstallationError): + """Invalid wheel filename.""" + + +class UnsupportedWheel(InstallationError): + """Unsupported wheel.""" + + +class MetadataInconsistent(InstallationError): + """Built metadata contains inconsistent information. + + This is raised when the metadata contains values (e.g. name and version) + that do not match the information previously obtained from sdist filename + or user-supplied ``#egg=`` value. + """ + def __init__(self, ireq, field, built): + # type: (InstallRequirement, str, Any) -> None + self.ireq = ireq + self.field = field + self.built = built + + def __str__(self): + # type: () -> str + return "Requested {} has different {} in metadata: {!r}".format( + self.ireq, self.field, self.built, + ) + + +class InstallationSubprocessError(InstallationError): + """A subprocess call failed during installation.""" + def __init__(self, returncode, description): + # type: (int, str) -> None + self.returncode = returncode + self.description = description + + def __str__(self): + # type: () -> str + return ( + "Command errored out with exit status {}: {} " + "Check the logs for full command output." + ).format(self.returncode, self.description) + + +class HashErrors(InstallationError): + """Multiple HashError instances rolled into one for reporting""" + + def __init__(self): + # type: () -> None + self.errors = [] # type: List[HashError] + + def append(self, error): + # type: (HashError) -> None + self.errors.append(error) + + def __str__(self): + # type: () -> str + lines = [] + self.errors.sort(key=lambda e: e.order) + for cls, errors_of_cls in groupby(self.errors, lambda e: e.__class__): + lines.append(cls.head) + lines.extend(e.body() for e in errors_of_cls) + if lines: + return '\n'.join(lines) + return '' + + def __nonzero__(self): + # type: () -> bool + return bool(self.errors) + + def __bool__(self): + # type: () -> bool + return self.__nonzero__() + + +class HashError(InstallationError): + """ + A failure to verify a package against known-good hashes + + :cvar order: An int sorting hash exception classes by difficulty of + recovery (lower being harder), so the user doesn't bother fretting + about unpinned packages when he has deeper issues, like VCS + dependencies, to deal with. Also keeps error reports in a + deterministic order. + :cvar head: A section heading for display above potentially many + exceptions of this kind + :ivar req: The InstallRequirement that triggered this error. This is + pasted on after the exception is instantiated, because it's not + typically available earlier. + + """ + req = None # type: Optional[InstallRequirement] + head = '' + order = -1 # type: int + + def body(self): + # type: () -> str + """Return a summary of me for display under the heading. + + This default implementation simply prints a description of the + triggering requirement. + + :param req: The InstallRequirement that provoked this error, with + its link already populated by the resolver's _populate_link(). + + """ + return ' {}'.format(self._requirement_name()) + + def __str__(self): + # type: () -> str + return '{}\n{}'.format(self.head, self.body()) + + def _requirement_name(self): + # type: () -> str + """Return a description of the requirement that triggered me. + + This default implementation returns long description of the req, with + line numbers + + """ + return str(self.req) if self.req else 'unknown package' + + +class VcsHashUnsupported(HashError): + """A hash was provided for a version-control-system-based requirement, but + we don't have a method for hashing those.""" + + order = 0 + head = ("Can't verify hashes for these requirements because we don't " + "have a way to hash version control repositories:") + + +class DirectoryUrlHashUnsupported(HashError): + """A hash was provided for a version-control-system-based requirement, but + we don't have a method for hashing those.""" + + order = 1 + head = ("Can't verify hashes for these file:// requirements because they " + "point to directories:") + + +class HashMissing(HashError): + """A hash was needed for a requirement but is absent.""" + + order = 2 + head = ('Hashes are required in --require-hashes mode, but they are ' + 'missing from some requirements. Here is a list of those ' + 'requirements along with the hashes their downloaded archives ' + 'actually had. Add lines like these to your requirements files to ' + 'prevent tampering. (If you did not enable --require-hashes ' + 'manually, note that it turns on automatically when any package ' + 'has a hash.)') + + def __init__(self, gotten_hash): + # type: (str) -> None + """ + :param gotten_hash: The hash of the (possibly malicious) archive we + just downloaded + """ + self.gotten_hash = gotten_hash + + def body(self): + # type: () -> str + # Dodge circular import. + from pip._internal.utils.hashes import FAVORITE_HASH + + package = None + if self.req: + # In the case of URL-based requirements, display the original URL + # seen in the requirements file rather than the package name, + # so the output can be directly copied into the requirements file. + package = (self.req.original_link if self.req.original_link + # In case someone feeds something downright stupid + # to InstallRequirement's constructor. + else getattr(self.req, 'req', None)) + return ' {} --hash={}:{}'.format(package or 'unknown package', + FAVORITE_HASH, + self.gotten_hash) + + +class HashUnpinned(HashError): + """A requirement had a hash specified but was not pinned to a specific + version.""" + + order = 3 + head = ('In --require-hashes mode, all requirements must have their ' + 'versions pinned with ==. These do not:') + + +class HashMismatch(HashError): + """ + Distribution file hash values don't match. + + :ivar package_name: The name of the package that triggered the hash + mismatch. Feel free to write to this after the exception is raise to + improve its error message. + + """ + order = 4 + head = ('THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS ' + 'FILE. If you have updated the package versions, please update ' + 'the hashes. Otherwise, examine the package contents carefully; ' + 'someone may have tampered with them.') + + def __init__(self, allowed, gots): + # type: (Dict[str, List[str]], Dict[str, _Hash]) -> None + """ + :param allowed: A dict of algorithm names pointing to lists of allowed + hex digests + :param gots: A dict of algorithm names pointing to hashes we + actually got from the files under suspicion + """ + self.allowed = allowed + self.gots = gots + + def body(self): + # type: () -> str + return ' {}:\n{}'.format(self._requirement_name(), + self._hash_comparison()) + + def _hash_comparison(self): + # type: () -> str + """ + Return a comparison of actual and expected hash values. + + Example:: + + Expected sha256 abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde + or 123451234512345123451234512345123451234512345 + Got bcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdef + + """ + def hash_then_or(hash_name): + # type: (str) -> chain[str] + # For now, all the decent hashes have 6-char names, so we can get + # away with hard-coding space literals. + return chain([hash_name], repeat(' or')) + + lines = [] # type: List[str] + for hash_name, expecteds in iteritems(self.allowed): + prefix = hash_then_or(hash_name) + lines.extend((' Expected {} {}'.format(next(prefix), e)) + for e in expecteds) + lines.append(' Got {}\n'.format( + self.gots[hash_name].hexdigest())) + return '\n'.join(lines) + + +class UnsupportedPythonVersion(InstallationError): + """Unsupported python version according to Requires-Python package + metadata.""" + + +class ConfigurationFileCouldNotBeLoaded(ConfigurationError): + """When there are errors while loading a configuration file + """ + + def __init__(self, reason="could not be loaded", fname=None, error=None): + # type: (str, Optional[str], Optional[configparser.Error]) -> None + super(ConfigurationFileCouldNotBeLoaded, self).__init__(error) + self.reason = reason + self.fname = fname + self.error = error + + def __str__(self): + # type: () -> str + if self.fname is not None: + message_part = " in {}.".format(self.fname) + else: + assert self.error is not None + message_part = ".\n{}\n".format(self.error) + return "Configuration file {}{}".format(self.reason, message_part) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/__init__.py new file mode 100644 index 0000000..7a17b7b --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/__init__.py @@ -0,0 +1,2 @@ +"""Index interaction code +""" diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..25447f97d5067e78a993e167f50d65134fb2723b GIT binary patch literal 254 zcmYjMyKVwO4BVp$LZVI=(Ng4GP(_NOv}tJQXjYqDi!<4?SGOBp5)!|YU!u(?Bo!4t zDlE-dWBD<54_{je-x1&XpZ*l) E3bV#bp8x;= literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/__pycache__/collector.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/__pycache__/collector.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..273146a8403854ef67a1490c9d7654b6bfaa8fac GIT binary patch literal 17779 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 X>NCb<{`sltsgp=u#fSgK@`wH}fi^h< literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/collector.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/collector.py new file mode 100644 index 0000000..b850b8c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/collector.py @@ -0,0 +1,667 @@ +""" +The main purpose of this module is to expose LinkCollector.collect_links(). +""" + +import cgi +import functools +import itertools +import logging +import mimetypes +import os +import re +from collections import OrderedDict + +from pip._vendor import html5lib, requests +from pip._vendor.distlib.compat import unescape +from pip._vendor.requests.exceptions import RetryError, SSLError +from pip._vendor.six.moves.urllib import parse as urllib_parse +from pip._vendor.six.moves.urllib import request as urllib_request + +from pip._internal.exceptions import NetworkConnectionError +from pip._internal.models.link import Link +from pip._internal.models.search_scope import SearchScope +from pip._internal.network.utils import raise_for_status +from pip._internal.utils.compat import lru_cache +from pip._internal.utils.filetypes import is_archive_file +from pip._internal.utils.misc import pairwise, redact_auth_from_url +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.urls import path_to_url, url_to_path +from pip._internal.vcs import is_url, vcs + +if MYPY_CHECK_RUNNING: + import xml.etree.ElementTree + from optparse import Values + from typing import ( + Callable, + Iterable, + List, + MutableMapping, + Optional, + Sequence, + Tuple, + Union, + ) + + from pip._vendor.requests import Response + + from pip._internal.network.session import PipSession + + HTMLElement = xml.etree.ElementTree.Element + ResponseHeaders = MutableMapping[str, str] + + +logger = logging.getLogger(__name__) + + +def _match_vcs_scheme(url): + # type: (str) -> Optional[str] + """Look for VCS schemes in the URL. + + Returns the matched VCS scheme, or None if there's no match. + """ + for scheme in vcs.schemes: + if url.lower().startswith(scheme) and url[len(scheme)] in '+:': + return scheme + return None + + +class _NotHTML(Exception): + def __init__(self, content_type, request_desc): + # type: (str, str) -> None + super(_NotHTML, self).__init__(content_type, request_desc) + self.content_type = content_type + self.request_desc = request_desc + + +def _ensure_html_header(response): + # type: (Response) -> None + """Check the Content-Type header to ensure the response contains HTML. + + Raises `_NotHTML` if the content type is not text/html. + """ + content_type = response.headers.get("Content-Type", "") + if not content_type.lower().startswith("text/html"): + raise _NotHTML(content_type, response.request.method) + + +class _NotHTTP(Exception): + pass + + +def _ensure_html_response(url, session): + # type: (str, PipSession) -> None + """Send a HEAD request to the URL, and ensure the response contains HTML. + + Raises `_NotHTTP` if the URL is not available for a HEAD request, or + `_NotHTML` if the content type is not text/html. + """ + scheme, netloc, path, query, fragment = urllib_parse.urlsplit(url) + if scheme not in {'http', 'https'}: + raise _NotHTTP() + + resp = session.head(url, allow_redirects=True) + raise_for_status(resp) + + _ensure_html_header(resp) + + +def _get_html_response(url, session): + # type: (str, PipSession) -> Response + """Access an HTML page with GET, and return the response. + + This consists of three parts: + + 1. If the URL looks suspiciously like an archive, send a HEAD first to + check the Content-Type is HTML, to avoid downloading a large file. + Raise `_NotHTTP` if the content type cannot be determined, or + `_NotHTML` if it is not HTML. + 2. Actually perform the request. Raise HTTP exceptions on network failures. + 3. Check the Content-Type header to make sure we got HTML, and raise + `_NotHTML` otherwise. + """ + if is_archive_file(Link(url).filename): + _ensure_html_response(url, session=session) + + logger.debug('Getting page %s', redact_auth_from_url(url)) + + resp = session.get( + url, + headers={ + "Accept": "text/html", + # We don't want to blindly returned cached data for + # /simple/, because authors generally expecting that + # twine upload && pip install will function, but if + # they've done a pip install in the last ~10 minutes + # it won't. Thus by setting this to zero we will not + # blindly use any cached data, however the benefit of + # using max-age=0 instead of no-cache, is that we will + # still support conditional requests, so we will still + # minimize traffic sent in cases where the page hasn't + # changed at all, we will just always incur the round + # trip for the conditional GET now instead of only + # once per 10 minutes. + # For more information, please see pypa/pip#5670. + "Cache-Control": "max-age=0", + }, + ) + raise_for_status(resp) + + # The check for archives above only works if the url ends with + # something that looks like an archive. However that is not a + # requirement of an url. Unless we issue a HEAD request on every + # url we cannot know ahead of time for sure if something is HTML + # or not. However we can check after we've downloaded it. + _ensure_html_header(resp) + + return resp + + +def _get_encoding_from_headers(headers): + # type: (ResponseHeaders) -> Optional[str] + """Determine if we have any encoding information in our headers. + """ + if headers and "Content-Type" in headers: + content_type, params = cgi.parse_header(headers["Content-Type"]) + if "charset" in params: + return params['charset'] + return None + + +def _determine_base_url(document, page_url): + # type: (HTMLElement, str) -> str + """Determine the HTML document's base URL. + + This looks for a ```` tag in the HTML document. If present, its href + attribute denotes the base URL of anchor tags in the document. If there is + no such tag (or if it does not have a valid href attribute), the HTML + file's URL is used as the base URL. + + :param document: An HTML document representation. The current + implementation expects the result of ``html5lib.parse()``. + :param page_url: The URL of the HTML document. + """ + for base in document.findall(".//base"): + href = base.get("href") + if href is not None: + return href + return page_url + + +def _clean_url_path_part(part): + # type: (str) -> str + """ + Clean a "part" of a URL path (i.e. after splitting on "@" characters). + """ + # We unquote prior to quoting to make sure nothing is double quoted. + return urllib_parse.quote(urllib_parse.unquote(part)) + + +def _clean_file_url_path(part): + # type: (str) -> str + """ + Clean the first part of a URL path that corresponds to a local + filesystem path (i.e. the first part after splitting on "@" characters). + """ + # We unquote prior to quoting to make sure nothing is double quoted. + # Also, on Windows the path part might contain a drive letter which + # should not be quoted. On Linux where drive letters do not + # exist, the colon should be quoted. We rely on urllib.request + # to do the right thing here. + return urllib_request.pathname2url(urllib_request.url2pathname(part)) + + +# percent-encoded: / +_reserved_chars_re = re.compile('(@|%2F)', re.IGNORECASE) + + +def _clean_url_path(path, is_local_path): + # type: (str, bool) -> str + """ + Clean the path portion of a URL. + """ + if is_local_path: + clean_func = _clean_file_url_path + else: + clean_func = _clean_url_path_part + + # Split on the reserved characters prior to cleaning so that + # revision strings in VCS URLs are properly preserved. + parts = _reserved_chars_re.split(path) + + cleaned_parts = [] + for to_clean, reserved in pairwise(itertools.chain(parts, [''])): + cleaned_parts.append(clean_func(to_clean)) + # Normalize %xx escapes (e.g. %2f -> %2F) + cleaned_parts.append(reserved.upper()) + + return ''.join(cleaned_parts) + + +def _clean_link(url): + # type: (str) -> str + """ + Make sure a link is fully quoted. + For example, if ' ' occurs in the URL, it will be replaced with "%20", + and without double-quoting other characters. + """ + # Split the URL into parts according to the general structure + # `scheme://netloc/path;parameters?query#fragment`. + result = urllib_parse.urlparse(url) + # If the netloc is empty, then the URL refers to a local filesystem path. + is_local_path = not result.netloc + path = _clean_url_path(result.path, is_local_path=is_local_path) + return urllib_parse.urlunparse(result._replace(path=path)) + + +def _create_link_from_element( + anchor, # type: HTMLElement + page_url, # type: str + base_url, # type: str +): + # type: (...) -> Optional[Link] + """ + Convert an anchor element in a simple repository page to a Link. + """ + href = anchor.get("href") + if not href: + return None + + url = _clean_link(urllib_parse.urljoin(base_url, href)) + pyrequire = anchor.get('data-requires-python') + pyrequire = unescape(pyrequire) if pyrequire else None + + yanked_reason = anchor.get('data-yanked') + if yanked_reason: + # This is a unicode string in Python 2 (and 3). + yanked_reason = unescape(yanked_reason) + + link = Link( + url, + comes_from=page_url, + requires_python=pyrequire, + yanked_reason=yanked_reason, + ) + + return link + + +class CacheablePageContent(object): + def __init__(self, page): + # type: (HTMLPage) -> None + assert page.cache_link_parsing + self.page = page + + def __eq__(self, other): + # type: (object) -> bool + return (isinstance(other, type(self)) and + self.page.url == other.page.url) + + def __hash__(self): + # type: () -> int + return hash(self.page.url) + + +def with_cached_html_pages( + fn, # type: Callable[[HTMLPage], Iterable[Link]] +): + # type: (...) -> Callable[[HTMLPage], List[Link]] + """ + Given a function that parses an Iterable[Link] from an HTMLPage, cache the + function's result (keyed by CacheablePageContent), unless the HTMLPage + `page` has `page.cache_link_parsing == False`. + """ + + @lru_cache(maxsize=None) + def wrapper(cacheable_page): + # type: (CacheablePageContent) -> List[Link] + return list(fn(cacheable_page.page)) + + @functools.wraps(fn) + def wrapper_wrapper(page): + # type: (HTMLPage) -> List[Link] + if page.cache_link_parsing: + return wrapper(CacheablePageContent(page)) + return list(fn(page)) + + return wrapper_wrapper + + +@with_cached_html_pages +def parse_links(page): + # type: (HTMLPage) -> Iterable[Link] + """ + Parse an HTML document, and yield its anchor elements as Link objects. + """ + document = html5lib.parse( + page.content, + transport_encoding=page.encoding, + namespaceHTMLElements=False, + ) + + url = page.url + base_url = _determine_base_url(document, url) + for anchor in document.findall(".//a"): + link = _create_link_from_element( + anchor, + page_url=url, + base_url=base_url, + ) + if link is None: + continue + yield link + + +class HTMLPage(object): + """Represents one page, along with its URL""" + + def __init__( + self, + content, # type: bytes + encoding, # type: Optional[str] + url, # type: str + cache_link_parsing=True, # type: bool + ): + # type: (...) -> None + """ + :param encoding: the encoding to decode the given content. + :param url: the URL from which the HTML was downloaded. + :param cache_link_parsing: whether links parsed from this page's url + should be cached. PyPI index urls should + have this set to False, for example. + """ + self.content = content + self.encoding = encoding + self.url = url + self.cache_link_parsing = cache_link_parsing + + def __str__(self): + # type: () -> str + return redact_auth_from_url(self.url) + + +def _handle_get_page_fail( + link, # type: Link + reason, # type: Union[str, Exception] + meth=None # type: Optional[Callable[..., None]] +): + # type: (...) -> None + if meth is None: + meth = logger.debug + meth("Could not fetch URL %s: %s - skipping", link, reason) + + +def _make_html_page(response, cache_link_parsing=True): + # type: (Response, bool) -> HTMLPage + encoding = _get_encoding_from_headers(response.headers) + return HTMLPage( + response.content, + encoding=encoding, + url=response.url, + cache_link_parsing=cache_link_parsing) + + +def _get_html_page(link, session=None): + # type: (Link, Optional[PipSession]) -> Optional[HTMLPage] + if session is None: + raise TypeError( + "_get_html_page() missing 1 required keyword argument: 'session'" + ) + + url = link.url.split('#', 1)[0] + + # Check for VCS schemes that do not support lookup as web pages. + vcs_scheme = _match_vcs_scheme(url) + if vcs_scheme: + logger.warning('Cannot look at %s URL %s because it does not support ' + 'lookup as web pages.', vcs_scheme, link) + return None + + # Tack index.html onto file:// URLs that point to directories + scheme, _, path, _, _, _ = urllib_parse.urlparse(url) + if (scheme == 'file' and os.path.isdir(urllib_request.url2pathname(path))): + # add trailing slash if not present so urljoin doesn't trim + # final segment + if not url.endswith('/'): + url += '/' + url = urllib_parse.urljoin(url, 'index.html') + logger.debug(' file: URL is directory, getting %s', url) + + try: + resp = _get_html_response(url, session=session) + except _NotHTTP: + logger.warning( + 'Skipping page %s because it looks like an archive, and cannot ' + 'be checked by a HTTP HEAD request.', link, + ) + except _NotHTML as exc: + logger.warning( + 'Skipping page %s because the %s request got Content-Type: %s.' + 'The only supported Content-Type is text/html', + link, exc.request_desc, exc.content_type, + ) + except NetworkConnectionError as exc: + _handle_get_page_fail(link, exc) + except RetryError as exc: + _handle_get_page_fail(link, exc) + except SSLError as exc: + reason = "There was a problem confirming the ssl certificate: " + reason += str(exc) + _handle_get_page_fail(link, reason, meth=logger.info) + except requests.ConnectionError as exc: + _handle_get_page_fail(link, "connection error: {}".format(exc)) + except requests.Timeout: + _handle_get_page_fail(link, "timed out") + else: + return _make_html_page(resp, + cache_link_parsing=link.cache_link_parsing) + return None + + +def _remove_duplicate_links(links): + # type: (Iterable[Link]) -> List[Link] + """ + Return a list of links, with duplicates removed and ordering preserved. + """ + # We preserve the ordering when removing duplicates because we can. + return list(OrderedDict.fromkeys(links)) + + +def group_locations(locations, expand_dir=False): + # type: (Sequence[str], bool) -> Tuple[List[str], List[str]] + """ + Divide a list of locations into two groups: "files" (archives) and "urls." + + :return: A pair of lists (files, urls). + """ + files = [] + urls = [] + + # puts the url for the given file path into the appropriate list + def sort_path(path): + # type: (str) -> None + url = path_to_url(path) + if mimetypes.guess_type(url, strict=False)[0] == 'text/html': + urls.append(url) + else: + files.append(url) + + for url in locations: + + is_local_path = os.path.exists(url) + is_file_url = url.startswith('file:') + + if is_local_path or is_file_url: + if is_local_path: + path = url + else: + path = url_to_path(url) + if os.path.isdir(path): + if expand_dir: + path = os.path.realpath(path) + for item in os.listdir(path): + sort_path(os.path.join(path, item)) + elif is_file_url: + urls.append(url) + else: + logger.warning( + "Path '%s' is ignored: it is a directory.", path, + ) + elif os.path.isfile(path): + sort_path(path) + else: + logger.warning( + "Url '%s' is ignored: it is neither a file " + "nor a directory.", url, + ) + elif is_url(url): + # Only add url with clear scheme + urls.append(url) + else: + logger.warning( + "Url '%s' is ignored. It is either a non-existing " + "path or lacks a specific scheme.", url, + ) + + return files, urls + + +class CollectedLinks(object): + + """ + Encapsulates the return value of a call to LinkCollector.collect_links(). + + The return value includes both URLs to project pages containing package + links, as well as individual package Link objects collected from other + sources. + + This info is stored separately as: + + (1) links from the configured file locations, + (2) links from the configured find_links, and + (3) urls to HTML project pages, as described by the PEP 503 simple + repository API. + """ + + def __init__( + self, + files, # type: List[Link] + find_links, # type: List[Link] + project_urls, # type: List[Link] + ): + # type: (...) -> None + """ + :param files: Links from file locations. + :param find_links: Links from find_links. + :param project_urls: URLs to HTML project pages, as described by + the PEP 503 simple repository API. + """ + self.files = files + self.find_links = find_links + self.project_urls = project_urls + + +class LinkCollector(object): + + """ + Responsible for collecting Link objects from all configured locations, + making network requests as needed. + + The class's main method is its collect_links() method. + """ + + def __init__( + self, + session, # type: PipSession + search_scope, # type: SearchScope + ): + # type: (...) -> None + self.search_scope = search_scope + self.session = session + + @classmethod + def create(cls, session, options, suppress_no_index=False): + # type: (PipSession, Values, bool) -> LinkCollector + """ + :param session: The Session to use to make requests. + :param suppress_no_index: Whether to ignore the --no-index option + when constructing the SearchScope object. + """ + index_urls = [options.index_url] + options.extra_index_urls + if options.no_index and not suppress_no_index: + logger.debug( + 'Ignoring indexes: %s', + ','.join(redact_auth_from_url(url) for url in index_urls), + ) + index_urls = [] + + # Make sure find_links is a list before passing to create(). + find_links = options.find_links or [] + + search_scope = SearchScope.create( + find_links=find_links, index_urls=index_urls, + ) + link_collector = LinkCollector( + session=session, search_scope=search_scope, + ) + return link_collector + + @property + def find_links(self): + # type: () -> List[str] + return self.search_scope.find_links + + def fetch_page(self, location): + # type: (Link) -> Optional[HTMLPage] + """ + Fetch an HTML page containing package links. + """ + return _get_html_page(location, session=self.session) + + def collect_links(self, project_name): + # type: (str) -> CollectedLinks + """Find all available links for the given project name. + + :return: All the Link objects (unfiltered), as a CollectedLinks object. + """ + search_scope = self.search_scope + index_locations = search_scope.get_index_urls_locations(project_name) + index_file_loc, index_url_loc = group_locations(index_locations) + fl_file_loc, fl_url_loc = group_locations( + self.find_links, expand_dir=True, + ) + + file_links = [ + Link(url) for url in itertools.chain(index_file_loc, fl_file_loc) + ] + + # We trust every directly linked archive in find_links + find_link_links = [Link(url, '-f') for url in self.find_links] + + # We trust every url that the user has given us whether it was given + # via --index-url or --find-links. + # We want to filter out anything that does not have a secure origin. + url_locations = [ + link for link in itertools.chain( + # Mark PyPI indices as "cache_link_parsing == False" -- this + # will avoid caching the result of parsing the page for links. + (Link(url, cache_link_parsing=False) for url in index_url_loc), + (Link(url) for url in fl_url_loc), + ) + if self.session.is_secure_origin(link) + ] + + url_locations = _remove_duplicate_links(url_locations) + lines = [ + '{} location(s) to search for versions of {}:'.format( + len(url_locations), project_name, + ), + ] + for link in url_locations: + lines.append('* {}'.format(link)) + logger.debug('\n'.join(lines)) + + return CollectedLinks( + files=file_links, + find_links=find_link_links, + project_urls=url_locations, + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/package_finder.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/package_finder.py new file mode 100644 index 0000000..9f39631 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/index/package_finder.py @@ -0,0 +1,1015 @@ +"""Routines related to PyPI, indexes""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +from __future__ import absolute_import + +import logging +import re + +from pip._vendor.packaging import specifiers +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.exceptions import ( + BestVersionAlreadyInstalled, + DistributionNotFound, + InvalidWheelFilename, + UnsupportedWheel, +) +from pip._internal.index.collector import parse_links +from pip._internal.models.candidate import InstallationCandidate +from pip._internal.models.format_control import FormatControl +from pip._internal.models.link import Link +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.models.target_python import TargetPython +from pip._internal.models.wheel import Wheel +from pip._internal.utils.compat import lru_cache +from pip._internal.utils.filetypes import WHEEL_EXTENSION +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import build_netloc +from pip._internal.utils.packaging import check_requires_python +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.unpacking import SUPPORTED_EXTENSIONS +from pip._internal.utils.urls import url_to_path + +if MYPY_CHECK_RUNNING: + from typing import FrozenSet, Iterable, List, Optional, Set, Text, Tuple, Union + + from pip._vendor.packaging.tags import Tag + from pip._vendor.packaging.version import _BaseVersion + + from pip._internal.index.collector import LinkCollector + from pip._internal.models.search_scope import SearchScope + from pip._internal.req import InstallRequirement + from pip._internal.utils.hashes import Hashes + + BuildTag = Union[Tuple[()], Tuple[int, str]] + CandidateSortingKey = ( + Tuple[int, int, int, _BaseVersion, BuildTag, Optional[int]] + ) + + +__all__ = ['FormatControl', 'BestCandidateResult', 'PackageFinder'] + + +logger = logging.getLogger(__name__) + + +def _check_link_requires_python( + link, # type: Link + version_info, # type: Tuple[int, int, int] + ignore_requires_python=False, # type: bool +): + # type: (...) -> bool + """ + Return whether the given Python version is compatible with a link's + "Requires-Python" value. + + :param version_info: A 3-tuple of ints representing the Python + major-minor-micro version to check. + :param ignore_requires_python: Whether to ignore the "Requires-Python" + value if the given Python version isn't compatible. + """ + try: + is_compatible = check_requires_python( + link.requires_python, version_info=version_info, + ) + except specifiers.InvalidSpecifier: + logger.debug( + "Ignoring invalid Requires-Python (%r) for link: %s", + link.requires_python, link, + ) + else: + if not is_compatible: + version = '.'.join(map(str, version_info)) + if not ignore_requires_python: + logger.debug( + 'Link requires a different Python (%s not in: %r): %s', + version, link.requires_python, link, + ) + return False + + logger.debug( + 'Ignoring failed Requires-Python check (%s not in: %r) ' + 'for link: %s', + version, link.requires_python, link, + ) + + return True + + +class LinkEvaluator(object): + + """ + Responsible for evaluating links for a particular project. + """ + + _py_version_re = re.compile(r'-py([123]\.?[0-9]?)$') + + # Don't include an allow_yanked default value to make sure each call + # site considers whether yanked releases are allowed. This also causes + # that decision to be made explicit in the calling code, which helps + # people when reading the code. + def __init__( + self, + project_name, # type: str + canonical_name, # type: str + formats, # type: FrozenSet[str] + target_python, # type: TargetPython + allow_yanked, # type: bool + ignore_requires_python=None, # type: Optional[bool] + ): + # type: (...) -> None + """ + :param project_name: The user supplied package name. + :param canonical_name: The canonical package name. + :param formats: The formats allowed for this package. Should be a set + with 'binary' or 'source' or both in it. + :param target_python: The target Python interpreter to use when + evaluating link compatibility. This is used, for example, to + check wheel compatibility, as well as when checking the Python + version, e.g. the Python version embedded in a link filename + (or egg fragment) and against an HTML link's optional PEP 503 + "data-requires-python" attribute. + :param allow_yanked: Whether files marked as yanked (in the sense + of PEP 592) are permitted to be candidates for install. + :param ignore_requires_python: Whether to ignore incompatible + PEP 503 "data-requires-python" values in HTML links. Defaults + to False. + """ + if ignore_requires_python is None: + ignore_requires_python = False + + self._allow_yanked = allow_yanked + self._canonical_name = canonical_name + self._ignore_requires_python = ignore_requires_python + self._formats = formats + self._target_python = target_python + + self.project_name = project_name + + def evaluate_link(self, link): + # type: (Link) -> Tuple[bool, Optional[Text]] + """ + Determine whether a link is a candidate for installation. + + :return: A tuple (is_candidate, result), where `result` is (1) a + version string if `is_candidate` is True, and (2) if + `is_candidate` is False, an optional string to log the reason + the link fails to qualify. + """ + version = None + if link.is_yanked and not self._allow_yanked: + reason = link.yanked_reason or '' + # Mark this as a unicode string to prevent "UnicodeEncodeError: + # 'ascii' codec can't encode character" in Python 2 when + # the reason contains non-ascii characters. + return (False, u'yanked for reason: {}'.format(reason)) + + if link.egg_fragment: + egg_info = link.egg_fragment + ext = link.ext + else: + egg_info, ext = link.splitext() + if not ext: + return (False, 'not a file') + if ext not in SUPPORTED_EXTENSIONS: + return (False, 'unsupported archive format: {}'.format(ext)) + if "binary" not in self._formats and ext == WHEEL_EXTENSION: + reason = 'No binaries permitted for {}'.format( + self.project_name) + return (False, reason) + if "macosx10" in link.path and ext == '.zip': + return (False, 'macosx10 one') + if ext == WHEEL_EXTENSION: + try: + wheel = Wheel(link.filename) + except InvalidWheelFilename: + return (False, 'invalid wheel filename') + if canonicalize_name(wheel.name) != self._canonical_name: + reason = 'wrong project name (not {})'.format( + self.project_name) + return (False, reason) + + supported_tags = self._target_python.get_tags() + if not wheel.supported(supported_tags): + # Include the wheel's tags in the reason string to + # simplify troubleshooting compatibility issues. + file_tags = wheel.get_formatted_file_tags() + reason = ( + "none of the wheel's tags match: {}".format( + ', '.join(file_tags) + ) + ) + return (False, reason) + + version = wheel.version + + # This should be up by the self.ok_binary check, but see issue 2700. + if "source" not in self._formats and ext != WHEEL_EXTENSION: + reason = 'No sources permitted for {}'.format(self.project_name) + return (False, reason) + + if not version: + version = _extract_version_from_fragment( + egg_info, self._canonical_name, + ) + if not version: + reason = 'Missing project version for {}'.format(self.project_name) + return (False, reason) + + match = self._py_version_re.search(version) + if match: + version = version[:match.start()] + py_version = match.group(1) + if py_version != self._target_python.py_version: + return (False, 'Python version is incorrect') + + supports_python = _check_link_requires_python( + link, version_info=self._target_python.py_version_info, + ignore_requires_python=self._ignore_requires_python, + ) + if not supports_python: + # Return None for the reason text to suppress calling + # _log_skipped_link(). + return (False, None) + + logger.debug('Found link %s, version: %s', link, version) + + return (True, version) + + +def filter_unallowed_hashes( + candidates, # type: List[InstallationCandidate] + hashes, # type: Hashes + project_name, # type: str +): + # type: (...) -> List[InstallationCandidate] + """ + Filter out candidates whose hashes aren't allowed, and return a new + list of candidates. + + If at least one candidate has an allowed hash, then all candidates with + either an allowed hash or no hash specified are returned. Otherwise, + the given candidates are returned. + + Including the candidates with no hash specified when there is a match + allows a warning to be logged if there is a more preferred candidate + with no hash specified. Returning all candidates in the case of no + matches lets pip report the hash of the candidate that would otherwise + have been installed (e.g. permitting the user to more easily update + their requirements file with the desired hash). + """ + if not hashes: + logger.debug( + 'Given no hashes to check %s links for project %r: ' + 'discarding no candidates', + len(candidates), + project_name, + ) + # Make sure we're not returning back the given value. + return list(candidates) + + matches_or_no_digest = [] + # Collect the non-matches for logging purposes. + non_matches = [] + match_count = 0 + for candidate in candidates: + link = candidate.link + if not link.has_hash: + pass + elif link.is_hash_allowed(hashes=hashes): + match_count += 1 + else: + non_matches.append(candidate) + continue + + matches_or_no_digest.append(candidate) + + if match_count: + filtered = matches_or_no_digest + else: + # Make sure we're not returning back the given value. + filtered = list(candidates) + + if len(filtered) == len(candidates): + discard_message = 'discarding no candidates' + else: + discard_message = 'discarding {} non-matches:\n {}'.format( + len(non_matches), + '\n '.join(str(candidate.link) for candidate in non_matches) + ) + + logger.debug( + 'Checked %s links for project %r against %s hashes ' + '(%s matches, %s no digest): %s', + len(candidates), + project_name, + hashes.digest_count, + match_count, + len(matches_or_no_digest) - match_count, + discard_message + ) + + return filtered + + +class CandidatePreferences(object): + + """ + Encapsulates some of the preferences for filtering and sorting + InstallationCandidate objects. + """ + + def __init__( + self, + prefer_binary=False, # type: bool + allow_all_prereleases=False, # type: bool + ): + # type: (...) -> None + """ + :param allow_all_prereleases: Whether to allow all pre-releases. + """ + self.allow_all_prereleases = allow_all_prereleases + self.prefer_binary = prefer_binary + + +class BestCandidateResult(object): + """A collection of candidates, returned by `PackageFinder.find_best_candidate`. + + This class is only intended to be instantiated by CandidateEvaluator's + `compute_best_candidate()` method. + """ + + def __init__( + self, + candidates, # type: List[InstallationCandidate] + applicable_candidates, # type: List[InstallationCandidate] + best_candidate, # type: Optional[InstallationCandidate] + ): + # type: (...) -> None + """ + :param candidates: A sequence of all available candidates found. + :param applicable_candidates: The applicable candidates. + :param best_candidate: The most preferred candidate found, or None + if no applicable candidates were found. + """ + assert set(applicable_candidates) <= set(candidates) + + if best_candidate is None: + assert not applicable_candidates + else: + assert best_candidate in applicable_candidates + + self._applicable_candidates = applicable_candidates + self._candidates = candidates + + self.best_candidate = best_candidate + + def iter_all(self): + # type: () -> Iterable[InstallationCandidate] + """Iterate through all candidates. + """ + return iter(self._candidates) + + def iter_applicable(self): + # type: () -> Iterable[InstallationCandidate] + """Iterate through the applicable candidates. + """ + return iter(self._applicable_candidates) + + +class CandidateEvaluator(object): + + """ + Responsible for filtering and sorting candidates for installation based + on what tags are valid. + """ + + @classmethod + def create( + cls, + project_name, # type: str + target_python=None, # type: Optional[TargetPython] + prefer_binary=False, # type: bool + allow_all_prereleases=False, # type: bool + specifier=None, # type: Optional[specifiers.BaseSpecifier] + hashes=None, # type: Optional[Hashes] + ): + # type: (...) -> CandidateEvaluator + """Create a CandidateEvaluator object. + + :param target_python: The target Python interpreter to use when + checking compatibility. If None (the default), a TargetPython + object will be constructed from the running Python. + :param specifier: An optional object implementing `filter` + (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable + versions. + :param hashes: An optional collection of allowed hashes. + """ + if target_python is None: + target_python = TargetPython() + if specifier is None: + specifier = specifiers.SpecifierSet() + + supported_tags = target_python.get_tags() + + return cls( + project_name=project_name, + supported_tags=supported_tags, + specifier=specifier, + prefer_binary=prefer_binary, + allow_all_prereleases=allow_all_prereleases, + hashes=hashes, + ) + + def __init__( + self, + project_name, # type: str + supported_tags, # type: List[Tag] + specifier, # type: specifiers.BaseSpecifier + prefer_binary=False, # type: bool + allow_all_prereleases=False, # type: bool + hashes=None, # type: Optional[Hashes] + ): + # type: (...) -> None + """ + :param supported_tags: The PEP 425 tags supported by the target + Python in order of preference (most preferred first). + """ + self._allow_all_prereleases = allow_all_prereleases + self._hashes = hashes + self._prefer_binary = prefer_binary + self._project_name = project_name + self._specifier = specifier + self._supported_tags = supported_tags + + def get_applicable_candidates( + self, + candidates, # type: List[InstallationCandidate] + ): + # type: (...) -> List[InstallationCandidate] + """ + Return the applicable candidates from a list of candidates. + """ + # Using None infers from the specifier instead. + allow_prereleases = self._allow_all_prereleases or None + specifier = self._specifier + versions = { + str(v) for v in specifier.filter( + # We turn the version object into a str here because otherwise + # when we're debundled but setuptools isn't, Python will see + # packaging.version.Version and + # pkg_resources._vendor.packaging.version.Version as different + # types. This way we'll use a str as a common data interchange + # format. If we stop using the pkg_resources provided specifier + # and start using our own, we can drop the cast to str(). + (str(c.version) for c in candidates), + prereleases=allow_prereleases, + ) + } + + # Again, converting version to str to deal with debundling. + applicable_candidates = [ + c for c in candidates if str(c.version) in versions + ] + + filtered_applicable_candidates = filter_unallowed_hashes( + candidates=applicable_candidates, + hashes=self._hashes, + project_name=self._project_name, + ) + + return sorted(filtered_applicable_candidates, key=self._sort_key) + + def _sort_key(self, candidate): + # type: (InstallationCandidate) -> CandidateSortingKey + """ + Function to pass as the `key` argument to a call to sorted() to sort + InstallationCandidates by preference. + + Returns a tuple such that tuples sorting as greater using Python's + default comparison operator are more preferred. + + The preference is as follows: + + First and foremost, candidates with allowed (matching) hashes are + always preferred over candidates without matching hashes. This is + because e.g. if the only candidate with an allowed hash is yanked, + we still want to use that candidate. + + Second, excepting hash considerations, candidates that have been + yanked (in the sense of PEP 592) are always less preferred than + candidates that haven't been yanked. Then: + + If not finding wheels, they are sorted by version only. + If finding wheels, then the sort order is by version, then: + 1. existing installs + 2. wheels ordered via Wheel.support_index_min(self._supported_tags) + 3. source archives + If prefer_binary was set, then all wheels are sorted above sources. + + Note: it was considered to embed this logic into the Link + comparison operators, but then different sdist links + with the same version, would have to be considered equal + """ + valid_tags = self._supported_tags + support_num = len(valid_tags) + build_tag = () # type: BuildTag + binary_preference = 0 + link = candidate.link + if link.is_wheel: + # can raise InvalidWheelFilename + wheel = Wheel(link.filename) + if not wheel.supported(valid_tags): + raise UnsupportedWheel( + "{} is not a supported wheel for this platform. It " + "can't be sorted.".format(wheel.filename) + ) + if self._prefer_binary: + binary_preference = 1 + pri = -(wheel.support_index_min(valid_tags)) + if wheel.build_tag is not None: + match = re.match(r'^(\d+)(.*)$', wheel.build_tag) + build_tag_groups = match.groups() + build_tag = (int(build_tag_groups[0]), build_tag_groups[1]) + else: # sdist + pri = -(support_num) + has_allowed_hash = int(link.is_hash_allowed(self._hashes)) + yank_value = -1 * int(link.is_yanked) # -1 for yanked. + return ( + has_allowed_hash, yank_value, binary_preference, candidate.version, + build_tag, pri, + ) + + def sort_best_candidate( + self, + candidates, # type: List[InstallationCandidate] + ): + # type: (...) -> Optional[InstallationCandidate] + """ + Return the best candidate per the instance's sort order, or None if + no candidate is acceptable. + """ + if not candidates: + return None + best_candidate = max(candidates, key=self._sort_key) + return best_candidate + + def compute_best_candidate( + self, + candidates, # type: List[InstallationCandidate] + ): + # type: (...) -> BestCandidateResult + """ + Compute and return a `BestCandidateResult` instance. + """ + applicable_candidates = self.get_applicable_candidates(candidates) + + best_candidate = self.sort_best_candidate(applicable_candidates) + + return BestCandidateResult( + candidates, + applicable_candidates=applicable_candidates, + best_candidate=best_candidate, + ) + + +class PackageFinder(object): + """This finds packages. + + This is meant to match easy_install's technique for looking for + packages, by reading pages and looking for appropriate links. + """ + + def __init__( + self, + link_collector, # type: LinkCollector + target_python, # type: TargetPython + allow_yanked, # type: bool + format_control=None, # type: Optional[FormatControl] + candidate_prefs=None, # type: CandidatePreferences + ignore_requires_python=None, # type: Optional[bool] + ): + # type: (...) -> None + """ + This constructor is primarily meant to be used by the create() class + method and from tests. + + :param format_control: A FormatControl object, used to control + the selection of source packages / binary packages when consulting + the index and links. + :param candidate_prefs: Options to use when creating a + CandidateEvaluator object. + """ + if candidate_prefs is None: + candidate_prefs = CandidatePreferences() + + format_control = format_control or FormatControl(set(), set()) + + self._allow_yanked = allow_yanked + self._candidate_prefs = candidate_prefs + self._ignore_requires_python = ignore_requires_python + self._link_collector = link_collector + self._target_python = target_python + + self.format_control = format_control + + # These are boring links that have already been logged somehow. + self._logged_links = set() # type: Set[Link] + + # Don't include an allow_yanked default value to make sure each call + # site considers whether yanked releases are allowed. This also causes + # that decision to be made explicit in the calling code, which helps + # people when reading the code. + @classmethod + def create( + cls, + link_collector, # type: LinkCollector + selection_prefs, # type: SelectionPreferences + target_python=None, # type: Optional[TargetPython] + ): + # type: (...) -> PackageFinder + """Create a PackageFinder. + + :param selection_prefs: The candidate selection preferences, as a + SelectionPreferences object. + :param target_python: The target Python interpreter to use when + checking compatibility. If None (the default), a TargetPython + object will be constructed from the running Python. + """ + if target_python is None: + target_python = TargetPython() + + candidate_prefs = CandidatePreferences( + prefer_binary=selection_prefs.prefer_binary, + allow_all_prereleases=selection_prefs.allow_all_prereleases, + ) + + return cls( + candidate_prefs=candidate_prefs, + link_collector=link_collector, + target_python=target_python, + allow_yanked=selection_prefs.allow_yanked, + format_control=selection_prefs.format_control, + ignore_requires_python=selection_prefs.ignore_requires_python, + ) + + @property + def target_python(self): + # type: () -> TargetPython + return self._target_python + + @property + def search_scope(self): + # type: () -> SearchScope + return self._link_collector.search_scope + + @search_scope.setter + def search_scope(self, search_scope): + # type: (SearchScope) -> None + self._link_collector.search_scope = search_scope + + @property + def find_links(self): + # type: () -> List[str] + return self._link_collector.find_links + + @property + def index_urls(self): + # type: () -> List[str] + return self.search_scope.index_urls + + @property + def trusted_hosts(self): + # type: () -> Iterable[str] + for host_port in self._link_collector.session.pip_trusted_origins: + yield build_netloc(*host_port) + + @property + def allow_all_prereleases(self): + # type: () -> bool + return self._candidate_prefs.allow_all_prereleases + + def set_allow_all_prereleases(self): + # type: () -> None + self._candidate_prefs.allow_all_prereleases = True + + @property + def prefer_binary(self): + # type: () -> bool + return self._candidate_prefs.prefer_binary + + def set_prefer_binary(self): + # type: () -> None + self._candidate_prefs.prefer_binary = True + + def make_link_evaluator(self, project_name): + # type: (str) -> LinkEvaluator + canonical_name = canonicalize_name(project_name) + formats = self.format_control.get_allowed_formats(canonical_name) + + return LinkEvaluator( + project_name=project_name, + canonical_name=canonical_name, + formats=formats, + target_python=self._target_python, + allow_yanked=self._allow_yanked, + ignore_requires_python=self._ignore_requires_python, + ) + + def _sort_links(self, links): + # type: (Iterable[Link]) -> List[Link] + """ + Returns elements of links in order, non-egg links first, egg links + second, while eliminating duplicates + """ + eggs, no_eggs = [], [] + seen = set() # type: Set[Link] + for link in links: + if link not in seen: + seen.add(link) + if link.egg_fragment: + eggs.append(link) + else: + no_eggs.append(link) + return no_eggs + eggs + + def _log_skipped_link(self, link, reason): + # type: (Link, Text) -> None + if link not in self._logged_links: + # Mark this as a unicode string to prevent "UnicodeEncodeError: + # 'ascii' codec can't encode character" in Python 2 when + # the reason contains non-ascii characters. + # Also, put the link at the end so the reason is more visible + # and because the link string is usually very long. + logger.debug(u'Skipping link: %s: %s', reason, link) + self._logged_links.add(link) + + def get_install_candidate(self, link_evaluator, link): + # type: (LinkEvaluator, Link) -> Optional[InstallationCandidate] + """ + If the link is a candidate for install, convert it to an + InstallationCandidate and return it. Otherwise, return None. + """ + is_candidate, result = link_evaluator.evaluate_link(link) + if not is_candidate: + if result: + self._log_skipped_link(link, reason=result) + return None + + return InstallationCandidate( + name=link_evaluator.project_name, + link=link, + # Convert the Text result to str since InstallationCandidate + # accepts str. + version=str(result), + ) + + def evaluate_links(self, link_evaluator, links): + # type: (LinkEvaluator, Iterable[Link]) -> List[InstallationCandidate] + """ + Convert links that are candidates to InstallationCandidate objects. + """ + candidates = [] + for link in self._sort_links(links): + candidate = self.get_install_candidate(link_evaluator, link) + if candidate is not None: + candidates.append(candidate) + + return candidates + + def process_project_url(self, project_url, link_evaluator): + # type: (Link, LinkEvaluator) -> List[InstallationCandidate] + logger.debug( + 'Fetching project page and analyzing links: %s', project_url, + ) + html_page = self._link_collector.fetch_page(project_url) + if html_page is None: + return [] + + page_links = list(parse_links(html_page)) + + with indent_log(): + package_links = self.evaluate_links( + link_evaluator, + links=page_links, + ) + + return package_links + + @lru_cache(maxsize=None) + def find_all_candidates(self, project_name): + # type: (str) -> List[InstallationCandidate] + """Find all available InstallationCandidate for project_name + + This checks index_urls and find_links. + All versions found are returned as an InstallationCandidate list. + + See LinkEvaluator.evaluate_link() for details on which files + are accepted. + """ + collected_links = self._link_collector.collect_links(project_name) + + link_evaluator = self.make_link_evaluator(project_name) + + find_links_versions = self.evaluate_links( + link_evaluator, + links=collected_links.find_links, + ) + + page_versions = [] + for project_url in collected_links.project_urls: + package_links = self.process_project_url( + project_url, link_evaluator=link_evaluator, + ) + page_versions.extend(package_links) + + file_versions = self.evaluate_links( + link_evaluator, + links=collected_links.files, + ) + if file_versions: + file_versions.sort(reverse=True) + logger.debug( + 'Local files found: %s', + ', '.join([ + url_to_path(candidate.link.url) + for candidate in file_versions + ]) + ) + + # This is an intentional priority ordering + return file_versions + find_links_versions + page_versions + + def make_candidate_evaluator( + self, + project_name, # type: str + specifier=None, # type: Optional[specifiers.BaseSpecifier] + hashes=None, # type: Optional[Hashes] + ): + # type: (...) -> CandidateEvaluator + """Create a CandidateEvaluator object to use. + """ + candidate_prefs = self._candidate_prefs + return CandidateEvaluator.create( + project_name=project_name, + target_python=self._target_python, + prefer_binary=candidate_prefs.prefer_binary, + allow_all_prereleases=candidate_prefs.allow_all_prereleases, + specifier=specifier, + hashes=hashes, + ) + + @lru_cache(maxsize=None) + def find_best_candidate( + self, + project_name, # type: str + specifier=None, # type: Optional[specifiers.BaseSpecifier] + hashes=None, # type: Optional[Hashes] + ): + # type: (...) -> BestCandidateResult + """Find matches for the given project and specifier. + + :param specifier: An optional object implementing `filter` + (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable + versions. + + :return: A `BestCandidateResult` instance. + """ + candidates = self.find_all_candidates(project_name) + candidate_evaluator = self.make_candidate_evaluator( + project_name=project_name, + specifier=specifier, + hashes=hashes, + ) + return candidate_evaluator.compute_best_candidate(candidates) + + def find_requirement(self, req, upgrade): + # type: (InstallRequirement, bool) -> Optional[InstallationCandidate] + """Try to find a Link matching req + + Expects req, an InstallRequirement and upgrade, a boolean + Returns a InstallationCandidate if found, + Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise + """ + hashes = req.hashes(trust_internet=False) + best_candidate_result = self.find_best_candidate( + req.name, specifier=req.specifier, hashes=hashes, + ) + best_candidate = best_candidate_result.best_candidate + + installed_version = None # type: Optional[_BaseVersion] + if req.satisfied_by is not None: + installed_version = parse_version(req.satisfied_by.version) + + def _format_versions(cand_iter): + # type: (Iterable[InstallationCandidate]) -> str + # This repeated parse_version and str() conversion is needed to + # handle different vendoring sources from pip and pkg_resources. + # If we stop using the pkg_resources provided specifier and start + # using our own, we can drop the cast to str(). + return ", ".join(sorted( + {str(c.version) for c in cand_iter}, + key=parse_version, + )) or "none" + + if installed_version is None and best_candidate is None: + logger.critical( + 'Could not find a version that satisfies the requirement %s ' + '(from versions: %s)', + req, + _format_versions(best_candidate_result.iter_all()), + ) + + raise DistributionNotFound( + 'No matching distribution found for {}'.format( + req) + ) + + best_installed = False + if installed_version and ( + best_candidate is None or + best_candidate.version <= installed_version): + best_installed = True + + if not upgrade and installed_version is not None: + if best_installed: + logger.debug( + 'Existing installed version (%s) is most up-to-date and ' + 'satisfies requirement', + installed_version, + ) + else: + logger.debug( + 'Existing installed version (%s) satisfies requirement ' + '(most up-to-date version is %s)', + installed_version, + best_candidate.version, + ) + return None + + if best_installed: + # We have an existing version, and its the best version + logger.debug( + 'Installed version (%s) is most up-to-date (past versions: ' + '%s)', + installed_version, + _format_versions(best_candidate_result.iter_applicable()), + ) + raise BestVersionAlreadyInstalled + + logger.debug( + 'Using version %s (newest of versions: %s)', + best_candidate.version, + _format_versions(best_candidate_result.iter_applicable()), + ) + return best_candidate + + +def _find_name_version_sep(fragment, canonical_name): + # type: (str, str) -> int + """Find the separator's index based on the package's canonical name. + + :param fragment: A + filename "fragment" (stem) or + egg fragment. + :param canonical_name: The package's canonical name. + + This function is needed since the canonicalized name does not necessarily + have the same length as the egg info's name part. An example:: + + >>> fragment = 'foo__bar-1.0' + >>> canonical_name = 'foo-bar' + >>> _find_name_version_sep(fragment, canonical_name) + 8 + """ + # Project name and version must be separated by one single dash. Find all + # occurrences of dashes; if the string in front of it matches the canonical + # name, this is the one separating the name and version parts. + for i, c in enumerate(fragment): + if c != "-": + continue + if canonicalize_name(fragment[:i]) == canonical_name: + return i + raise ValueError("{} does not match {}".format(fragment, canonical_name)) + + +def _extract_version_from_fragment(fragment, canonical_name): + # type: (str, str) -> Optional[str] + """Parse the version string from a + filename + "fragment" (stem) or egg fragment. + + :param fragment: The string to parse. E.g. foo-2.1 + :param canonical_name: The canonicalized name of the package this + belongs to. + """ + try: + version_start = _find_name_version_sep(fragment, canonical_name) + 1 + except ValueError: + return None + version = fragment[version_start:] + if not version: + return None + return version diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/locations.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/locations.py new file mode 100644 index 0000000..f521844 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/locations.py @@ -0,0 +1,199 @@ +"""Locations where we look for configs, install stuff, etc""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +from __future__ import absolute_import + +import os +import os.path +import platform +import site +import sys +import sysconfig +from distutils import sysconfig as distutils_sysconfig +from distutils.command.install import SCHEME_KEYS # type: ignore +from distutils.command.install import install as distutils_install_command + +from pip._internal.models.scheme import Scheme +from pip._internal.utils import appdirs +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.typing import MYPY_CHECK_RUNNING, cast +from pip._internal.utils.virtualenv import running_under_virtualenv + +if MYPY_CHECK_RUNNING: + from distutils.cmd import Command as DistutilsCommand + from typing import Dict, List, Optional, Union + + +# Application Directories +USER_CACHE_DIR = appdirs.user_cache_dir("pip") + + +def get_major_minor_version(): + # type: () -> str + """ + Return the major-minor version of the current Python as a string, e.g. + "3.7" or "3.10". + """ + return '{}.{}'.format(*sys.version_info) + + +def get_src_prefix(): + # type: () -> str + if running_under_virtualenv(): + src_prefix = os.path.join(sys.prefix, 'src') + else: + # FIXME: keep src in cwd for now (it is not a temporary folder) + try: + src_prefix = os.path.join(os.getcwd(), 'src') + except OSError: + # In case the current working directory has been renamed or deleted + sys.exit( + "The folder you are executing pip from can no longer be found." + ) + + # under macOS + virtualenv sys.prefix is not properly resolved + # it is something like /path/to/python/bin/.. + return os.path.abspath(src_prefix) + + +# FIXME doesn't account for venv linked to global site-packages + +# The python2.7 part of this is Debian specific: +# https://github.com/pypa/pip/issues/5193 +# https://bitbucket.org/pypy/pypy/issues/2506/sysconfig-returns-incorrect-paths +can_not_depend_on_purelib = ( + sys.version_info[:2] == (2, 7) or + platform.python_implementation().lower() == "pypy" +) +site_packages = None # type: Optional[str] +if can_not_depend_on_purelib: + site_packages = distutils_sysconfig.get_python_lib() +else: + site_packages = sysconfig.get_path("purelib") + +try: + # Use getusersitepackages if this is present, as it ensures that the + # value is initialised properly. + user_site = site.getusersitepackages() +except AttributeError: + user_site = site.USER_SITE + +if WINDOWS: + bin_py = os.path.join(sys.prefix, 'Scripts') + bin_user = os.path.join(user_site, 'Scripts') + # buildout uses 'bin' on Windows too? + if not os.path.exists(bin_py): + bin_py = os.path.join(sys.prefix, 'bin') + bin_user = os.path.join(user_site, 'bin') +else: + bin_py = os.path.join(sys.prefix, 'bin') + bin_user = os.path.join(user_site, 'bin') + + # Forcing to use /usr/local/bin for standard macOS framework installs + # Also log to ~/Library/Logs/ for use with the Console.app log viewer + if sys.platform[:6] == 'darwin' and sys.prefix[:16] == '/System/Library/': + bin_py = '/usr/local/bin' + + +def distutils_scheme( + dist_name, user=False, home=None, root=None, isolated=False, prefix=None +): + # type:(str, bool, str, str, bool, str) -> Dict[str, str] + """ + Return a distutils install scheme + """ + from distutils.dist import Distribution + + dist_args = {'name': dist_name} # type: Dict[str, Union[str, List[str]]] + if isolated: + dist_args["script_args"] = ["--no-user-cfg"] + + d = Distribution(dist_args) + d.parse_config_files() + obj = None # type: Optional[DistutilsCommand] + obj = d.get_command_obj('install', create=True) + assert obj is not None + i = cast(distutils_install_command, obj) + # NOTE: setting user or home has the side-effect of creating the home dir + # or user base for installations during finalize_options() + # ideally, we'd prefer a scheme class that has no side-effects. + assert not (user and prefix), "user={} prefix={}".format(user, prefix) + assert not (home and prefix), "home={} prefix={}".format(home, prefix) + i.user = user or i.user + if user or home: + i.prefix = "" + i.prefix = prefix or i.prefix + i.home = home or i.home + i.root = root or i.root + i.finalize_options() + + scheme = {} + for key in SCHEME_KEYS: + scheme[key] = getattr(i, 'install_' + key) + + # install_lib specified in setup.cfg should install *everything* + # into there (i.e. it takes precedence over both purelib and + # platlib). Note, i.install_lib is *always* set after + # finalize_options(); we only want to override here if the user + # has explicitly requested it hence going back to the config + if 'install_lib' in d.get_option_dict('install'): + scheme.update(dict(purelib=i.install_lib, platlib=i.install_lib)) + + if running_under_virtualenv(): + scheme['headers'] = os.path.join( + i.prefix, + 'include', + 'site', + 'python{}'.format(get_major_minor_version()), + dist_name, + ) + + if root is not None: + path_no_drive = os.path.splitdrive( + os.path.abspath(scheme["headers"]))[1] + scheme["headers"] = os.path.join( + root, + path_no_drive[1:], + ) + + return scheme + + +def get_scheme( + dist_name, # type: str + user=False, # type: bool + home=None, # type: Optional[str] + root=None, # type: Optional[str] + isolated=False, # type: bool + prefix=None, # type: Optional[str] +): + # type: (...) -> Scheme + """ + Get the "scheme" corresponding to the input parameters. The distutils + documentation provides the context for the available schemes: + https://docs.python.org/3/install/index.html#alternate-installation + + :param dist_name: the name of the package to retrieve the scheme for, used + in the headers scheme path + :param user: indicates to use the "user" scheme + :param home: indicates to use the "home" scheme and provides the base + directory for the same + :param root: root under which other directories are re-based + :param isolated: equivalent to --no-user-cfg, i.e. do not consider + ~/.pydistutils.cfg (posix) or ~/pydistutils.cfg (non-posix) for + scheme paths + :param prefix: indicates to use the "prefix" scheme and provides the + base directory for the same + """ + scheme = distutils_scheme( + dist_name, user, home, root, isolated, prefix + ) + return Scheme( + platlib=scheme["platlib"], + purelib=scheme["purelib"], + headers=scheme["headers"], + scripts=scheme["scripts"], + data=scheme["data"], + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/main.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/main.py new file mode 100644 index 0000000..1c99c49 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/main.py @@ -0,0 +1,16 @@ +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional + + +def main(args=None): + # type: (Optional[List[str]]) -> int + """This is preserved for old console scripts that may still be referencing + it. + + For additional details, see https://github.com/pypa/pip/issues/7498. + """ + from pip._internal.utils.entrypoints import _wrapper + + return _wrapper(args) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__init__.py new file mode 100644 index 0000000..7855226 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__init__.py @@ -0,0 +1,2 @@ +"""A package that contains models that represent entities. +""" diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c2cab0b90844aaf62a7275dbde987d54a1262f7f GIT binary patch literal 288 zcmYjMJ5EDE4BVH7C{pgQZ3>7HhsU@^uVYj{6xK*A zekuvG9KwdRp&+X_k`hY4xLI|(qYzRVLU?y=W@~@t`whl2Az;o_R3FO7QW&HSU~7s% zd`7Xtaf)g}6S9yM*2vf_f_{U%flT*Mw>lO+>CZsOx_@^HRH_h&6&uG4heIJ)LK;F} Rx4Zedg-;nT_FsP*-493USa<*c literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/candidate.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/candidate.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bdf14eb32669f8f9c55d875244d390f034548c5f GIT binary patch literal 1515 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/format_control.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/format_control.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e1cf73f2716b6fea42fa3a1a1df5bf0bd64d07ea GIT binary patch literal 2773 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 Zkkj$cC>lk5HdEA#`ZR7a_T#N+{tqZxp?LrR literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/scheme.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/scheme.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..324562d2217687586ed2cda2e13be46f7b9ae9be GIT binary patch literal 976 zcmZWn&2H2%5KcDPpQf#f#Fc{ur9ME*Rs$CL3lpFBLwBC_(!Z0=;j^G*Rg!8uxF0X0NSd{<;Qa644e~dQfbmeaUo%UK%64wiUyo zge72}wHG8?Km|@3X4l}>8aB+%nOsY47=m#nS}RX}@D?I_NlR29x&fH~tmtJXTtxkk!(c z$Tp=eN+un!6%un2!-LsOA~2;L6y7>b8Nr(3cQEfbWt_#_vQxADb* z3cR=Ahsw`r;A4Vqyp2S(?GeV?gs`_w36pJ~FjW!tIKFT(MUDqeieTn0+;=3M$OWyq zet?koHgbD3{rSpEy95r#XzTr@Ei1GYM^|tMwM8yBfD~{{v=ZngR7m>ZogO^!d=1r_ zQ!jYe*pvJjM@_MJ&q7}7nhQ;GpspIevE(J=BVpH zejjr&9)=5*T!IiyCIqEhncyD?@p&c9-N{f05*uyrPtM++zdsl6&Oc6?Jt5Fok3zWp zz(XKl2g1MIkl=s@29ic`nx?&W?_!*~qY&_bpc&ZNCH1;J*~!o*3~8Fti>|Vlp&1yc IPe-HVFC8fjr~m)} literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7cf201c6bb72e61032c7e85f1a29849a6dc1857f GIT binary patch literal 3469 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 L?u9Yxg}vxM`%LW6 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/target_python.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/target_python.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..16f22d0c6b861973fbc8b9898b98120700cd6682 GIT binary patch literal 3392 zcmcInU6UI}6`k%GNwZq5Z31@U0IsHrN~~f%0vjH185iIfCj}_3uuw$cn#`(O(yZqz z-L2hdBR#F*jsM_KyzrOil`5+I&QnO0bMA~*AM21eMm2Y4`s2>+b5EZ;iuU%}4vxv< zKheK0JI=r8Ve|0t@N=AI0wW#C5@$eHp0Jb;cg)nlbioM&O2jq=duVV29>c3F8X%XJzh@u>4csx1 z_&XbTvMoK?c*X_|*_5qk&Y&rMxr1v(O{**Slx+c z^?j9!ayL8%`ZBc9*z|{u4e*+{Z{d7^(~Mx|eC~v>l1&|b!?GjXN&Xjp-C6L=x9*&u zu?3gzbI&$xlg3Gpde8W0Y|)sznBAItu>PFE?#vso?aJ$}q?S&_p+m9y-{_uFN})xaDsdQf|VQK5QJ9&rDhxc*8OcHs4ywFi#5vei$dQomE>RC}wXPv881BFF3Blr=lflImRMJLK& zz%2<8y(MD^7nO(JSY=A1sRyED$Gs#z>=l*t-U)u%Gcm@V?~z^+7d>bg#1(a*m*!F> zrdR7LG?L^R$t(R3V`3YIHxQM%2IIWmCc~0M1QS(>TeyW6|DgpZ<%d=agcp|d37Su{d+5n;4*y?@#O~kpi3gQH< z#L!8A%$+Bf7R)+xcEgpBTtJKKc4^|UvDp4S7>V3|{R?O$fS24eZp@{j$pZNmy26e^( z`lvR~v4T1OjBl)g_fK1&E`Iju_w)jv2+cZ@uB(X*rTbLP$_C2cR9#q>7U=&YPD4e| z14;as-A1*I^y_G;LtYUd4&Ov;d3g!{d3`S1cmvhfsWKPdPGl7K=@wG7r77r&qwnH|xL8%}U*eAV%If+J?o!p}l=TIt>P?Kq zNqlWe{x@&oRyDiw06w^<|5!2d17)YWE^X`b`S{^u@#EV+!8Z;{GL#?ncleY9TP39E zGN!$5L^O`*ODAZryrB@*lc*fya|y1i5(&MO^yxH$;H!~BQ68d}q&bRz-Jq!?#@g78 zBGT`AWoxN&>pYbniE_79iCCRT;*=)Bu18g}*Y&Dw)|z({{iR1Mx|l$piUM^!!H_z6 zt+q=kgS>FgIP>WDMYGxD7sTa!X4mWE==vm5S(K_UEZboSC7UL6-wDHyr%|%(X@#N8 zhiKjjLzCpzgrWW}MgKOLACMv8-7vI4HT_E{kPrquT}lsEBY#W z%eNq@!AepCd|@Oec(o?hpb>oK8(%dejm@wwEpL8Rx1AOEiqIsaWpnvJjMen9sePD1 zJr5N?<~pbaA5(%V4LjAm{P0K(Z592-iYovrUGneMFy1HqHdM%beuZ^dhkNW>yyJce Dm1mDQ literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/wheel.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4098cdf4538762b3c80ebbe3b3c6423921c17620 GIT binary patch literal 3240 zcmbVO&vVcNvXyl}hoOs$Q9y@Ux)(#4Bmn0Mr zfObJyVyPY?%_OIGrhkEStN)*#FunEEb9>5k#{J$xgvi**q2yq(`*!#3+xNcrJp_x3 z4FkWy;eUd^qxVl5%>HZ)-ov9lLBoxX!5KFr)?s*CkvX(F79*J**~3bwqWhJoI;?eS z%n&vC9_Ff%Gpu*&%=pmYHSQc6+!2i7JN_r%0#KBOY6J+in*c0wh1aTPmy~e*_ zyRp?`x%ElV$7}gcyca|v|1BML8z<35$S?iov%8=9w?5ju^(+70r(0WhwmyW^{&lFb zE~%LPm5$kfR2XoG(J?veSi(N3a8uYj)l;)m;}*A%jgG@Byoz_da6qTQ>%4*S0$+d& znt4T=GH$*jn#5W%D z-+#XPh~{rD-+erqoO5(PX-L@2IqT0b@p|D_;2N{}hC}I_2L0`l|Le%#5M7-CI z!tHi?kPVXfP4Aty3b8f~x?co+q1tJfw*4^9gp7lzJxsWWR9ka^mmcKxbtSTHGE6r- zx^)#zm6>e$>G(CBF`kdTVdneZdX#j7NNsrKj;+>(d{JxiDSo~bd1VNn4kTeVuOfgL z=FT*@d8IFtQJU9qwJ7KcS)*k&goy5x*L9fuEa>MIl}2HfH*~~kQpp#vR$ihFb$u9? zsg@2ZlCYawIH&LdVXW{$ zeVs6~pURD&L-ubx#`t=1&A!O|B33Y|2qhUh6Y=TRmYG)z%jHiagY((O1=rYgAm1mNJ;ZlKSaKrM{Sg*MI5!i8s)azpf0f=4AV$lb32NtfUmv&b9`lTsJht`|yu4{ZWL<{I^4R~87n?wy~!hI$bhY3!{2SiUu3CwD1W{*6h z_y<8W5}Q&ca?QQd14TdI*@Y#VC){Gm+==w6D0*LVK?&N?9-qLLTIt^pU=_& zF@{6sOuPXnqI=+c8%Wdfoe5Nd?{A^`|HagK;9913OWp_-K6iE!lp}eg^vyYU)XT_! zRQjYkzA)z#!ME@|2TG?h@B4Yf_fgbFs6T$*^!?pY5S`7`e4i&>h)qSnmDe6@ z-uvap_c!HBWWejxw5fTEnqN?JPH3fNk_zJmJc>$?!)z1P!?OQt*PIufigQuVx0>=@ z+P{vb^CIf5=YuVHBE6y*)2FgV8*y5GMK72ZW>4&QMXJfCsGi0Ca(a}7k@B*G6iOt) pKChk)DteG??}%=u&3K;uxwBq4X@km_BFxy9V>ZnuYvL+R>wgz1Zb$$C literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/candidate.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/candidate.py new file mode 100644 index 0000000..0d89a8c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/candidate.py @@ -0,0 +1,39 @@ +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.utils.models import KeyBasedCompareMixin +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from pip._vendor.packaging.version import _BaseVersion + + from pip._internal.models.link import Link + + +class InstallationCandidate(KeyBasedCompareMixin): + """Represents a potential "candidate" for installation. + """ + + __slots__ = ["name", "version", "link"] + + def __init__(self, name, version, link): + # type: (str, str, Link) -> None + self.name = name + self.version = parse_version(version) # type: _BaseVersion + self.link = link + + super(InstallationCandidate, self).__init__( + key=(self.name, self.version, self.link), + defining_class=InstallationCandidate + ) + + def __repr__(self): + # type: () -> str + return "".format( + self.name, self.version, self.link, + ) + + def __str__(self): + # type: () -> str + return '{!r} candidate (version {} at {})'.format( + self.name, self.version, self.link, + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/direct_url.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/direct_url.py new file mode 100644 index 0000000..99aa68d --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/direct_url.py @@ -0,0 +1,243 @@ +""" PEP 610 """ +import json +import re + +from pip._vendor import six +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, Iterable, Optional, Type, TypeVar, Union + + T = TypeVar("T") + + +DIRECT_URL_METADATA_NAME = "direct_url.json" +ENV_VAR_RE = re.compile(r"^\$\{[A-Za-z0-9-_]+\}(:\$\{[A-Za-z0-9-_]+\})?$") + +__all__ = [ + "DirectUrl", + "DirectUrlValidationError", + "DirInfo", + "ArchiveInfo", + "VcsInfo", +] + + +class DirectUrlValidationError(Exception): + pass + + +def _get(d, expected_type, key, default=None): + # type: (Dict[str, Any], Type[T], str, Optional[T]) -> Optional[T] + """Get value from dictionary and verify expected type.""" + if key not in d: + return default + value = d[key] + if six.PY2 and expected_type is str: + expected_type = six.string_types # type: ignore + if not isinstance(value, expected_type): + raise DirectUrlValidationError( + "{!r} has unexpected type for {} (expected {})".format( + value, key, expected_type + ) + ) + return value + + +def _get_required(d, expected_type, key, default=None): + # type: (Dict[str, Any], Type[T], str, Optional[T]) -> T + value = _get(d, expected_type, key, default) + if value is None: + raise DirectUrlValidationError("{} must have a value".format(key)) + return value + + +def _exactly_one_of(infos): + # type: (Iterable[Optional[InfoType]]) -> InfoType + infos = [info for info in infos if info is not None] + if not infos: + raise DirectUrlValidationError( + "missing one of archive_info, dir_info, vcs_info" + ) + if len(infos) > 1: + raise DirectUrlValidationError( + "more than one of archive_info, dir_info, vcs_info" + ) + assert infos[0] is not None + return infos[0] + + +def _filter_none(**kwargs): + # type: (Any) -> Dict[str, Any] + """Make dict excluding None values.""" + return {k: v for k, v in kwargs.items() if v is not None} + + +class VcsInfo(object): + name = "vcs_info" + + def __init__( + self, + vcs, # type: str + commit_id, # type: str + requested_revision=None, # type: Optional[str] + resolved_revision=None, # type: Optional[str] + resolved_revision_type=None, # type: Optional[str] + ): + self.vcs = vcs + self.requested_revision = requested_revision + self.commit_id = commit_id + self.resolved_revision = resolved_revision + self.resolved_revision_type = resolved_revision_type + + @classmethod + def _from_dict(cls, d): + # type: (Optional[Dict[str, Any]]) -> Optional[VcsInfo] + if d is None: + return None + return cls( + vcs=_get_required(d, str, "vcs"), + commit_id=_get_required(d, str, "commit_id"), + requested_revision=_get(d, str, "requested_revision"), + resolved_revision=_get(d, str, "resolved_revision"), + resolved_revision_type=_get(d, str, "resolved_revision_type"), + ) + + def _to_dict(self): + # type: () -> Dict[str, Any] + return _filter_none( + vcs=self.vcs, + requested_revision=self.requested_revision, + commit_id=self.commit_id, + resolved_revision=self.resolved_revision, + resolved_revision_type=self.resolved_revision_type, + ) + + +class ArchiveInfo(object): + name = "archive_info" + + def __init__( + self, + hash=None, # type: Optional[str] + ): + self.hash = hash + + @classmethod + def _from_dict(cls, d): + # type: (Optional[Dict[str, Any]]) -> Optional[ArchiveInfo] + if d is None: + return None + return cls(hash=_get(d, str, "hash")) + + def _to_dict(self): + # type: () -> Dict[str, Any] + return _filter_none(hash=self.hash) + + +class DirInfo(object): + name = "dir_info" + + def __init__( + self, + editable=False, # type: bool + ): + self.editable = editable + + @classmethod + def _from_dict(cls, d): + # type: (Optional[Dict[str, Any]]) -> Optional[DirInfo] + if d is None: + return None + return cls( + editable=_get_required(d, bool, "editable", default=False) + ) + + def _to_dict(self): + # type: () -> Dict[str, Any] + return _filter_none(editable=self.editable or None) + + +if MYPY_CHECK_RUNNING: + InfoType = Union[ArchiveInfo, DirInfo, VcsInfo] + + +class DirectUrl(object): + + def __init__( + self, + url, # type: str + info, # type: InfoType + subdirectory=None, # type: Optional[str] + ): + self.url = url + self.info = info + self.subdirectory = subdirectory + + def _remove_auth_from_netloc(self, netloc): + # type: (str) -> str + if "@" not in netloc: + return netloc + user_pass, netloc_no_user_pass = netloc.split("@", 1) + if ( + isinstance(self.info, VcsInfo) and + self.info.vcs == "git" and + user_pass == "git" + ): + return netloc + if ENV_VAR_RE.match(user_pass): + return netloc + return netloc_no_user_pass + + @property + def redacted_url(self): + # type: () -> str + """url with user:password part removed unless it is formed with + environment variables as specified in PEP 610, or it is ``git`` + in the case of a git URL. + """ + purl = urllib_parse.urlsplit(self.url) + netloc = self._remove_auth_from_netloc(purl.netloc) + surl = urllib_parse.urlunsplit( + (purl.scheme, netloc, purl.path, purl.query, purl.fragment) + ) + return surl + + def validate(self): + # type: () -> None + self.from_dict(self.to_dict()) + + @classmethod + def from_dict(cls, d): + # type: (Dict[str, Any]) -> DirectUrl + return DirectUrl( + url=_get_required(d, str, "url"), + subdirectory=_get(d, str, "subdirectory"), + info=_exactly_one_of( + [ + ArchiveInfo._from_dict(_get(d, dict, "archive_info")), + DirInfo._from_dict(_get(d, dict, "dir_info")), + VcsInfo._from_dict(_get(d, dict, "vcs_info")), + ] + ), + ) + + def to_dict(self): + # type: () -> Dict[str, Any] + res = _filter_none( + url=self.redacted_url, + subdirectory=self.subdirectory, + ) + res[self.info.name] = self.info._to_dict() + return res + + @classmethod + def from_json(cls, s): + # type: (str) -> DirectUrl + return cls.from_dict(json.loads(s)) + + def to_json(self): + # type: () -> str + return json.dumps(self.to_dict(), sort_keys=True) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/format_control.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/format_control.py new file mode 100644 index 0000000..adcf61e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/format_control.py @@ -0,0 +1,92 @@ +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import CommandError +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import FrozenSet, Optional, Set + + +class FormatControl(object): + """Helper for managing formats from which a package can be installed. + """ + + __slots__ = ["no_binary", "only_binary"] + + def __init__(self, no_binary=None, only_binary=None): + # type: (Optional[Set[str]], Optional[Set[str]]) -> None + if no_binary is None: + no_binary = set() + if only_binary is None: + only_binary = set() + + self.no_binary = no_binary + self.only_binary = only_binary + + def __eq__(self, other): + # type: (object) -> bool + if not isinstance(other, self.__class__): + return NotImplemented + + if self.__slots__ != other.__slots__: + return False + + return all( + getattr(self, k) == getattr(other, k) + for k in self.__slots__ + ) + + def __ne__(self, other): + # type: (object) -> bool + return not self.__eq__(other) + + def __repr__(self): + # type: () -> str + return "{}({}, {})".format( + self.__class__.__name__, + self.no_binary, + self.only_binary + ) + + @staticmethod + def handle_mutual_excludes(value, target, other): + # type: (str, Set[str], Set[str]) -> None + if value.startswith('-'): + raise CommandError( + "--no-binary / --only-binary option requires 1 argument." + ) + new = value.split(',') + while ':all:' in new: + other.clear() + target.clear() + target.add(':all:') + del new[:new.index(':all:') + 1] + # Without a none, we want to discard everything as :all: covers it + if ':none:' not in new: + return + for name in new: + if name == ':none:': + target.clear() + continue + name = canonicalize_name(name) + other.discard(name) + target.add(name) + + def get_allowed_formats(self, canonical_name): + # type: (str) -> FrozenSet[str] + result = {"binary", "source"} + if canonical_name in self.only_binary: + result.discard('source') + elif canonical_name in self.no_binary: + result.discard('binary') + elif ':all:' in self.only_binary: + result.discard('source') + elif ':all:' in self.no_binary: + result.discard('binary') + return frozenset(result) + + def disallow_binaries(self): + # type: () -> None + self.handle_mutual_excludes( + ':all:', self.no_binary, self.only_binary, + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/index.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/index.py new file mode 100644 index 0000000..5b4a1fe --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/index.py @@ -0,0 +1,34 @@ +from pip._vendor.six.moves.urllib import parse as urllib_parse + + +class PackageIndex(object): + """Represents a Package Index and provides easier access to endpoints + """ + + __slots__ = ['url', 'netloc', 'simple_url', 'pypi_url', + 'file_storage_domain'] + + def __init__(self, url, file_storage_domain): + # type: (str, str) -> None + super(PackageIndex, self).__init__() + self.url = url + self.netloc = urllib_parse.urlsplit(url).netloc + self.simple_url = self._url_for_path('simple') + self.pypi_url = self._url_for_path('pypi') + + # This is part of a temporary hack used to block installs of PyPI + # packages which depend on external urls only necessary until PyPI can + # block such packages themselves + self.file_storage_domain = file_storage_domain + + def _url_for_path(self, path): + # type: (str) -> str + return urllib_parse.urljoin(self.url, path) + + +PyPI = PackageIndex( + 'https://pypi.org/', file_storage_domain='files.pythonhosted.org' +) +TestPyPI = PackageIndex( + 'https://test.pypi.org/', file_storage_domain='test-files.pythonhosted.org' +) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/link.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/link.py new file mode 100644 index 0000000..29ef402 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/link.py @@ -0,0 +1,246 @@ +import os +import posixpath +import re + +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.utils.filetypes import WHEEL_EXTENSION +from pip._internal.utils.misc import ( + redact_auth_from_url, + split_auth_from_netloc, + splitext, +) +from pip._internal.utils.models import KeyBasedCompareMixin +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.urls import path_to_url, url_to_path + +if MYPY_CHECK_RUNNING: + from typing import Optional, Text, Tuple, Union + + from pip._internal.index.collector import HTMLPage + from pip._internal.utils.hashes import Hashes + + +class Link(KeyBasedCompareMixin): + """Represents a parsed link from a Package Index's simple URL + """ + + __slots__ = [ + "_parsed_url", + "_url", + "comes_from", + "requires_python", + "yanked_reason", + "cache_link_parsing", + ] + + def __init__( + self, + url, # type: str + comes_from=None, # type: Optional[Union[str, HTMLPage]] + requires_python=None, # type: Optional[str] + yanked_reason=None, # type: Optional[Text] + cache_link_parsing=True, # type: bool + ): + # type: (...) -> None + """ + :param url: url of the resource pointed to (href of the link) + :param comes_from: instance of HTMLPage where the link was found, + or string. + :param requires_python: String containing the `Requires-Python` + metadata field, specified in PEP 345. This may be specified by + a data-requires-python attribute in the HTML link tag, as + described in PEP 503. + :param yanked_reason: the reason the file has been yanked, if the + file has been yanked, or None if the file hasn't been yanked. + This is the value of the "data-yanked" attribute, if present, in + a simple repository HTML link. If the file has been yanked but + no reason was provided, this should be the empty string. See + PEP 592 for more information and the specification. + :param cache_link_parsing: A flag that is used elsewhere to determine + whether resources retrieved from this link + should be cached. PyPI index urls should + generally have this set to False, for + example. + """ + + # url can be a UNC windows share + if url.startswith('\\\\'): + url = path_to_url(url) + + self._parsed_url = urllib_parse.urlsplit(url) + # Store the url as a private attribute to prevent accidentally + # trying to set a new value. + self._url = url + + self.comes_from = comes_from + self.requires_python = requires_python if requires_python else None + self.yanked_reason = yanked_reason + + super(Link, self).__init__(key=url, defining_class=Link) + + self.cache_link_parsing = cache_link_parsing + + def __str__(self): + # type: () -> str + if self.requires_python: + rp = ' (requires-python:{})'.format(self.requires_python) + else: + rp = '' + if self.comes_from: + return '{} (from {}){}'.format( + redact_auth_from_url(self._url), self.comes_from, rp) + else: + return redact_auth_from_url(str(self._url)) + + def __repr__(self): + # type: () -> str + return ''.format(self) + + @property + def url(self): + # type: () -> str + return self._url + + @property + def filename(self): + # type: () -> str + path = self.path.rstrip('/') + name = posixpath.basename(path) + if not name: + # Make sure we don't leak auth information if the netloc + # includes a username and password. + netloc, user_pass = split_auth_from_netloc(self.netloc) + return netloc + + name = urllib_parse.unquote(name) + assert name, ( + 'URL {self._url!r} produced no filename'.format(**locals())) + return name + + @property + def file_path(self): + # type: () -> str + return url_to_path(self.url) + + @property + def scheme(self): + # type: () -> str + return self._parsed_url.scheme + + @property + def netloc(self): + # type: () -> str + """ + This can contain auth information. + """ + return self._parsed_url.netloc + + @property + def path(self): + # type: () -> str + return urllib_parse.unquote(self._parsed_url.path) + + def splitext(self): + # type: () -> Tuple[str, str] + return splitext(posixpath.basename(self.path.rstrip('/'))) + + @property + def ext(self): + # type: () -> str + return self.splitext()[1] + + @property + def url_without_fragment(self): + # type: () -> str + scheme, netloc, path, query, fragment = self._parsed_url + return urllib_parse.urlunsplit((scheme, netloc, path, query, None)) + + _egg_fragment_re = re.compile(r'[#&]egg=([^&]*)') + + @property + def egg_fragment(self): + # type: () -> Optional[str] + match = self._egg_fragment_re.search(self._url) + if not match: + return None + return match.group(1) + + _subdirectory_fragment_re = re.compile(r'[#&]subdirectory=([^&]*)') + + @property + def subdirectory_fragment(self): + # type: () -> Optional[str] + match = self._subdirectory_fragment_re.search(self._url) + if not match: + return None + return match.group(1) + + _hash_re = re.compile( + r'(sha1|sha224|sha384|sha256|sha512|md5)=([a-f0-9]+)' + ) + + @property + def hash(self): + # type: () -> Optional[str] + match = self._hash_re.search(self._url) + if match: + return match.group(2) + return None + + @property + def hash_name(self): + # type: () -> Optional[str] + match = self._hash_re.search(self._url) + if match: + return match.group(1) + return None + + @property + def show_url(self): + # type: () -> str + return posixpath.basename(self._url.split('#', 1)[0].split('?', 1)[0]) + + @property + def is_file(self): + # type: () -> bool + return self.scheme == 'file' + + def is_existing_dir(self): + # type: () -> bool + return self.is_file and os.path.isdir(self.file_path) + + @property + def is_wheel(self): + # type: () -> bool + return self.ext == WHEEL_EXTENSION + + @property + def is_vcs(self): + # type: () -> bool + from pip._internal.vcs import vcs + + return self.scheme in vcs.all_schemes + + @property + def is_yanked(self): + # type: () -> bool + return self.yanked_reason is not None + + @property + def has_hash(self): + # type: () -> bool + return self.hash_name is not None + + def is_hash_allowed(self, hashes): + # type: (Optional[Hashes]) -> bool + """ + Return True if the link has a hash and it is allowed. + """ + if hashes is None or not self.has_hash: + return False + # Assert non-None so mypy knows self.hash_name and self.hash are str. + assert self.hash_name is not None + assert self.hash is not None + + return hashes.is_hash_allowed(self.hash_name, hex_digest=self.hash) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/scheme.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/scheme.py new file mode 100644 index 0000000..5040551 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/scheme.py @@ -0,0 +1,31 @@ +""" +For types associated with installation schemes. + +For a general overview of available schemes and their context, see +https://docs.python.org/3/install/index.html#alternate-installation. +""" + + +SCHEME_KEYS = ['platlib', 'purelib', 'headers', 'scripts', 'data'] + + +class Scheme(object): + """A Scheme holds paths which are used as the base directories for + artifacts associated with a Python package. + """ + + __slots__ = SCHEME_KEYS + + def __init__( + self, + platlib, # type: str + purelib, # type: str + headers, # type: str + scripts, # type: str + data, # type: str + ): + self.platlib = platlib + self.purelib = purelib + self.headers = headers + self.scripts = scripts + self.data = data diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/search_scope.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/search_scope.py new file mode 100644 index 0000000..d732504 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/search_scope.py @@ -0,0 +1,135 @@ +import itertools +import logging +import os +import posixpath + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.models.index import PyPI +from pip._internal.utils.compat import has_tls +from pip._internal.utils.misc import normalize_path, redact_auth_from_url +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List + + +logger = logging.getLogger(__name__) + + +class SearchScope(object): + + """ + Encapsulates the locations that pip is configured to search. + """ + + __slots__ = ["find_links", "index_urls"] + + @classmethod + def create( + cls, + find_links, # type: List[str] + index_urls, # type: List[str] + ): + # type: (...) -> SearchScope + """ + Create a SearchScope object after normalizing the `find_links`. + """ + # Build find_links. If an argument starts with ~, it may be + # a local file relative to a home directory. So try normalizing + # it and if it exists, use the normalized version. + # This is deliberately conservative - it might be fine just to + # blindly normalize anything starting with a ~... + built_find_links = [] # type: List[str] + for link in find_links: + if link.startswith('~'): + new_link = normalize_path(link) + if os.path.exists(new_link): + link = new_link + built_find_links.append(link) + + # If we don't have TLS enabled, then WARN if anyplace we're looking + # relies on TLS. + if not has_tls(): + for link in itertools.chain(index_urls, built_find_links): + parsed = urllib_parse.urlparse(link) + if parsed.scheme == 'https': + logger.warning( + 'pip is configured with locations that require ' + 'TLS/SSL, however the ssl module in Python is not ' + 'available.' + ) + break + + return cls( + find_links=built_find_links, + index_urls=index_urls, + ) + + def __init__( + self, + find_links, # type: List[str] + index_urls, # type: List[str] + ): + # type: (...) -> None + self.find_links = find_links + self.index_urls = index_urls + + def get_formatted_locations(self): + # type: () -> str + lines = [] + redacted_index_urls = [] + if self.index_urls and self.index_urls != [PyPI.simple_url]: + for url in self.index_urls: + + redacted_index_url = redact_auth_from_url(url) + + # Parse the URL + purl = urllib_parse.urlsplit(redacted_index_url) + + # URL is generally invalid if scheme and netloc is missing + # there are issues with Python and URL parsing, so this test + # is a bit crude. See bpo-20271, bpo-23505. Python doesn't + # always parse invalid URLs correctly - it should raise + # exceptions for malformed URLs + if not purl.scheme and not purl.netloc: + logger.warning( + 'The index url "%s" seems invalid, ' + 'please provide a scheme.', redacted_index_url) + + redacted_index_urls.append(redacted_index_url) + + lines.append('Looking in indexes: {}'.format( + ', '.join(redacted_index_urls))) + + if self.find_links: + lines.append( + 'Looking in links: {}'.format(', '.join( + redact_auth_from_url(url) for url in self.find_links)) + ) + return '\n'.join(lines) + + def get_index_urls_locations(self, project_name): + # type: (str) -> List[str] + """Returns the locations found via self.index_urls + + Checks the url_name on the main (first in the list) index and + use this url_name to produce all locations + """ + + def mkurl_pypi_url(url): + # type: (str) -> str + loc = posixpath.join( + url, + urllib_parse.quote(canonicalize_name(project_name))) + # For maximum compatibility with easy_install, ensure the path + # ends in a trailing slash. Although this isn't in the spec + # (and PyPI can handle it without the slash) some other index + # implementations might break if they relied on easy_install's + # behavior. + if not loc.endswith('/'): + loc = loc + '/' + return loc + + return [mkurl_pypi_url(url) for url in self.index_urls] diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/selection_prefs.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/selection_prefs.py new file mode 100644 index 0000000..83110dd --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/selection_prefs.py @@ -0,0 +1,50 @@ +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Optional + + from pip._internal.models.format_control import FormatControl + + +class SelectionPreferences(object): + """ + Encapsulates the candidate selection preferences for downloading + and installing files. + """ + + __slots__ = ['allow_yanked', 'allow_all_prereleases', 'format_control', + 'prefer_binary', 'ignore_requires_python'] + + # Don't include an allow_yanked default value to make sure each call + # site considers whether yanked releases are allowed. This also causes + # that decision to be made explicit in the calling code, which helps + # people when reading the code. + def __init__( + self, + allow_yanked, # type: bool + allow_all_prereleases=False, # type: bool + format_control=None, # type: Optional[FormatControl] + prefer_binary=False, # type: bool + ignore_requires_python=None, # type: Optional[bool] + ): + # type: (...) -> None + """Create a SelectionPreferences object. + + :param allow_yanked: Whether files marked as yanked (in the sense + of PEP 592) are permitted to be candidates for install. + :param format_control: A FormatControl object or None. Used to control + the selection of source packages / binary packages when consulting + the index and links. + :param prefer_binary: Whether to prefer an old, but valid, binary + dist over a new source dist. + :param ignore_requires_python: Whether to ignore incompatible + "Requires-Python" values in links. Defaults to False. + """ + if ignore_requires_python is None: + ignore_requires_python = False + + self.allow_yanked = allow_yanked + self.allow_all_prereleases = allow_all_prereleases + self.format_control = format_control + self.prefer_binary = prefer_binary + self.ignore_requires_python = ignore_requires_python diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/target_python.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/target_python.py new file mode 100644 index 0000000..4593dc8 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/target_python.py @@ -0,0 +1,117 @@ +import sys + +from pip._internal.utils.compatibility_tags import get_supported, version_info_to_nodot +from pip._internal.utils.misc import normalize_version_info +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional, Tuple + + from pip._vendor.packaging.tags import Tag + + +class TargetPython(object): + + """ + Encapsulates the properties of a Python interpreter one is targeting + for a package install, download, etc. + """ + + __slots__ = [ + "_given_py_version_info", + "abis", + "implementation", + "platforms", + "py_version", + "py_version_info", + "_valid_tags", + ] + + def __init__( + self, + platforms=None, # type: Optional[List[str]] + py_version_info=None, # type: Optional[Tuple[int, ...]] + abis=None, # type: Optional[List[str]] + implementation=None, # type: Optional[str] + ): + # type: (...) -> None + """ + :param platforms: A list of strings or None. If None, searches for + packages that are supported by the current system. Otherwise, will + find packages that can be built on the platforms passed in. These + packages will only be downloaded for distribution: they will + not be built locally. + :param py_version_info: An optional tuple of ints representing the + Python version information to use (e.g. `sys.version_info[:3]`). + This can have length 1, 2, or 3 when provided. + :param abis: A list of strings or None. This is passed to + compatibility_tags.py's get_supported() function as is. + :param implementation: A string or None. This is passed to + compatibility_tags.py's get_supported() function as is. + """ + # Store the given py_version_info for when we call get_supported(). + self._given_py_version_info = py_version_info + + if py_version_info is None: + py_version_info = sys.version_info[:3] + else: + py_version_info = normalize_version_info(py_version_info) + + py_version = '.'.join(map(str, py_version_info[:2])) + + self.abis = abis + self.implementation = implementation + self.platforms = platforms + self.py_version = py_version + self.py_version_info = py_version_info + + # This is used to cache the return value of get_tags(). + self._valid_tags = None # type: Optional[List[Tag]] + + def format_given(self): + # type: () -> str + """ + Format the given, non-None attributes for display. + """ + display_version = None + if self._given_py_version_info is not None: + display_version = '.'.join( + str(part) for part in self._given_py_version_info + ) + + key_values = [ + ('platforms', self.platforms), + ('version_info', display_version), + ('abis', self.abis), + ('implementation', self.implementation), + ] + return ' '.join( + '{}={!r}'.format(key, value) for key, value in key_values + if value is not None + ) + + def get_tags(self): + # type: () -> List[Tag] + """ + Return the supported PEP 425 tags to check wheel candidates against. + + The tags are returned in order of preference (most preferred first). + """ + if self._valid_tags is None: + # Pass versions=None if no py_version_info was given since + # versions=None uses special default logic. + py_version_info = self._given_py_version_info + if py_version_info is None: + version = None + else: + version = version_info_to_nodot(py_version_info) + + tags = get_supported( + version=version, + platforms=self.platforms, + abis=self.abis, + impl=self.implementation, + ) + self._valid_tags = tags + + return self._valid_tags diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/wheel.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/wheel.py new file mode 100644 index 0000000..4d4068f --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/models/wheel.py @@ -0,0 +1,78 @@ +"""Represents a wheel file and provides access to the various parts of the +name that have meaning. +""" +import re + +from pip._vendor.packaging.tags import Tag + +from pip._internal.exceptions import InvalidWheelFilename +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List + + +class Wheel(object): + """A wheel file""" + + wheel_file_re = re.compile( + r"""^(?P(?P.+?)-(?P.*?)) + ((-(?P\d[^-]*?))?-(?P.+?)-(?P.+?)-(?P.+?) + \.whl|\.dist-info)$""", + re.VERBOSE + ) + + def __init__(self, filename): + # type: (str) -> None + """ + :raises InvalidWheelFilename: when the filename is invalid for a wheel + """ + wheel_info = self.wheel_file_re.match(filename) + if not wheel_info: + raise InvalidWheelFilename( + "{} is not a valid wheel filename.".format(filename) + ) + self.filename = filename + self.name = wheel_info.group('name').replace('_', '-') + # we'll assume "_" means "-" due to wheel naming scheme + # (https://github.com/pypa/pip/issues/1150) + self.version = wheel_info.group('ver').replace('_', '-') + self.build_tag = wheel_info.group('build') + self.pyversions = wheel_info.group('pyver').split('.') + self.abis = wheel_info.group('abi').split('.') + self.plats = wheel_info.group('plat').split('.') + + # All the tag combinations from this file + self.file_tags = { + Tag(x, y, z) for x in self.pyversions + for y in self.abis for z in self.plats + } + + def get_formatted_file_tags(self): + # type: () -> List[str] + """Return the wheel's tags as a sorted list of strings.""" + return sorted(str(tag) for tag in self.file_tags) + + def support_index_min(self, tags): + # type: (List[Tag]) -> int + """Return the lowest index that one of the wheel's file_tag combinations + achieves in the given list of supported tags. + + For example, if there are 8 supported tags and one of the file tags + is first in the list, then return 0. + + :param tags: the PEP 425 tags to check the wheel against, in order + with most preferred first. + + :raises ValueError: If none of the wheel's file tags match one of + the supported tags. + """ + return min(tags.index(tag) for tag in self.file_tags if tag in tags) + + def supported(self, tags): + # type: (List[Tag]) -> bool + """Return whether the wheel is compatible with one of the given tags. + + :param tags: the PEP 425 tags to check the wheel against. + """ + return not self.file_tags.isdisjoint(tags) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__init__.py new file mode 100644 index 0000000..b51bde9 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__init__.py @@ -0,0 +1,2 @@ +"""Contains purely network-related utilities. +""" diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf1fde0795d693a9144e429b9d1bf08268120580 GIT binary patch literal 276 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/download.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/download.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7d4231c50a18884f02f1c66f6b4ad680f60982b GIT binary patch literal 5303 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9db62a1f661c05e03d2f7391ef1b899690812034 GIT binary patch literal 8092 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/session.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/session.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a81a7eb446749241c7993e6abdb44534d9c6ce80 GIT binary patch literal 9537 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/utils.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/__pycache__/utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7c20a5cacc80c231324cc48b6439816760de174 GIT binary patch literal 1429 zcmZux&u<(x7_~h=cCy)|t0)a9mFNhG!%E3c5kg9<3N>t&CTdww(onJjMw79Vbu;6c z*xrO)?FtEcq!NEZ;l`B%e~hnO;NBA#_&l4fQiNCYjqUG^?eD#}PL`JH2-;x!DtX*Q z=np%%-W(V_fJc1=fg*}Cl;b|mNuOXlCYh7FeYfg6nV0*0A0y_=`;c?9S|0R+e4)Pp zd5`)W_v^GqgXgHf$nXiK3$*?m_ZxKa0JR!_!49ZJ%u468-ji^+JP_WE5D z>@!ssLa`P$Ydxkf3whQlgkY)Wh3HCINXV>wdi41beAeweiuVtDy}jN;SkK+zsW!o$ zW-`%*9N*YZQ&#HDu1E{Y#iXXf_ zah`-0h1R@{yz%% z59C~>z`#~qD4mFu8DFwQ6~cJOBh8fYDFf!2SveHkc6O>^wY6D!^GBY%>mRYHlwL-h*Td9+|p2dd`WX)2dV;7&J12;Cm^ps?jTvrG<2mYg=kFh9 zDKFzRIq-LRl#8<9vX^9K$}*PANG3(@{SM)xK_9D?#+ZOPC_&IFBQ6*)n*%0~3jT7t z$a5C!U5_{~IB3>*ln6!+3r+<1n+TAtf3vr`*tw+V(PGWuXQPXq&dE4P1*la79n8gTL?UTVC97 z{%nUA(}c2K)Z4!%1N;9;L2sHw+VtPZ_PrjA;$RH7^=tldtnob`EnxI|8>YAqM4~Z1 zH7Zn@X9h;nJhdu(h8I?4jawBWb_F`(Py`|4LEq&D>{0EDh?Pr7k|&Z7)t&GZ@FI2Y zl?$tevqd}t)RaS(j7vn5#(qm#f~AM5o#d1q6WF4hr4HNyJT#I_CK(GmjRkm=;#b5s zAc{YK3`Rx90tTlRQjUvJE{Z%5JPtT33lT&|On||bcCtmmORljChAd|sM1enL`80r# zgK{QEMgEchNgxuiEu;8lG-M(ulQMwoNyhUi4f3Xzf(97Bobe8XaSx_&fgocQd)USE zJO2mPKhILE0XQGJE%mIy_yw2>jZuXwgF+ipbZ9SHQiIb1K?& zvvPEG{bVg%*{a+(7^BLnK|`lb<&NDm`~rZpkZjL>#%R&TXnwzHk3ErpiC$ybIqlMx zUXNEQ`wW`=HF|;e;N(U7hj#8YzYov@kO2JlVBUp3lF(vXyR(wbUCEB6&c<%vR2F18 zQqG7)lyRYKAvue(`8!W{cXxVBH(l>T(K{L?DeDcHlu14WL4TFsfP3>U5aj{>le{h( zzNQ5hpeVV{m~y6!9~6SA)ml$DgC`+}waKF+t}9x(7cx67hC{}c8}mdaag?e~)8iyA zDC>LtX6=0h-XY>BrzseBIeRr>LXv}m&iGwzp`Q^clnHV1TOi=?YN^SN~aiOLL}Y{sRhf67>K8 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/auth.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/auth.py new file mode 100644 index 0000000..357811a --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/auth.py @@ -0,0 +1,310 @@ +"""Network Authentication Helpers + +Contains interface (MultiDomainBasicAuth) and associated glue code for +providing credentials in the context of network requests. +""" + +import logging + +from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth +from pip._vendor.requests.utils import get_netrc_auth +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.utils.misc import ( + ask, + ask_input, + ask_password, + remove_auth_from_url, + split_auth_netloc_from_url, +) +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, List, Optional, Tuple + + from pip._vendor.requests.models import Request, Response + + from pip._internal.vcs.versioncontrol import AuthInfo + + Credentials = Tuple[str, str, str] + +logger = logging.getLogger(__name__) + +try: + import keyring # noqa +except ImportError: + keyring = None +except Exception as exc: + logger.warning( + "Keyring is skipped due to an exception: %s", str(exc), + ) + keyring = None + + +def get_keyring_auth(url, username): + # type: (str, str) -> Optional[AuthInfo] + """Return the tuple auth for a given url from keyring.""" + global keyring + if not url or not keyring: + return None + + try: + try: + get_credential = keyring.get_credential + except AttributeError: + pass + else: + logger.debug("Getting credentials from keyring for %s", url) + cred = get_credential(url, username) + if cred is not None: + return cred.username, cred.password + return None + + if username: + logger.debug("Getting password from keyring for %s", url) + password = keyring.get_password(url, username) + if password: + return username, password + + except Exception as exc: + logger.warning( + "Keyring is skipped due to an exception: %s", str(exc), + ) + keyring = None + return None + + +class MultiDomainBasicAuth(AuthBase): + + def __init__(self, prompting=True, index_urls=None): + # type: (bool, Optional[List[str]]) -> None + self.prompting = prompting + self.index_urls = index_urls + self.passwords = {} # type: Dict[str, AuthInfo] + # When the user is prompted to enter credentials and keyring is + # available, we will offer to save them. If the user accepts, + # this value is set to the credentials they entered. After the + # request authenticates, the caller should call + # ``save_credentials`` to save these. + self._credentials_to_save = None # type: Optional[Credentials] + + def _get_index_url(self, url): + # type: (str) -> Optional[str] + """Return the original index URL matching the requested URL. + + Cached or dynamically generated credentials may work against + the original index URL rather than just the netloc. + + The provided url should have had its username and password + removed already. If the original index url had credentials then + they will be included in the return value. + + Returns None if no matching index was found, or if --no-index + was specified by the user. + """ + if not url or not self.index_urls: + return None + + for u in self.index_urls: + prefix = remove_auth_from_url(u).rstrip("/") + "/" + if url.startswith(prefix): + return u + return None + + def _get_new_credentials(self, original_url, allow_netrc=True, + allow_keyring=True): + # type: (str, bool, bool) -> AuthInfo + """Find and return credentials for the specified URL.""" + # Split the credentials and netloc from the url. + url, netloc, url_user_password = split_auth_netloc_from_url( + original_url, + ) + + # Start with the credentials embedded in the url + username, password = url_user_password + if username is not None and password is not None: + logger.debug("Found credentials in url for %s", netloc) + return url_user_password + + # Find a matching index url for this request + index_url = self._get_index_url(url) + if index_url: + # Split the credentials from the url. + index_info = split_auth_netloc_from_url(index_url) + if index_info: + index_url, _, index_url_user_password = index_info + logger.debug("Found index url %s", index_url) + + # If an index URL was found, try its embedded credentials + if index_url and index_url_user_password[0] is not None: + username, password = index_url_user_password + if username is not None and password is not None: + logger.debug("Found credentials in index url for %s", netloc) + return index_url_user_password + + # Get creds from netrc if we still don't have them + if allow_netrc: + netrc_auth = get_netrc_auth(original_url) + if netrc_auth: + logger.debug("Found credentials in netrc for %s", netloc) + return netrc_auth + + # If we don't have a password and keyring is available, use it. + if allow_keyring: + # The index url is more specific than the netloc, so try it first + kr_auth = ( + get_keyring_auth(index_url, username) or + get_keyring_auth(netloc, username) + ) + if kr_auth: + logger.debug("Found credentials in keyring for %s", netloc) + return kr_auth + + return username, password + + def _get_url_and_credentials(self, original_url): + # type: (str) -> Tuple[str, Optional[str], Optional[str]] + """Return the credentials to use for the provided URL. + + If allowed, netrc and keyring may be used to obtain the + correct credentials. + + Returns (url_without_credentials, username, password). Note + that even if the original URL contains credentials, this + function may return a different username and password. + """ + url, netloc, _ = split_auth_netloc_from_url(original_url) + + # Use any stored credentials that we have for this netloc + username, password = self.passwords.get(netloc, (None, None)) + + if username is None and password is None: + # No stored credentials. Acquire new credentials without prompting + # the user. (e.g. from netrc, keyring, or the URL itself) + username, password = self._get_new_credentials(original_url) + + if username is not None or password is not None: + # Convert the username and password if they're None, so that + # this netloc will show up as "cached" in the conditional above. + # Further, HTTPBasicAuth doesn't accept None, so it makes sense to + # cache the value that is going to be used. + username = username or "" + password = password or "" + + # Store any acquired credentials. + self.passwords[netloc] = (username, password) + + assert ( + # Credentials were found + (username is not None and password is not None) or + # Credentials were not found + (username is None and password is None) + ), "Could not load credentials from url: {}".format(original_url) + + return url, username, password + + def __call__(self, req): + # type: (Request) -> Request + # Get credentials for this request + url, username, password = self._get_url_and_credentials(req.url) + + # Set the url of the request to the url without any credentials + req.url = url + + if username is not None and password is not None: + # Send the basic auth with this request + req = HTTPBasicAuth(username, password)(req) + + # Attach a hook to handle 401 responses + req.register_hook("response", self.handle_401) + + return req + + # Factored out to allow for easy patching in tests + def _prompt_for_password(self, netloc): + # type: (str) -> Tuple[Optional[str], Optional[str], bool] + username = ask_input("User for {}: ".format(netloc)) + if not username: + return None, None, False + auth = get_keyring_auth(netloc, username) + if auth and auth[0] is not None and auth[1] is not None: + return auth[0], auth[1], False + password = ask_password("Password: ") + return username, password, True + + # Factored out to allow for easy patching in tests + def _should_save_password_to_keyring(self): + # type: () -> bool + if not keyring: + return False + return ask("Save credentials to keyring [y/N]: ", ["y", "n"]) == "y" + + def handle_401(self, resp, **kwargs): + # type: (Response, **Any) -> Response + # We only care about 401 responses, anything else we want to just + # pass through the actual response + if resp.status_code != 401: + return resp + + # We are not able to prompt the user so simply return the response + if not self.prompting: + return resp + + parsed = urllib_parse.urlparse(resp.url) + + # Prompt the user for a new username and password + username, password, save = self._prompt_for_password(parsed.netloc) + + # Store the new username and password to use for future requests + self._credentials_to_save = None + if username is not None and password is not None: + self.passwords[parsed.netloc] = (username, password) + + # Prompt to save the password to keyring + if save and self._should_save_password_to_keyring(): + self._credentials_to_save = (parsed.netloc, username, password) + + # Consume content and release the original connection to allow our new + # request to reuse the same one. + resp.content + resp.raw.release_conn() + + # Add our new username and password to the request + req = HTTPBasicAuth(username or "", password or "")(resp.request) + req.register_hook("response", self.warn_on_401) + + # On successful request, save the credentials that were used to + # keyring. (Note that if the user responded "no" above, this member + # is not set and nothing will be saved.) + if self._credentials_to_save: + req.register_hook("response", self.save_credentials) + + # Send our new request + new_resp = resp.connection.send(req, **kwargs) + new_resp.history.append(resp) + + return new_resp + + def warn_on_401(self, resp, **kwargs): + # type: (Response, **Any) -> None + """Response callback to warn about incorrect credentials.""" + if resp.status_code == 401: + logger.warning( + '401 Error, Credentials not correct for %s', resp.request.url, + ) + + def save_credentials(self, resp, **kwargs): + # type: (Response, **Any) -> None + """Response callback to save credentials on success.""" + assert keyring is not None, "should never reach here without keyring" + if not keyring: + return + + creds = self._credentials_to_save + self._credentials_to_save = None + if creds and resp.status_code < 400: + try: + logger.info('Saving credentials to keyring') + keyring.set_password(*creds) + except Exception: + logger.exception('Failed to save credentials') diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/cache.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/cache.py new file mode 100644 index 0000000..d2a1b73 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/cache.py @@ -0,0 +1,79 @@ +"""HTTP cache implementation. +""" + +import os +from contextlib import contextmanager + +from pip._vendor.cachecontrol.cache import BaseCache +from pip._vendor.cachecontrol.caches import FileCache +from pip._vendor.requests.models import Response + +from pip._internal.utils.filesystem import adjacent_tmp_file, replace +from pip._internal.utils.misc import ensure_dir +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Iterator, Optional + + +def is_from_cache(response): + # type: (Response) -> bool + return getattr(response, "from_cache", False) + + +@contextmanager +def suppressed_cache_errors(): + # type: () -> Iterator[None] + """If we can't access the cache then we can just skip caching and process + requests as if caching wasn't enabled. + """ + try: + yield + except (OSError, IOError): + pass + + +class SafeFileCache(BaseCache): + """ + A file based cache which is safe to use even when the target directory may + not be accessible or writable. + """ + + def __init__(self, directory): + # type: (str) -> None + assert directory is not None, "Cache directory must not be None." + super(SafeFileCache, self).__init__() + self.directory = directory + + def _get_cache_path(self, name): + # type: (str) -> str + # From cachecontrol.caches.file_cache.FileCache._fn, brought into our + # class for backwards-compatibility and to avoid using a non-public + # method. + hashed = FileCache.encode(name) + parts = list(hashed[:5]) + [hashed] + return os.path.join(self.directory, *parts) + + def get(self, key): + # type: (str) -> Optional[bytes] + path = self._get_cache_path(key) + with suppressed_cache_errors(): + with open(path, 'rb') as f: + return f.read() + + def set(self, key, value): + # type: (str, bytes) -> None + path = self._get_cache_path(key) + with suppressed_cache_errors(): + ensure_dir(os.path.dirname(path)) + + with adjacent_tmp_file(path) as f: + f.write(value) + + replace(f.name, path) + + def delete(self, key): + # type: (str) -> None + path = self._get_cache_path(key) + with suppressed_cache_errors(): + os.remove(path) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/download.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/download.py new file mode 100644 index 0000000..76896e8 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/download.py @@ -0,0 +1,202 @@ +"""Download files with progress indicators. +""" +import cgi +import logging +import mimetypes +import os + +from pip._vendor.requests.models import CONTENT_CHUNK_SIZE + +from pip._internal.cli.progress_bars import DownloadProgressProvider +from pip._internal.exceptions import NetworkConnectionError +from pip._internal.models.index import PyPI +from pip._internal.network.cache import is_from_cache +from pip._internal.network.utils import HEADERS, raise_for_status, response_chunks +from pip._internal.utils.misc import format_size, redact_auth_from_url, splitext +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Iterable, Optional, Tuple + + from pip._vendor.requests.models import Response + + from pip._internal.models.link import Link + from pip._internal.network.session import PipSession + +logger = logging.getLogger(__name__) + + +def _get_http_response_size(resp): + # type: (Response) -> Optional[int] + try: + return int(resp.headers['content-length']) + except (ValueError, KeyError, TypeError): + return None + + +def _prepare_download( + resp, # type: Response + link, # type: Link + progress_bar # type: str +): + # type: (...) -> Iterable[bytes] + total_length = _get_http_response_size(resp) + + if link.netloc == PyPI.file_storage_domain: + url = link.show_url + else: + url = link.url_without_fragment + + logged_url = redact_auth_from_url(url) + + if total_length: + logged_url = '{} ({})'.format(logged_url, format_size(total_length)) + + if is_from_cache(resp): + logger.info("Using cached %s", logged_url) + else: + logger.info("Downloading %s", logged_url) + + if logger.getEffectiveLevel() > logging.INFO: + show_progress = False + elif is_from_cache(resp): + show_progress = False + elif not total_length: + show_progress = True + elif total_length > (40 * 1000): + show_progress = True + else: + show_progress = False + + chunks = response_chunks(resp, CONTENT_CHUNK_SIZE) + + if not show_progress: + return chunks + + return DownloadProgressProvider( + progress_bar, max=total_length + )(chunks) + + +def sanitize_content_filename(filename): + # type: (str) -> str + """ + Sanitize the "filename" value from a Content-Disposition header. + """ + return os.path.basename(filename) + + +def parse_content_disposition(content_disposition, default_filename): + # type: (str, str) -> str + """ + Parse the "filename" value from a Content-Disposition header, and + return the default filename if the result is empty. + """ + _type, params = cgi.parse_header(content_disposition) + filename = params.get('filename') + if filename: + # We need to sanitize the filename to prevent directory traversal + # in case the filename contains ".." path parts. + filename = sanitize_content_filename(filename) + return filename or default_filename + + +def _get_http_response_filename(resp, link): + # type: (Response, Link) -> str + """Get an ideal filename from the given HTTP response, falling back to + the link filename if not provided. + """ + filename = link.filename # fallback + # Have a look at the Content-Disposition header for a better guess + content_disposition = resp.headers.get('content-disposition') + if content_disposition: + filename = parse_content_disposition(content_disposition, filename) + ext = splitext(filename)[1] # type: Optional[str] + if not ext: + ext = mimetypes.guess_extension( + resp.headers.get('content-type', '') + ) + if ext: + filename += ext + if not ext and link.url != resp.url: + ext = os.path.splitext(resp.url)[1] + if ext: + filename += ext + return filename + + +def _http_get_download(session, link): + # type: (PipSession, Link) -> Response + target_url = link.url.split('#', 1)[0] + resp = session.get(target_url, headers=HEADERS, stream=True) + raise_for_status(resp) + return resp + + +class Downloader(object): + def __init__( + self, + session, # type: PipSession + progress_bar, # type: str + ): + # type: (...) -> None + self._session = session + self._progress_bar = progress_bar + + def __call__(self, link, location): + # type: (Link, str) -> Tuple[str, str] + """Download the file given by link into location.""" + try: + resp = _http_get_download(self._session, link) + except NetworkConnectionError as e: + assert e.response is not None + logger.critical( + "HTTP error %s while getting %s", e.response.status_code, link + ) + raise + + filename = _get_http_response_filename(resp, link) + filepath = os.path.join(location, filename) + + chunks = _prepare_download(resp, link, self._progress_bar) + with open(filepath, 'wb') as content_file: + for chunk in chunks: + content_file.write(chunk) + content_type = resp.headers.get('Content-Type', '') + return filepath, content_type + + +class BatchDownloader(object): + + def __init__( + self, + session, # type: PipSession + progress_bar, # type: str + ): + # type: (...) -> None + self._session = session + self._progress_bar = progress_bar + + def __call__(self, links, location): + # type: (Iterable[Link], str) -> Iterable[Tuple[str, Tuple[str, str]]] + """Download the files given by links into location.""" + for link in links: + try: + resp = _http_get_download(self._session, link) + except NetworkConnectionError as e: + assert e.response is not None + logger.critical( + "HTTP error %s while getting %s", + e.response.status_code, link, + ) + raise + + filename = _get_http_response_filename(resp, link) + filepath = os.path.join(location, filename) + + chunks = _prepare_download(resp, link, self._progress_bar) + with open(filepath, 'wb') as content_file: + for chunk in chunks: + content_file.write(chunk) + content_type = resp.headers.get('Content-Type', '') + yield link.url, (filepath, content_type) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/lazy_wheel.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/lazy_wheel.py new file mode 100644 index 0000000..608475a --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/lazy_wheel.py @@ -0,0 +1,231 @@ +"""Lazy ZIP over HTTP""" + +__all__ = ['HTTPRangeRequestUnsupported', 'dist_from_wheel_url'] + +from bisect import bisect_left, bisect_right +from contextlib import contextmanager +from tempfile import NamedTemporaryFile +from zipfile import BadZipfile, ZipFile + +from pip._vendor.requests.models import CONTENT_CHUNK_SIZE +from pip._vendor.six.moves import range + +from pip._internal.network.utils import HEADERS, raise_for_status, response_chunks +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.wheel import pkg_resources_distribution_for_wheel + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, Iterator, List, Optional, Tuple + + from pip._vendor.pkg_resources import Distribution + from pip._vendor.requests.models import Response + + from pip._internal.network.session import PipSession + + +class HTTPRangeRequestUnsupported(Exception): + pass + + +def dist_from_wheel_url(name, url, session): + # type: (str, str, PipSession) -> Distribution + """Return a pkg_resources.Distribution from the given wheel URL. + + This uses HTTP range requests to only fetch the potion of the wheel + containing metadata, just enough for the object to be constructed. + If such requests are not supported, HTTPRangeRequestUnsupported + is raised. + """ + with LazyZipOverHTTP(url, session) as wheel: + # For read-only ZIP files, ZipFile only needs methods read, + # seek, seekable and tell, not the whole IO protocol. + zip_file = ZipFile(wheel) # type: ignore + # After context manager exit, wheel.name + # is an invalid file by intention. + return pkg_resources_distribution_for_wheel(zip_file, name, wheel.name) + + +class LazyZipOverHTTP(object): + """File-like object mapped to a ZIP file over HTTP. + + This uses HTTP range requests to lazily fetch the file's content, + which is supposed to be fed to ZipFile. If such requests are not + supported by the server, raise HTTPRangeRequestUnsupported + during initialization. + """ + + def __init__(self, url, session, chunk_size=CONTENT_CHUNK_SIZE): + # type: (str, PipSession, int) -> None + head = session.head(url, headers=HEADERS) + raise_for_status(head) + assert head.status_code == 200 + self._session, self._url, self._chunk_size = session, url, chunk_size + self._length = int(head.headers['Content-Length']) + self._file = NamedTemporaryFile() + self.truncate(self._length) + self._left = [] # type: List[int] + self._right = [] # type: List[int] + if 'bytes' not in head.headers.get('Accept-Ranges', 'none'): + raise HTTPRangeRequestUnsupported('range request is not supported') + self._check_zip() + + @property + def mode(self): + # type: () -> str + """Opening mode, which is always rb.""" + return 'rb' + + @property + def name(self): + # type: () -> str + """Path to the underlying file.""" + return self._file.name + + def seekable(self): + # type: () -> bool + """Return whether random access is supported, which is True.""" + return True + + def close(self): + # type: () -> None + """Close the file.""" + self._file.close() + + @property + def closed(self): + # type: () -> bool + """Whether the file is closed.""" + return self._file.closed + + def read(self, size=-1): + # type: (int) -> bytes + """Read up to size bytes from the object and return them. + + As a convenience, if size is unspecified or -1, + all bytes until EOF are returned. Fewer than + size bytes may be returned if EOF is reached. + """ + download_size = max(size, self._chunk_size) + start, length = self.tell(), self._length + stop = length if size < 0 else min(start+download_size, length) + start = max(0, stop-download_size) + self._download(start, stop-1) + return self._file.read(size) + + def readable(self): + # type: () -> bool + """Return whether the file is readable, which is True.""" + return True + + def seek(self, offset, whence=0): + # type: (int, int) -> int + """Change stream position and return the new absolute position. + + Seek to offset relative position indicated by whence: + * 0: Start of stream (the default). pos should be >= 0; + * 1: Current position - pos may be negative; + * 2: End of stream - pos usually negative. + """ + return self._file.seek(offset, whence) + + def tell(self): + # type: () -> int + """Return the current possition.""" + return self._file.tell() + + def truncate(self, size=None): + # type: (Optional[int]) -> int + """Resize the stream to the given size in bytes. + + If size is unspecified resize to the current position. + The current stream position isn't changed. + + Return the new file size. + """ + return self._file.truncate(size) + + def writable(self): + # type: () -> bool + """Return False.""" + return False + + def __enter__(self): + # type: () -> LazyZipOverHTTP + self._file.__enter__() + return self + + def __exit__(self, *exc): + # type: (*Any) -> Optional[bool] + return self._file.__exit__(*exc) + + @contextmanager + def _stay(self): + # type: ()-> Iterator[None] + """Return a context manager keeping the position. + + At the end of the block, seek back to original position. + """ + pos = self.tell() + try: + yield + finally: + self.seek(pos) + + def _check_zip(self): + # type: () -> None + """Check and download until the file is a valid ZIP.""" + end = self._length - 1 + for start in reversed(range(0, end, self._chunk_size)): + self._download(start, end) + with self._stay(): + try: + # For read-only ZIP files, ZipFile only needs + # methods read, seek, seekable and tell. + ZipFile(self) # type: ignore + except BadZipfile: + pass + else: + break + + def _stream_response(self, start, end, base_headers=HEADERS): + # type: (int, int, Dict[str, str]) -> Response + """Return HTTP response to a range request from start to end.""" + headers = base_headers.copy() + headers['Range'] = 'bytes={}-{}'.format(start, end) + # TODO: Get range requests to be correctly cached + headers['Cache-Control'] = 'no-cache' + return self._session.get(self._url, headers=headers, stream=True) + + def _merge(self, start, end, left, right): + # type: (int, int, int, int) -> Iterator[Tuple[int, int]] + """Return an iterator of intervals to be fetched. + + Args: + start (int): Start of needed interval + end (int): End of needed interval + left (int): Index of first overlapping downloaded data + right (int): Index after last overlapping downloaded data + """ + lslice, rslice = self._left[left:right], self._right[left:right] + i = start = min([start]+lslice[:1]) + end = max([end]+rslice[-1:]) + for j, k in zip(lslice, rslice): + if j > i: + yield i, j-1 + i = k + 1 + if i <= end: + yield i, end + self._left[left:right], self._right[left:right] = [start], [end] + + def _download(self, start, end): + # type: (int, int) -> None + """Download bytes from start to end inclusively.""" + with self._stay(): + left = bisect_left(self._right, start) + right = bisect_right(self._left, end) + for start, end in self._merge(start, end, left, right): + response = self._stream_response(start, end) + response.raise_for_status() + self.seek(start) + for chunk in response_chunks(response, self._chunk_size): + self._file.write(chunk) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/session.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/session.py new file mode 100644 index 0000000..454945d --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/session.py @@ -0,0 +1,428 @@ +"""PipSession and supporting code, containing all pip-specific +network request configuration and behavior. +""" + +# The following comment should be removed at some point in the future. +# mypy: disallow-untyped-defs=False + +import email.utils +import json +import logging +import mimetypes +import os +import platform +import sys +import warnings + +from pip._vendor import requests, six, urllib3 +from pip._vendor.cachecontrol import CacheControlAdapter +from pip._vendor.requests.adapters import BaseAdapter, HTTPAdapter +from pip._vendor.requests.models import Response +from pip._vendor.requests.structures import CaseInsensitiveDict +from pip._vendor.six.moves.urllib import parse as urllib_parse +from pip._vendor.urllib3.exceptions import InsecureRequestWarning + +from pip import __version__ +from pip._internal.network.auth import MultiDomainBasicAuth +from pip._internal.network.cache import SafeFileCache + +# Import ssl from compat so the initial import occurs in only one place. +from pip._internal.utils.compat import has_tls, ipaddress +from pip._internal.utils.glibc import libc_ver +from pip._internal.utils.misc import ( + build_url_from_netloc, + get_installed_version, + parse_netloc, +) +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.urls import url_to_path + +if MYPY_CHECK_RUNNING: + from typing import Iterator, List, Optional, Tuple, Union + + from pip._internal.models.link import Link + + SecureOrigin = Tuple[str, str, Optional[Union[int, str]]] + + +logger = logging.getLogger(__name__) + + +# Ignore warning raised when using --trusted-host. +warnings.filterwarnings("ignore", category=InsecureRequestWarning) + + +SECURE_ORIGINS = [ + # protocol, hostname, port + # Taken from Chrome's list of secure origins (See: http://bit.ly/1qrySKC) + ("https", "*", "*"), + ("*", "localhost", "*"), + ("*", "127.0.0.0/8", "*"), + ("*", "::1/128", "*"), + ("file", "*", None), + # ssh is always secure. + ("ssh", "*", "*"), +] # type: List[SecureOrigin] + + +# These are environment variables present when running under various +# CI systems. For each variable, some CI systems that use the variable +# are indicated. The collection was chosen so that for each of a number +# of popular systems, at least one of the environment variables is used. +# This list is used to provide some indication of and lower bound for +# CI traffic to PyPI. Thus, it is okay if the list is not comprehensive. +# For more background, see: https://github.com/pypa/pip/issues/5499 +CI_ENVIRONMENT_VARIABLES = ( + # Azure Pipelines + 'BUILD_BUILDID', + # Jenkins + 'BUILD_ID', + # AppVeyor, CircleCI, Codeship, Gitlab CI, Shippable, Travis CI + 'CI', + # Explicit environment variable. + 'PIP_IS_CI', +) + + +def looks_like_ci(): + # type: () -> bool + """ + Return whether it looks like pip is running under CI. + """ + # We don't use the method of checking for a tty (e.g. using isatty()) + # because some CI systems mimic a tty (e.g. Travis CI). Thus that + # method doesn't provide definitive information in either direction. + return any(name in os.environ for name in CI_ENVIRONMENT_VARIABLES) + + +def user_agent(): + """ + Return a string representing the user agent. + """ + data = { + "installer": {"name": "pip", "version": __version__}, + "python": platform.python_version(), + "implementation": { + "name": platform.python_implementation(), + }, + } + + if data["implementation"]["name"] == 'CPython': + data["implementation"]["version"] = platform.python_version() + elif data["implementation"]["name"] == 'PyPy': + if sys.pypy_version_info.releaselevel == 'final': + pypy_version_info = sys.pypy_version_info[:3] + else: + pypy_version_info = sys.pypy_version_info + data["implementation"]["version"] = ".".join( + [str(x) for x in pypy_version_info] + ) + elif data["implementation"]["name"] == 'Jython': + # Complete Guess + data["implementation"]["version"] = platform.python_version() + elif data["implementation"]["name"] == 'IronPython': + # Complete Guess + data["implementation"]["version"] = platform.python_version() + + if sys.platform.startswith("linux"): + from pip._vendor import distro + distro_infos = dict(filter( + lambda x: x[1], + zip(["name", "version", "id"], distro.linux_distribution()), + )) + libc = dict(filter( + lambda x: x[1], + zip(["lib", "version"], libc_ver()), + )) + if libc: + distro_infos["libc"] = libc + if distro_infos: + data["distro"] = distro_infos + + if sys.platform.startswith("darwin") and platform.mac_ver()[0]: + data["distro"] = {"name": "macOS", "version": platform.mac_ver()[0]} + + if platform.system(): + data.setdefault("system", {})["name"] = platform.system() + + if platform.release(): + data.setdefault("system", {})["release"] = platform.release() + + if platform.machine(): + data["cpu"] = platform.machine() + + if has_tls(): + import _ssl as ssl + data["openssl_version"] = ssl.OPENSSL_VERSION + + setuptools_version = get_installed_version("setuptools") + if setuptools_version is not None: + data["setuptools_version"] = setuptools_version + + # Use None rather than False so as not to give the impression that + # pip knows it is not being run under CI. Rather, it is a null or + # inconclusive result. Also, we include some value rather than no + # value to make it easier to know that the check has been run. + data["ci"] = True if looks_like_ci() else None + + user_data = os.environ.get("PIP_USER_AGENT_USER_DATA") + if user_data is not None: + data["user_data"] = user_data + + return "{data[installer][name]}/{data[installer][version]} {json}".format( + data=data, + json=json.dumps(data, separators=(",", ":"), sort_keys=True), + ) + + +class LocalFSAdapter(BaseAdapter): + + def send(self, request, stream=None, timeout=None, verify=None, cert=None, + proxies=None): + pathname = url_to_path(request.url) + + resp = Response() + resp.status_code = 200 + resp.url = request.url + + try: + stats = os.stat(pathname) + except OSError as exc: + resp.status_code = 404 + resp.raw = exc + else: + modified = email.utils.formatdate(stats.st_mtime, usegmt=True) + content_type = mimetypes.guess_type(pathname)[0] or "text/plain" + resp.headers = CaseInsensitiveDict({ + "Content-Type": content_type, + "Content-Length": stats.st_size, + "Last-Modified": modified, + }) + + resp.raw = open(pathname, "rb") + resp.close = resp.raw.close + + return resp + + def close(self): + pass + + +class InsecureHTTPAdapter(HTTPAdapter): + + def cert_verify(self, conn, url, verify, cert): + super(InsecureHTTPAdapter, self).cert_verify( + conn=conn, url=url, verify=False, cert=cert + ) + + +class InsecureCacheControlAdapter(CacheControlAdapter): + + def cert_verify(self, conn, url, verify, cert): + super(InsecureCacheControlAdapter, self).cert_verify( + conn=conn, url=url, verify=False, cert=cert + ) + + +class PipSession(requests.Session): + + timeout = None # type: Optional[int] + + def __init__(self, *args, **kwargs): + """ + :param trusted_hosts: Domains not to emit warnings for when not using + HTTPS. + """ + retries = kwargs.pop("retries", 0) + cache = kwargs.pop("cache", None) + trusted_hosts = kwargs.pop("trusted_hosts", []) # type: List[str] + index_urls = kwargs.pop("index_urls", None) + + super(PipSession, self).__init__(*args, **kwargs) + + # Namespace the attribute with "pip_" just in case to prevent + # possible conflicts with the base class. + self.pip_trusted_origins = [] # type: List[Tuple[str, Optional[int]]] + + # Attach our User Agent to the request + self.headers["User-Agent"] = user_agent() + + # Attach our Authentication handler to the session + self.auth = MultiDomainBasicAuth(index_urls=index_urls) + + # Create our urllib3.Retry instance which will allow us to customize + # how we handle retries. + retries = urllib3.Retry( + # Set the total number of retries that a particular request can + # have. + total=retries, + + # A 503 error from PyPI typically means that the Fastly -> Origin + # connection got interrupted in some way. A 503 error in general + # is typically considered a transient error so we'll go ahead and + # retry it. + # A 500 may indicate transient error in Amazon S3 + # A 520 or 527 - may indicate transient error in CloudFlare + status_forcelist=[500, 503, 520, 527], + + # Add a small amount of back off between failed requests in + # order to prevent hammering the service. + backoff_factor=0.25, + ) + + # Our Insecure HTTPAdapter disables HTTPS validation. It does not + # support caching so we'll use it for all http:// URLs. + # If caching is disabled, we will also use it for + # https:// hosts that we've marked as ignoring + # TLS errors for (trusted-hosts). + insecure_adapter = InsecureHTTPAdapter(max_retries=retries) + + # We want to _only_ cache responses on securely fetched origins or when + # the host is specified as trusted. We do this because + # we can't validate the response of an insecurely/untrusted fetched + # origin, and we don't want someone to be able to poison the cache and + # require manual eviction from the cache to fix it. + if cache: + secure_adapter = CacheControlAdapter( + cache=SafeFileCache(cache), + max_retries=retries, + ) + self._trusted_host_adapter = InsecureCacheControlAdapter( + cache=SafeFileCache(cache), + max_retries=retries, + ) + else: + secure_adapter = HTTPAdapter(max_retries=retries) + self._trusted_host_adapter = insecure_adapter + + self.mount("https://", secure_adapter) + self.mount("http://", insecure_adapter) + + # Enable file:// urls + self.mount("file://", LocalFSAdapter()) + + for host in trusted_hosts: + self.add_trusted_host(host, suppress_logging=True) + + def update_index_urls(self, new_index_urls): + # type: (List[str]) -> None + """ + :param new_index_urls: New index urls to update the authentication + handler with. + """ + self.auth.index_urls = new_index_urls + + def add_trusted_host(self, host, source=None, suppress_logging=False): + # type: (str, Optional[str], bool) -> None + """ + :param host: It is okay to provide a host that has previously been + added. + :param source: An optional source string, for logging where the host + string came from. + """ + if not suppress_logging: + msg = 'adding trusted host: {!r}'.format(host) + if source is not None: + msg += ' (from {})'.format(source) + logger.info(msg) + + host_port = parse_netloc(host) + if host_port not in self.pip_trusted_origins: + self.pip_trusted_origins.append(host_port) + + self.mount( + build_url_from_netloc(host) + '/', + self._trusted_host_adapter + ) + if not host_port[1]: + # Mount wildcard ports for the same host. + self.mount( + build_url_from_netloc(host) + ':', + self._trusted_host_adapter + ) + + def iter_secure_origins(self): + # type: () -> Iterator[SecureOrigin] + for secure_origin in SECURE_ORIGINS: + yield secure_origin + for host, port in self.pip_trusted_origins: + yield ('*', host, '*' if port is None else port) + + def is_secure_origin(self, location): + # type: (Link) -> bool + # Determine if this url used a secure transport mechanism + parsed = urllib_parse.urlparse(str(location)) + origin_protocol, origin_host, origin_port = ( + parsed.scheme, parsed.hostname, parsed.port, + ) + + # The protocol to use to see if the protocol matches. + # Don't count the repository type as part of the protocol: in + # cases such as "git+ssh", only use "ssh". (I.e., Only verify against + # the last scheme.) + origin_protocol = origin_protocol.rsplit('+', 1)[-1] + + # Determine if our origin is a secure origin by looking through our + # hardcoded list of secure origins, as well as any additional ones + # configured on this PackageFinder instance. + for secure_origin in self.iter_secure_origins(): + secure_protocol, secure_host, secure_port = secure_origin + if origin_protocol != secure_protocol and secure_protocol != "*": + continue + + try: + addr = ipaddress.ip_address( + None + if origin_host is None + else six.ensure_text(origin_host) + ) + network = ipaddress.ip_network( + six.ensure_text(secure_host) + ) + except ValueError: + # We don't have both a valid address or a valid network, so + # we'll check this origin against hostnames. + if ( + origin_host and + origin_host.lower() != secure_host.lower() and + secure_host != "*" + ): + continue + else: + # We have a valid address and network, so see if the address + # is contained within the network. + if addr not in network: + continue + + # Check to see if the port matches. + if ( + origin_port != secure_port and + secure_port != "*" and + secure_port is not None + ): + continue + + # If we've gotten here, then this origin matches the current + # secure origin and we should return True + return True + + # If we've gotten to this point, then the origin isn't secure and we + # will not accept it as a valid location to search. We will however + # log a warning that we are ignoring it. + logger.warning( + "The repository located at %s is not a trusted or secure host and " + "is being ignored. If this repository is available via HTTPS we " + "recommend you use HTTPS instead, otherwise you may silence " + "this warning and allow it anyway with '--trusted-host %s'.", + origin_host, + origin_host, + ) + + return False + + def request(self, method, url, *args, **kwargs): + # Allow setting a default timeout on a session + kwargs.setdefault("timeout", self.timeout) + + # Dispatch the actual request + return super(PipSession, self).request(method, url, *args, **kwargs) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/utils.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/utils.py new file mode 100644 index 0000000..907b3fe --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/utils.py @@ -0,0 +1,97 @@ +from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response + +from pip._internal.exceptions import NetworkConnectionError +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Dict, Iterator + +# The following comments and HTTP headers were originally added by +# Donald Stufft in git commit 22c562429a61bb77172039e480873fb239dd8c03. +# +# We use Accept-Encoding: identity here because requests defaults to +# accepting compressed responses. This breaks in a variety of ways +# depending on how the server is configured. +# - Some servers will notice that the file isn't a compressible file +# and will leave the file alone and with an empty Content-Encoding +# - Some servers will notice that the file is already compressed and +# will leave the file alone, adding a Content-Encoding: gzip header +# - Some servers won't notice anything at all and will take a file +# that's already been compressed and compress it again, and set +# the Content-Encoding: gzip header +# By setting this to request only the identity encoding we're hoping +# to eliminate the third case. Hopefully there does not exist a server +# which when given a file will notice it is already compressed and that +# you're not asking for a compressed file and will then decompress it +# before sending because if that's the case I don't think it'll ever be +# possible to make this work. +HEADERS = {'Accept-Encoding': 'identity'} # type: Dict[str, str] + + +def raise_for_status(resp): + # type: (Response) -> None + http_error_msg = u'' + if isinstance(resp.reason, bytes): + # We attempt to decode utf-8 first because some servers + # choose to localize their reason strings. If the string + # isn't utf-8, we fall back to iso-8859-1 for all other + # encodings. + try: + reason = resp.reason.decode('utf-8') + except UnicodeDecodeError: + reason = resp.reason.decode('iso-8859-1') + else: + reason = resp.reason + + if 400 <= resp.status_code < 500: + http_error_msg = u'%s Client Error: %s for url: %s' % ( + resp.status_code, reason, resp.url) + + elif 500 <= resp.status_code < 600: + http_error_msg = u'%s Server Error: %s for url: %s' % ( + resp.status_code, reason, resp.url) + + if http_error_msg: + raise NetworkConnectionError(http_error_msg, response=resp) + + +def response_chunks(response, chunk_size=CONTENT_CHUNK_SIZE): + # type: (Response, int) -> Iterator[bytes] + """Given a requests Response, provide the data chunks. + """ + try: + # Special case for urllib3. + for chunk in response.raw.stream( + chunk_size, + # We use decode_content=False here because we don't + # want urllib3 to mess with the raw bytes we get + # from the server. If we decompress inside of + # urllib3 then we cannot verify the checksum + # because the checksum will be of the compressed + # file. This breakage will only occur if the + # server adds a Content-Encoding header, which + # depends on how the server was configured: + # - Some servers will notice that the file isn't a + # compressible file and will leave the file alone + # and with an empty Content-Encoding + # - Some servers will notice that the file is + # already compressed and will leave the file + # alone and will add a Content-Encoding: gzip + # header + # - Some servers won't notice anything at all and + # will take a file that's already been compressed + # and compress it again and set the + # Content-Encoding: gzip header + # + # By setting this not to decode automatically we + # hope to eliminate problems with the second case. + decode_content=False, + ): + yield chunk + except AttributeError: + # Standard file-like object. + while True: + chunk = response.raw.read(chunk_size) + if not chunk: + break + yield chunk diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/xmlrpc.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/xmlrpc.py new file mode 100644 index 0000000..504018f --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/network/xmlrpc.py @@ -0,0 +1,53 @@ +"""xmlrpclib.Transport implementation +""" + +import logging + +# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is +# why we ignore the type on this import +from pip._vendor.six.moves import xmlrpc_client # type: ignore +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.exceptions import NetworkConnectionError +from pip._internal.network.utils import raise_for_status +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Dict + + from pip._internal.network.session import PipSession + + +logger = logging.getLogger(__name__) + + +class PipXmlrpcTransport(xmlrpc_client.Transport): + """Provide a `xmlrpclib.Transport` implementation via a `PipSession` + object. + """ + + def __init__(self, index_url, session, use_datetime=False): + # type: (str, PipSession, bool) -> None + xmlrpc_client.Transport.__init__(self, use_datetime) + index_parts = urllib_parse.urlparse(index_url) + self._scheme = index_parts.scheme + self._session = session + + def request(self, host, handler, request_body, verbose=False): + # type: (str, str, Dict[str, str], bool) -> None + parts = (self._scheme, host, handler, None, None, None) + url = urllib_parse.urlunparse(parts) + try: + headers = {'Content-Type': 'text/xml'} + response = self._session.post(url, data=request_body, + headers=headers, stream=True) + raise_for_status(response) + self.verbose = verbose + return self.parse_response(response.raw) + except NetworkConnectionError as exc: + assert exc.response + logger.critical( + "HTTP error %s while getting %s", + exc.response.status_code, url, + ) + raise diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a3e36c0be6484110942b21cdd01dc9fcf574daf GIT binary patch literal 224 zcmYk0F%H5o3`J9k0U`Au4AcV?5<;ASg#$#Pwc0@HL~$tUz{p{^5-Uf5i3w){OaEE^ z`nGJ!a;BuZ>)Yi1%=oWDhOLMvf=2Dtyx84U%=QnT8+5)$KF7IRPr$K;h`}?M z3$g?jjY$IABe9i0i-b`us0O3~oIOAoQ|D<}t$?j$gQ-uZMTTGlXiEtr83#V(JvqUk W#kEQ6DvXcmy7$f5;U>TL5~(lY0YH=h literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/check.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/check.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..159e49cce4f06ac14a33d0863ee61b1a8775c0b7 GIT binary patch literal 3646 zcmZ`+OLN><71ov1YPGuU*d05u^BQF)A?YEwQxIMu6&}tEGfc*lN(P3gpoHAI-IlFK z`(Cw!U1}ENR52`OR#dTJ;Z(87A7II^V5Kc9c2vQN1@N6K*=|!H*S&r3IY&qL@tyA+ z2Xk|dhG%Q~kKh+en)Vl(%swV2-$Rpkn5KoAr-dxkW9BjZ8nK=jp20|F#%9v+8fx5# zt)%HS)!2&dq~*2LxEVW1+iR<_9e0vBZ;ol49nJG|ub8*M=fvOOsTD6KU9X#*_s%Cv z-cqvcEhiVe3&}8@jZgd&;^>cOp_1aTAwd6cDYHgrQi=4r^&LBu7^$H8DH z7;)+Rl@5HP$4Vy+5+3H0am+DW90X~WMgurG;6AA!Tz<-TCz0R@PxB{%ko+AXG66*| z33j+2Mlu)C=7hfK4>RFMsmy~o_QmOIFupwE`LT+JXWo)fcRzgotXr>39fa6rp zwIRlZ_6PO_d!+q*b86(QFt+tWHZ>1casy+tFpe6pv_rjMh511HMBBY>YPpp+hx-0! zOq&A02iJ1@s1=%pSu|b|xEoXb6YaScTGPg_8oRfv-@DpfybCY-kS@D<@U8VM#ZGeR z25yWqQ8zww8`6!^JcF{{KF(>)aq+zSTI=bh6KA++KTG5N(v&;V_~53xS)c@`laAb( z3zRNy*1ak3qkX*5a|E4{Fwm8qvBPie}3BE$`an^aU5lNzMXBQ zGE4hX4ElnPGuaPba0!F2AQsR?z%E^Qf5cNRAnLE}@pP{rN1Ofee!i8ZUt9ZjUq-M! z4w3#i8utO%oC|=gpN;7~xRCw979Z@ajrYsz1Hs|TpIN#;6j^c#^Ea_nxq?n>*v!#Q zX0k4Gn9f#MSD$BBn79tzKqrg(A>cL9*3smj(E(~Yno(!~*q^3mt{nn2s<#Rz-X>Tb z;&-=GXob0|Z4(gVX*1W0=C%PK+J#+cdra&Bur0{UP@gcdNh1O#WG!*8XdGFv11MiH zrtRK?FB`s^QwMhTcB^oReLvUby~0wKkPnU8wjutQJ4GXJhvw&cp%cstOLQQ!YMDVY ztWYlu1>VNN@7C!U-Dn7W)(7a~?%hbb1DrCh9dzR;xV}GhAu7olitcv9p$OHlHSQ6Pt8(pD&h9G*Ty=EKg6njh^?`u}JUTlFlh=8l(bzxoF58@!%410qBm(Foau$+v%`eM$&uY=h0FRu1{L1y*X- zsnY_d=tp*8Db8^UN`d;p57x6}JjoH|1c^GW&sI7$0%mUi^jxZd-{`f(4Xjeon#*fc zri^z+s9t0?5d$vIlqyx^zeVO}Go82vS+6M`kV*x0tNtcp-KHVcL*-ns377=Pma1&J zO4bym{}q_xK4iZ{laxg@%R=bk4}s{gCB367{h33j#h)DdV@z@&76*x{1L@#C(uYy# zdz!ce5=MnmrwJG71awVlLTPW{h*7W55hDq7c5e`6Khwn5;jq`Jj)_)O9fMl9+IK@d zB&pi>V$D<14~9e31;ALJlwYMzp-puzO}~Tg3$$vRU>n*daShl8+g17=+vxSmrtgQ@ z!1v20)eto~#xeX;P8JlZc1q|0vnZ{DB*jqhgF?-8Zfl_%mPWo%J zrLC;+v7$VjSSa6X;NpR*h{{XJH}eL)pMY1L*#Hljrx z{hK7H9uOVs=BS%T=UqMf6##1u?IhgKk>Qug(0Ni7zNq}X=7&{Q@!IRBS;cGDQmU-I zb2AzxXs=U}e#+$}p3&B2bQJ+qz$orlM4*7Fu5IS3PwpG6m}KE3<`0QpRhlt@><)0P d8hR>{Zs;8Y5;m_dAi0ok-msUQJNB}D;XmuN)a?KO literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a734d5715f5877293466f6ef59ebebfbb70aa118 GIT binary patch literal 5966 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d412dd5047abbdef873dfa3b65b4400f20372b92 GIT binary patch literal 13692 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 F{|A+jh&TWM literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a7f03181256db97ca32648ec0db9d5cde366d928 GIT binary patch literal 230 zcmYjLF%H5o3``{kgw%&HP!CK<2=M|I9#EyN)f&g6tFjRq`V(09-*Z`Acy{^x?MFvkEO0p4y)drkTdvb!I a8pt$I%8X)J7Jhonx4mlygS+(POQ^nmc|zF$ literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6e5d45a904a9c872343b342fcab1ee3a4a21705e GIT binary patch literal 1251 zcmZux&2JMq6t`!b$p@(@h=mob&|Gt1hH4kBRzjp<6!9TwE~ClVWZZh}k?pif zl}Ia<+iKN+fgbl?nkxsicTQZo&yyw;fg`{8efask-+OP;wY3g{mCrw=9|=Mq9CLYj zz-+=cZ-7uVL=;m`;30;8UwDN-^s$o>L5jw(QJ)(kD4N42My#oyf-VrPqCITax~Aw9 zSB6*M+@kGwXxOFR3)Jfz|MHC4l%_Tf$4oMvTCQX$)R<@CTctyzCOTsw<;H40nmDbA zI{!gTsNciY9X*k7D>>pePfW>creMaTV+QKAm#irN;F@Jt=_v@VKieDZC0o1OTYo0c zU-kQs`#T_AAF%Sl#;?0d9c-mSFzsZICS1^MdC0Yr1(P;&h%8qChc@gj*yb-Fw#JA0 z|9Eq6=I!ITKSQTaF|r;dCwNX~_`N?PXZZ9sMsOxG{|wI?uMuq!M9>LfDc3iUd2%1& z`nL!48*P4BYa9FceK7N9jWdU2a4dEf0J5-HLOL;Aj)BecRB}_8kTR12j*Ny}hJ)=v z2x&*1P6+EcvlA^%XmhqK1(>Z|(ItveZGC*TP?TwTZ)xzd=T+o@OIodug&F~j)1*ix z)PWxVIMA$2wTtB_XH2ZT_Ipk319}xHQ=4mtaCOa0Mx|C66fs#;w+hSpK1-I5CD0nl z$Q3B59af$)71>u@_JXRtP%wE|HAiW7z#yiptDCkcA(g7T5;!inc&O|8jLWww0qMU; z-++KV{~hP5U@;SdD{J>vE{&40(OC>pDHEqh%z(i?Xks87dc{DO#ux3(;^+`Ui3K0U z<<#a%{v7=l8xFQ51PAz-xa4J=aA^V0RK%*h7y}d6nZ(ObqjFkZTe@9gu?{hsn?O+D zVR9ajzzawVcQL`<`6kg$)my8YNkUbYB)SWHbr+tDR!>GSSHeVJfL~PNr|%hAm?($N zqHedpYchpF9BcThpz2O-00>Z}qp}{e=t!p}C#j1GP%~&0MU4~2K2Y0RY a5E^hI*zXuP<3J#O%j-hkU5~)-`u_t>4s?$I literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ad6c27edce395fd70f7dd4cf9caae90f789abd50 GIT binary patch literal 2027 zcmah~&yU+g6rOP=j+17$+ZL&%DwS2W6^pcSp(miKD%w&i=n8FHp+-Wkt{Ztd)CxuO7QuJMZ*6 z^|+Ot%Deq8C8DdJik9I_8L^&=>r7{zWBneYFRAHnO1BKHuj)Z1BD71=&u}dpYL|)uWwTMfl zCs;W9=-JoL!nlOd;pPLZu6;I6Gk#ybNVSr=kY!A*DM!sg-^6zppV@-2 zz`i0S*{3sdK<|+~x=Ux&TrVBo*l*aiJ^B+Z*$h2rJ51lfPV?9f*>3K;Gcu#xeU}_q z;9Aq0pQn=hk@S1;Ys32G!xg@;-A|?ed^vmG>-cCVn)%q8c@ZKZGxF_OYuY||aX>W; z`o;N<;W;{OFQ0+`o{-$UOv}-_Q#rjG6&?OY^eJ5N*RR1y>WJT{*ra%aD z8-s=V^vb3>hVK$iP;(6M0r3yJZ*1tN8;_J0emO!slobDWM%y#%t;$iRYT4Itv$kec zE=Zq8W!1=ptXL71ql#^-R08Ps^7*PgOtBy3!qlkGMc1BRecP#XSTmO(2y>}-=rTqf z^o(`UV|?fwGFMwvV$0Y?L)jo6zM8=t1It|wV$9eifbbV# z^v5QZiCO!w4A)tr&=>CPy)-3BHAF*U}&mVo^_^zPxOS;5;3sA8n1L zJbu6bzJ>ggYi8YFRExR{9kI{9W~N;baAT2jPY@Tj0~%FpNu~yAkh+p!m3(Dd$9&%ygP0+br(%K>~H3~IT@T$d;Hfd(GtpgRa1@gbl zI}0DueP*RU4N%)g&|jQ7=rn52k7h5 z*r+Z5*WNO*d*b_86m^}SC&tycxA7N{nclJDUOQX^QC&V!by?f(tilfs(pT9ePet+2#g+x)58i73CC2h0mYo2_A}FJq?;QjNwjjBWMQbqag8a>d7) axNVDsxd6c$9`&3qJ^DF}cAZYcJO3}4ZA;?- literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bb4af520059303437de2e4eac32e74520d0661bb GIT binary patch literal 1368 zcmZux&yO256tgiZ7Km5~s)}>Diy@Z$3i5 z*UIJ50_9_v`dbhg%5aW`%@+?b=p-jaYuLi|S}XSof9PYxe02!Amj^|A*e=3h==S}5 ztLO|nu#eW;tb2}!J6Vvme?Y@GGW-?lg?~T}H0WV_LsddBmCU)BCc5NKDVWyjgu(XJ zFHeq6lK$aA|BK}K>%ri`;IkgF-b1d94Ih<;OOfVaw|m6O_wRggDCLuWn&(W7f#Stz z!@m$_AEy2V#EN9N!n*r8`W~-ZiW;=W8Cjuo0`LLg@*7woS!?ChE2fosYY%qu3w-9U z@Y-Mb=lG|a7_IOuSa}f5e@V`Q$KdNB550gQiQPL$&u$~^ekULwBSAf6+KZo?HJ3AJ za-O)Xw~+~FTk8%)49*FZsl9ypNyYPwO2Oy@p$$+wX5Up@v4ROhE6v4(nkl142S*h6 z(~&bTl^jC}qfUpyIA*3&LenxeQ)(ogPZ`T8Kc%`F*Jh_xo-drIiRdGUrsiC;cd6R= z4Iq2uA`O=J`>7DpZ1OabPNkx^^ajkoKwwMI{e6dLU%G>$955)R0r~RUr%W3z()s{t z27Jaws>MeTXZen!ToZd8{`nc*+eGfwT~RQTW~oV&3)kh__fwv;tU>l)?_0XJZG&7+ zCQMnMDJ9{Pu~9Wq1e(DHz@SKteN$JXP3e-RE$y}=kT@iE>)_d#IVzS&ZN0jn)|*K# zdTr~8v|zS9O238E(Ojh^P}C}@Ew(1iJZ!okOkCZQMAh$t1L{uT glDJm8gm(*>RXMwdLDRb+LL3sH2gG+tmvmbH0K~|UfB*mh literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f495d761abfdc4e4b18435d2ca0d639c3ae5394 GIT binary patch literal 2650 zcma);&2tn*6u`UZdncO&!k73#4HO7#$u4LWB4tq)As`xqMMR3Vbev3gb_Zsrx4L^1 zvY9=_;v~htkQ}}E7xw-lsH=6W$XoTTLzA zz8PP?_0_HG3wP9Pn&f#bhARWkQYwTxw90sq$T($1k(8vKgw@>V_rJIw&wsKo|5<$J z?$Xk&rJJD2Sp@AWxIK^=E0bI~U(!c1we;>Lmjh21?s>Syx6nvbp)EYN2;Rn(wS&iY zg+)}^#QFe@?edDWw(T7xod@nihhGM{ZRDpayzLQZ2a8WDOdOD5_~wEREd3obx3a-C z-stQNV?Z=9Aj-xH;Y&w*u~g{mQGiqddJ4%GJRhl?$t@ zG?m#JU8HL?SN>#=%DujD?e0w#(2|JtO!m2UXUkE|iE$=6YG$`rZ}`PmLPe?^2{HK* z@uM*Hx2K&xD`L|!|8yDPO?q~3^-2`2~7rG5#YB@j{;sG>a^Er zxz@?EmCj&8_F4IU`@@dNVC*1CA0|C2I)iM`iL+8t4nTAOPnZWPL}z7~<)l-SnA2X8 zZnOs*>PYR4J={1I!(1MMy^6!oATPk7<=_y{z%#@FK49_JK%Q!-b}#MMJ;)?JKPwo|z~7&6mZM$*+-5*wgfA&y3~LOa&@Kj%pAfxjJ8xI)A| z4kHbESMNaL@iLNq8VwTJ*HGwpV>EzhI+7Lx#uL5~8IMFH;}CnsH`=3%i^eaL4{UWZ zQB%8ll8>X5QwRcyN*1kVITh`2=@|xdN8SH9v0xlX?I&dfNE;pP@CIlqlY)xqT-s+$ zKyJVnE@aE31J?_*8p;!l!`i$FT@wKg)eexxQ8s8%78Ab~tfcN~oiKMkW&4ae@KH{XEURHL8a1wes1QUM4AKXJw$u^{vas*(?=_*?kt z<8h!tAvU05VKkZpP&|MmAkGte+_;CzOAeCW#v_dMuL`z(VxWRq0r50M7~Mzr5b+)4 zpe-A4^Ow;DBpchI#%~M+l1RAoE5 z4eI!MCg{5nH>e9!9NR_{oCh<#oUJ5z%*=rx)N~!a-R>+DB$<__AZQpyk=ef{u3pxV zK90_r0}RSTYjphjizzQsqPmJ(@(jSbH+z+-bjFGQXBiS>N8@gKpO@92SV>5qO6hap&H zumfdUyP7tp#Dk64q(vy$kf&4|&(G+YZ|gy>&JLo&x;W}%S~ay*F=VBHs>)k>lvkH` zv;W<(TIs9VGq*ow>d@bS`QkD(XxhS)-yfbILefCW>`I=8Zc|I}VW_lwQf&S1`TP>h zZ5`vY@K8PzZL_d3`*o=J?Y)ZMPV=liiHP9Zi|X{t1BNooMSK5W6wR=4y*lx)L-+oi znB&hxqCQGrS-RFNH^6f}?(3z!Nhg2~*NM;dpFP!p`m$J`zCj%8f)vLl*mYskWy2V} o&$IgUkjo7;q=3Y=#LM}iZ71BWT^hX4Qo literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/metadata.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/metadata.py new file mode 100644 index 0000000..5709962 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/metadata.py @@ -0,0 +1,38 @@ +"""Metadata generation logic for source distributions. +""" + +import os + +from pip._internal.utils.subprocess import runner_with_spinner_message +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from pip._vendor.pep517.wrappers import Pep517HookCaller + + from pip._internal.build_env import BuildEnvironment + + +def generate_metadata(build_env, backend): + # type: (BuildEnvironment, Pep517HookCaller) -> str + """Generate metadata using mechanisms described in PEP 517. + + Returns the generated metadata directory. + """ + metadata_tmpdir = TempDirectory( + kind="modern-metadata", globally_managed=True + ) + + metadata_dir = metadata_tmpdir.path + + with build_env: + # Note that Pep517HookCaller implements a fallback for + # prepare_metadata_for_build_wheel, so we don't have to + # consider the possibility that this hook doesn't exist. + runner = runner_with_spinner_message("Preparing wheel metadata") + with backend.subprocess_runner(runner): + distinfo_dir = backend.prepare_metadata_for_build_wheel( + metadata_dir + ) + + return os.path.join(metadata_dir, distinfo_dir) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/metadata_legacy.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/metadata_legacy.py new file mode 100644 index 0000000..14762ae --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/metadata_legacy.py @@ -0,0 +1,77 @@ +"""Metadata generation logic for legacy source distributions. +""" + +import logging +import os + +from pip._internal.exceptions import InstallationError +from pip._internal.utils.setuptools_build import make_setuptools_egg_info_args +from pip._internal.utils.subprocess import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from pip._internal.build_env import BuildEnvironment + +logger = logging.getLogger(__name__) + + +def _find_egg_info(directory): + # type: (str) -> str + """Find an .egg-info subdirectory in `directory`. + """ + filenames = [ + f for f in os.listdir(directory) if f.endswith(".egg-info") + ] + + if not filenames: + raise InstallationError( + "No .egg-info directory found in {}".format(directory) + ) + + if len(filenames) > 1: + raise InstallationError( + "More than one .egg-info directory found in {}".format( + directory + ) + ) + + return os.path.join(directory, filenames[0]) + + +def generate_metadata( + build_env, # type: BuildEnvironment + setup_py_path, # type: str + source_dir, # type: str + isolated, # type: bool + details, # type: str +): + # type: (...) -> str + """Generate metadata using setup.py-based defacto mechanisms. + + Returns the generated metadata directory. + """ + logger.debug( + 'Running setup.py (path:%s) egg_info for package %s', + setup_py_path, details, + ) + + egg_info_dir = TempDirectory( + kind="pip-egg-info", globally_managed=True + ).path + + args = make_setuptools_egg_info_args( + setup_py_path, + egg_info_dir=egg_info_dir, + no_user_config=isolated, + ) + + with build_env: + call_subprocess( + args, + cwd=source_dir, + command_desc='python setup.py egg_info', + ) + + # Return the .egg-info directory. + return _find_egg_info(egg_info_dir) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel.py new file mode 100644 index 0000000..d16ee09 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel.py @@ -0,0 +1,47 @@ +import logging +import os + +from pip._internal.utils.subprocess import runner_with_spinner_message +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional + + from pip._vendor.pep517.wrappers import Pep517HookCaller + +logger = logging.getLogger(__name__) + + +def build_wheel_pep517( + name, # type: str + backend, # type: Pep517HookCaller + metadata_directory, # type: str + build_options, # type: List[str] + tempd, # type: str +): + # type: (...) -> Optional[str] + """Build one InstallRequirement using the PEP 517 build process. + + Returns path to wheel if successfully built. Otherwise, returns None. + """ + assert metadata_directory is not None + if build_options: + # PEP 517 does not support --build-options + logger.error('Cannot build wheel for %s using PEP 517 when ' + '--build-option is present', name) + return None + try: + logger.debug('Destination directory: %s', tempd) + + runner = runner_with_spinner_message( + 'Building wheel for {} (PEP 517)'.format(name) + ) + with backend.subprocess_runner(runner): + wheel_name = backend.build_wheel( + tempd, + metadata_directory=metadata_directory, + ) + except Exception: + logger.error('Failed building wheel for %s', name) + return None + return os.path.join(tempd, wheel_name) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel_legacy.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel_legacy.py new file mode 100644 index 0000000..9da365e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel_legacy.py @@ -0,0 +1,113 @@ +import logging +import os.path + +from pip._internal.cli.spinners import open_spinner +from pip._internal.utils.setuptools_build import make_setuptools_bdist_wheel_args +from pip._internal.utils.subprocess import ( + LOG_DIVIDER, + call_subprocess, + format_command_args, +) +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional, Text + +logger = logging.getLogger(__name__) + + +def format_command_result( + command_args, # type: List[str] + command_output, # type: Text +): + # type: (...) -> str + """Format command information for logging.""" + command_desc = format_command_args(command_args) + text = 'Command arguments: {}\n'.format(command_desc) + + if not command_output: + text += 'Command output: None' + elif logger.getEffectiveLevel() > logging.DEBUG: + text += 'Command output: [use --verbose to show]' + else: + if not command_output.endswith('\n'): + command_output += '\n' + text += 'Command output:\n{}{}'.format(command_output, LOG_DIVIDER) + + return text + + +def get_legacy_build_wheel_path( + names, # type: List[str] + temp_dir, # type: str + name, # type: str + command_args, # type: List[str] + command_output, # type: Text +): + # type: (...) -> Optional[str] + """Return the path to the wheel in the temporary build directory.""" + # Sort for determinism. + names = sorted(names) + if not names: + msg = ( + 'Legacy build of wheel for {!r} created no files.\n' + ).format(name) + msg += format_command_result(command_args, command_output) + logger.warning(msg) + return None + + if len(names) > 1: + msg = ( + 'Legacy build of wheel for {!r} created more than one file.\n' + 'Filenames (choosing first): {}\n' + ).format(name, names) + msg += format_command_result(command_args, command_output) + logger.warning(msg) + + return os.path.join(temp_dir, names[0]) + + +def build_wheel_legacy( + name, # type: str + setup_py_path, # type: str + source_dir, # type: str + global_options, # type: List[str] + build_options, # type: List[str] + tempd, # type: str +): + # type: (...) -> Optional[str] + """Build one unpacked package using the "legacy" build process. + + Returns path to wheel if successfully built. Otherwise, returns None. + """ + wheel_args = make_setuptools_bdist_wheel_args( + setup_py_path, + global_options=global_options, + build_options=build_options, + destination_dir=tempd, + ) + + spin_message = 'Building wheel for {} (setup.py)'.format(name) + with open_spinner(spin_message) as spinner: + logger.debug('Destination directory: %s', tempd) + + try: + output = call_subprocess( + wheel_args, + cwd=source_dir, + spinner=spinner, + ) + except Exception: + spinner.finish("error") + logger.error('Failed building wheel for %s', name) + return None + + names = os.listdir(tempd) + wheel_path = get_legacy_build_wheel_path( + names=names, + temp_dir=tempd, + name=name, + command_args=wheel_args, + command_output=output, + ) + return wheel_path diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/check.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/check.py new file mode 100644 index 0000000..5dee6bc --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/check.py @@ -0,0 +1,155 @@ +"""Validation of dependencies of packages +""" + +import logging +from collections import namedtuple + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.pkg_resources import RequirementParseError + +from pip._internal.distributions import make_distribution_for_install_requirement +from pip._internal.utils.misc import get_installed_distributions +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +logger = logging.getLogger(__name__) + +if MYPY_CHECK_RUNNING: + from typing import Any, Callable, Dict, List, Optional, Set, Tuple + + from pip._internal.req.req_install import InstallRequirement + + # Shorthands + PackageSet = Dict[str, 'PackageDetails'] + Missing = Tuple[str, Any] + Conflicting = Tuple[str, str, Any] + + MissingDict = Dict[str, List[Missing]] + ConflictingDict = Dict[str, List[Conflicting]] + CheckResult = Tuple[MissingDict, ConflictingDict] + ConflictDetails = Tuple[PackageSet, CheckResult] + +PackageDetails = namedtuple('PackageDetails', ['version', 'requires']) + + +def create_package_set_from_installed(**kwargs): + # type: (**Any) -> Tuple[PackageSet, bool] + """Converts a list of distributions into a PackageSet. + """ + # Default to using all packages installed on the system + if kwargs == {}: + kwargs = {"local_only": False, "skip": ()} + + package_set = {} + problems = False + for dist in get_installed_distributions(**kwargs): + name = canonicalize_name(dist.project_name) + try: + package_set[name] = PackageDetails(dist.version, dist.requires()) + except (OSError, RequirementParseError) as e: + # Don't crash on unreadable or broken metadata + logger.warning("Error parsing requirements for %s: %s", name, e) + problems = True + return package_set, problems + + +def check_package_set(package_set, should_ignore=None): + # type: (PackageSet, Optional[Callable[[str], bool]]) -> CheckResult + """Check if a package set is consistent + + If should_ignore is passed, it should be a callable that takes a + package name and returns a boolean. + """ + + missing = {} + conflicting = {} + + for package_name in package_set: + # Info about dependencies of package_name + missing_deps = set() # type: Set[Missing] + conflicting_deps = set() # type: Set[Conflicting] + + if should_ignore and should_ignore(package_name): + continue + + for req in package_set[package_name].requires: + name = canonicalize_name(req.project_name) # type: str + + # Check if it's missing + if name not in package_set: + missed = True + if req.marker is not None: + missed = req.marker.evaluate() + if missed: + missing_deps.add((name, req)) + continue + + # Check if there's a conflict + version = package_set[name].version # type: str + if not req.specifier.contains(version, prereleases=True): + conflicting_deps.add((name, version, req)) + + if missing_deps: + missing[package_name] = sorted(missing_deps, key=str) + if conflicting_deps: + conflicting[package_name] = sorted(conflicting_deps, key=str) + + return missing, conflicting + + +def check_install_conflicts(to_install): + # type: (List[InstallRequirement]) -> ConflictDetails + """For checking if the dependency graph would be consistent after \ + installing given requirements + """ + # Start from the current state + package_set, _ = create_package_set_from_installed() + # Install packages + would_be_installed = _simulate_installation_of(to_install, package_set) + + # Only warn about directly-dependent packages; create a whitelist of them + whitelist = _create_whitelist(would_be_installed, package_set) + + return ( + package_set, + check_package_set( + package_set, should_ignore=lambda name: name not in whitelist + ) + ) + + +def _simulate_installation_of(to_install, package_set): + # type: (List[InstallRequirement], PackageSet) -> Set[str] + """Computes the version of packages after installing to_install. + """ + + # Keep track of packages that were installed + installed = set() + + # Modify it as installing requirement_set would (assuming no errors) + for inst_req in to_install: + abstract_dist = make_distribution_for_install_requirement(inst_req) + dist = abstract_dist.get_pkg_resources_distribution() + + assert dist is not None + name = canonicalize_name(dist.key) + package_set[name] = PackageDetails(dist.version, dist.requires()) + + installed.add(name) + + return installed + + +def _create_whitelist(would_be_installed, package_set): + # type: (Set[str], PackageSet) -> Set[str] + packages_affected = set(would_be_installed) + + for package_name in package_set: + if package_name in packages_affected: + continue + + for req in package_set[package_name].requires: + if canonicalize_name(req.name) in packages_affected: + packages_affected.add(package_name) + break + + return packages_affected diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/freeze.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/freeze.py new file mode 100644 index 0000000..d4f790c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/freeze.py @@ -0,0 +1,277 @@ +from __future__ import absolute_import + +import collections +import logging +import os + +from pip._vendor import six +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.pkg_resources import RequirementParseError + +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.req.constructors import ( + install_req_from_editable, + install_req_from_line, +) +from pip._internal.req.req_file import COMMENT_RE +from pip._internal.utils.direct_url_helpers import ( + direct_url_as_pep440_direct_reference, + dist_get_direct_url, +) +from pip._internal.utils.misc import dist_is_editable, get_installed_distributions +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import ( + Container, + Dict, + Iterable, + Iterator, + List, + Optional, + Set, + Tuple, + Union, + ) + + from pip._vendor.pkg_resources import Distribution, Requirement + + from pip._internal.cache import WheelCache + + RequirementInfo = Tuple[Optional[Union[str, Requirement]], bool, List[str]] + + +logger = logging.getLogger(__name__) + + +def freeze( + requirement=None, # type: Optional[List[str]] + find_links=None, # type: Optional[List[str]] + local_only=False, # type: bool + user_only=False, # type: bool + paths=None, # type: Optional[List[str]] + isolated=False, # type: bool + wheel_cache=None, # type: Optional[WheelCache] + exclude_editable=False, # type: bool + skip=() # type: Container[str] +): + # type: (...) -> Iterator[str] + find_links = find_links or [] + + for link in find_links: + yield '-f {}'.format(link) + installations = {} # type: Dict[str, FrozenRequirement] + + for dist in get_installed_distributions( + local_only=local_only, + skip=(), + user_only=user_only, + paths=paths + ): + try: + req = FrozenRequirement.from_dist(dist) + except RequirementParseError as exc: + # We include dist rather than dist.project_name because the + # dist string includes more information, like the version and + # location. We also include the exception message to aid + # troubleshooting. + logger.warning( + 'Could not generate requirement for distribution %r: %s', + dist, exc + ) + continue + if exclude_editable and req.editable: + continue + installations[req.canonical_name] = req + + if requirement: + # the options that don't get turned into an InstallRequirement + # should only be emitted once, even if the same option is in multiple + # requirements files, so we need to keep track of what has been emitted + # so that we don't emit it again if it's seen again + emitted_options = set() # type: Set[str] + # keep track of which files a requirement is in so that we can + # give an accurate warning if a requirement appears multiple times. + req_files = collections.defaultdict(list) # type: Dict[str, List[str]] + for req_file_path in requirement: + with open(req_file_path) as req_file: + for line in req_file: + if (not line.strip() or + line.strip().startswith('#') or + line.startswith(( + '-r', '--requirement', + '-f', '--find-links', + '-i', '--index-url', + '--pre', + '--trusted-host', + '--process-dependency-links', + '--extra-index-url', + '--use-feature'))): + line = line.rstrip() + if line not in emitted_options: + emitted_options.add(line) + yield line + continue + + if line.startswith('-e') or line.startswith('--editable'): + if line.startswith('-e'): + line = line[2:].strip() + else: + line = line[len('--editable'):].strip().lstrip('=') + line_req = install_req_from_editable( + line, + isolated=isolated, + ) + else: + line_req = install_req_from_line( + COMMENT_RE.sub('', line).strip(), + isolated=isolated, + ) + + if not line_req.name: + logger.info( + "Skipping line in requirement file [%s] because " + "it's not clear what it would install: %s", + req_file_path, line.strip(), + ) + logger.info( + " (add #egg=PackageName to the URL to avoid" + " this warning)" + ) + else: + line_req_canonical_name = canonicalize_name( + line_req.name) + if line_req_canonical_name not in installations: + # either it's not installed, or it is installed + # but has been processed already + if not req_files[line_req.name]: + logger.warning( + "Requirement file [%s] contains %s, but " + "package %r is not installed", + req_file_path, + COMMENT_RE.sub('', line).strip(), + line_req.name + ) + else: + req_files[line_req.name].append(req_file_path) + else: + yield str(installations[ + line_req_canonical_name]).rstrip() + del installations[line_req_canonical_name] + req_files[line_req.name].append(req_file_path) + + # Warn about requirements that were included multiple times (in a + # single requirements file or in different requirements files). + for name, files in six.iteritems(req_files): + if len(files) > 1: + logger.warning("Requirement %s included multiple times [%s]", + name, ', '.join(sorted(set(files)))) + + yield( + '## The following requirements were added by ' + 'pip freeze:' + ) + for installation in sorted( + installations.values(), key=lambda x: x.name.lower()): + if installation.canonical_name not in skip: + yield str(installation).rstrip() + + +def get_requirement_info(dist): + # type: (Distribution) -> RequirementInfo + """ + Compute and return values (req, editable, comments) for use in + FrozenRequirement.from_dist(). + """ + if not dist_is_editable(dist): + return (None, False, []) + + location = os.path.normcase(os.path.abspath(dist.location)) + + from pip._internal.vcs import RemoteNotFoundError, vcs + vcs_backend = vcs.get_backend_for_dir(location) + + if vcs_backend is None: + req = dist.as_requirement() + logger.debug( + 'No VCS found for editable requirement "%s" in: %r', req, + location, + ) + comments = [ + '# Editable install with no version control ({})'.format(req) + ] + return (location, True, comments) + + try: + req = vcs_backend.get_src_requirement(location, dist.project_name) + except RemoteNotFoundError: + req = dist.as_requirement() + comments = [ + '# Editable {} install with no remote ({})'.format( + type(vcs_backend).__name__, req, + ) + ] + return (location, True, comments) + + except BadCommand: + logger.warning( + 'cannot determine version of editable source in %s ' + '(%s command not found in path)', + location, + vcs_backend.name, + ) + return (None, True, []) + + except InstallationError as exc: + logger.warning( + "Error when trying to get requirement for VCS system %s, " + "falling back to uneditable format", exc + ) + else: + if req is not None: + return (req, True, []) + + logger.warning( + 'Could not determine repository location of %s', location + ) + comments = ['## !! Could not determine repository location'] + + return (None, False, comments) + + +class FrozenRequirement(object): + def __init__(self, name, req, editable, comments=()): + # type: (str, Union[str, Requirement], bool, Iterable[str]) -> None + self.name = name + self.canonical_name = canonicalize_name(name) + self.req = req + self.editable = editable + self.comments = comments + + @classmethod + def from_dist(cls, dist): + # type: (Distribution) -> FrozenRequirement + # TODO `get_requirement_info` is taking care of editable requirements. + # TODO This should be refactored when we will add detection of + # editable that provide .dist-info metadata. + req, editable, comments = get_requirement_info(dist) + if req is None and not editable: + # if PEP 610 metadata is present, attempt to use it + direct_url = dist_get_direct_url(dist) + if direct_url: + req = direct_url_as_pep440_direct_reference( + direct_url, dist.project_name + ) + comments = [] + if req is None: + # name==version requirement + req = dist.as_requirement() + + return cls(dist.project_name, req, editable, comments=comments) + + def __str__(self): + # type: () -> str + req = self.req + if self.editable: + req = '-e {}'.format(req) + return '\n'.join(list(self.comments) + [str(req)]) + '\n' diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__init__.py new file mode 100644 index 0000000..24d6a5d --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__init__.py @@ -0,0 +1,2 @@ +"""For modules related to installing packages. +""" diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6aad1d5a2318c366025227cbab33310f0a99a00a GIT binary patch literal 288 zcmYjMy-ou$49<0FRjKcgwGurKosbY>>d3;z5`~L(my)xiI209$N8mwtrLH^zOicLr zk+5W2w!iPQ?N_U%Q5&8={8sbZRQ$I_iz{_mXb9%kgyzPqXHRE4E_USbkWg&FKF+W-In literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f1411754180b1a1553aefe470dc6004cc4ad969e GIT binary patch literal 1406 zcmZux&5s*36!&~2nS5>1b|usg!5rWaiOqmGAyrVZs-R*Us#XZ?aPUsX-ifKlp4y(2 ztfr@Ot$N`PXpj6ioPFiQoeLZg&$HQ&inZmJ@%!+5{{5bljmHB7WA);%?Dq~rf4I%% z5y0jiEWHLnP>P60eD0+l{07`FgEa7*F63d^NjvR#hj+_f+H1eNJSzKX-$S&oj=-S#Xr6N*QRnP&$~5GoAjvVh&4 zGJ8sK>u;pw8gCkpt}C>@X;aO|K|SwxA^h*i^YS**R#Ne2TU6q zeOI}9GH#cV+gAcYafaK#DG!luA||Lg0t3pW~F3Z ztOhX*BjXET=dJ4GgU7WHOcbYMg66#4Q&R-G!G@bNYn`JG~1c^do=dwbKv1U4Ik|g8u-` C^PG49 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__pycache__/legacy.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/__pycache__/legacy.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..064ea184faf726827bda0213e107089c3020926f GIT binary patch literal 3296 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 O_=52YqRWTdCI1&k!q8Iy literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/editable_legacy.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/editable_legacy.py new file mode 100644 index 0000000..a668a61 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/editable_legacy.py @@ -0,0 +1,52 @@ +"""Legacy editable installation process, i.e. `setup.py develop`. +""" +import logging + +from pip._internal.utils.logging import indent_log +from pip._internal.utils.setuptools_build import make_setuptools_develop_args +from pip._internal.utils.subprocess import call_subprocess +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional, Sequence + + from pip._internal.build_env import BuildEnvironment + + +logger = logging.getLogger(__name__) + + +def install_editable( + install_options, # type: List[str] + global_options, # type: Sequence[str] + prefix, # type: Optional[str] + home, # type: Optional[str] + use_user_site, # type: bool + name, # type: str + setup_py_path, # type: str + isolated, # type: bool + build_env, # type: BuildEnvironment + unpacked_source_directory, # type: str +): + # type: (...) -> None + """Install a package in editable mode. Most arguments are pass-through + to setuptools. + """ + logger.info('Running setup.py develop for %s', name) + + args = make_setuptools_develop_args( + setup_py_path, + global_options=global_options, + install_options=install_options, + no_user_config=isolated, + prefix=prefix, + home=home, + use_user_site=use_user_site, + ) + + with indent_log(): + with build_env: + call_subprocess( + args, + cwd=unpacked_source_directory, + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/legacy.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/legacy.py new file mode 100644 index 0000000..87227d5 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/legacy.py @@ -0,0 +1,130 @@ +"""Legacy installation process, i.e. `setup.py install`. +""" + +import logging +import os +import sys +from distutils.util import change_root + +from pip._internal.exceptions import InstallationError +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ensure_dir +from pip._internal.utils.setuptools_build import make_setuptools_install_args +from pip._internal.utils.subprocess import runner_with_spinner_message +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional, Sequence + + from pip._internal.build_env import BuildEnvironment + from pip._internal.models.scheme import Scheme + + +logger = logging.getLogger(__name__) + + +class LegacyInstallFailure(Exception): + def __init__(self): + # type: () -> None + self.parent = sys.exc_info() + + +def install( + install_options, # type: List[str] + global_options, # type: Sequence[str] + root, # type: Optional[str] + home, # type: Optional[str] + prefix, # type: Optional[str] + use_user_site, # type: bool + pycompile, # type: bool + scheme, # type: Scheme + setup_py_path, # type: str + isolated, # type: bool + req_name, # type: str + build_env, # type: BuildEnvironment + unpacked_source_directory, # type: str + req_description, # type: str +): + # type: (...) -> bool + + header_dir = scheme.headers + + with TempDirectory(kind="record") as temp_dir: + try: + record_filename = os.path.join(temp_dir.path, 'install-record.txt') + install_args = make_setuptools_install_args( + setup_py_path, + global_options=global_options, + install_options=install_options, + record_filename=record_filename, + root=root, + prefix=prefix, + header_dir=header_dir, + home=home, + use_user_site=use_user_site, + no_user_config=isolated, + pycompile=pycompile, + ) + + runner = runner_with_spinner_message( + "Running setup.py install for {}".format(req_name) + ) + with indent_log(), build_env: + runner( + cmd=install_args, + cwd=unpacked_source_directory, + ) + + if not os.path.exists(record_filename): + logger.debug('Record file %s not found', record_filename) + # Signal to the caller that we didn't install the new package + return False + + except Exception: + # Signal to the caller that we didn't install the new package + raise LegacyInstallFailure + + # At this point, we have successfully installed the requirement. + + # We intentionally do not use any encoding to read the file because + # setuptools writes the file using distutils.file_util.write_file, + # which does not specify an encoding. + with open(record_filename) as f: + record_lines = f.read().splitlines() + + def prepend_root(path): + # type: (str) -> str + if root is None or not os.path.isabs(path): + return path + else: + return change_root(root, path) + + for line in record_lines: + directory = os.path.dirname(line) + if directory.endswith('.egg-info'): + egg_info_dir = prepend_root(directory) + break + else: + message = ( + "{} did not indicate that it installed an " + ".egg-info directory. Only setup.py projects " + "generating .egg-info directories are supported." + ).format(req_description) + raise InstallationError(message) + + new_lines = [] + for line in record_lines: + filename = line.strip() + if os.path.isdir(filename): + filename += os.path.sep + new_lines.append( + os.path.relpath(prepend_root(filename), egg_info_dir) + ) + new_lines.sort() + ensure_dir(egg_info_dir) + inst_files_path = os.path.join(egg_info_dir, 'installed-files.txt') + with open(inst_files_path, 'w') as f: + f.write('\n'.join(new_lines) + '\n') + + return True diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/wheel.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/wheel.py new file mode 100644 index 0000000..8b67ebb --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/install/wheel.py @@ -0,0 +1,846 @@ +"""Support for installing and building the "wheel" binary package format. +""" + +from __future__ import absolute_import + +import collections +import compileall +import contextlib +import csv +import importlib +import logging +import os.path +import re +import shutil +import sys +import warnings +from base64 import urlsafe_b64encode +from itertools import chain, starmap +from zipfile import ZipFile + +from pip._vendor import pkg_resources +from pip._vendor.distlib.scripts import ScriptMaker +from pip._vendor.distlib.util import get_export_entry +from pip._vendor.six import PY2, ensure_str, ensure_text, itervalues, reraise, text_type +from pip._vendor.six.moves import filterfalse, map + +from pip._internal.exceptions import InstallationError +from pip._internal.locations import get_major_minor_version +from pip._internal.models.direct_url import DIRECT_URL_METADATA_NAME, DirectUrl +from pip._internal.models.scheme import SCHEME_KEYS +from pip._internal.utils.filesystem import adjacent_tmp_file, replace +from pip._internal.utils.misc import captured_stdout, ensure_dir, hash_file, partition +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.unpacking import ( + current_umask, + is_within_directory, + set_extracted_file_to_default_mode_plus_executable, + zip_item_is_executable, +) +from pip._internal.utils.wheel import parse_wheel, pkg_resources_distribution_for_wheel + +# Use the custom cast function at runtime to make cast work, +# and import typing.cast when performing pre-commit and type +# checks +if not MYPY_CHECK_RUNNING: + from pip._internal.utils.typing import cast +else: + from email.message import Message + from typing import ( + IO, + Any, + Callable, + Dict, + Iterable, + Iterator, + List, + NewType, + Optional, + Protocol, + Sequence, + Set, + Tuple, + Union, + cast, + ) + from zipfile import ZipInfo + + from pip._vendor.pkg_resources import Distribution + + from pip._internal.models.scheme import Scheme + from pip._internal.utils.filesystem import NamedTemporaryFileResult + + RecordPath = NewType('RecordPath', text_type) + InstalledCSVRow = Tuple[RecordPath, str, Union[int, str]] + + class File(Protocol): + src_record_path = None # type: RecordPath + dest_path = None # type: text_type + changed = None # type: bool + + def save(self): + # type: () -> None + pass + + +logger = logging.getLogger(__name__) + + +def rehash(path, blocksize=1 << 20): + # type: (text_type, int) -> Tuple[str, str] + """Return (encoded_digest, length) for path using hashlib.sha256()""" + h, length = hash_file(path, blocksize) + digest = 'sha256=' + urlsafe_b64encode( + h.digest() + ).decode('latin1').rstrip('=') + # unicode/str python2 issues + return (digest, str(length)) # type: ignore + + +def csv_io_kwargs(mode): + # type: (str) -> Dict[str, Any] + """Return keyword arguments to properly open a CSV file + in the given mode. + """ + if PY2: + return {'mode': '{}b'.format(mode)} + else: + return {'mode': mode, 'newline': '', 'encoding': 'utf-8'} + + +def fix_script(path): + # type: (text_type) -> bool + """Replace #!python with #!/path/to/python + Return True if file was changed. + """ + # XXX RECORD hashes will need to be updated + assert os.path.isfile(path) + + with open(path, 'rb') as script: + firstline = script.readline() + if not firstline.startswith(b'#!python'): + return False + exename = sys.executable.encode(sys.getfilesystemencoding()) + firstline = b'#!' + exename + os.linesep.encode("ascii") + rest = script.read() + with open(path, 'wb') as script: + script.write(firstline) + script.write(rest) + return True + + +def wheel_root_is_purelib(metadata): + # type: (Message) -> bool + return metadata.get("Root-Is-Purelib", "").lower() == "true" + + +def get_entrypoints(distribution): + # type: (Distribution) -> Tuple[Dict[str, str], Dict[str, str]] + # get the entry points and then the script names + try: + console = distribution.get_entry_map('console_scripts') + gui = distribution.get_entry_map('gui_scripts') + except KeyError: + # Our dict-based Distribution raises KeyError if entry_points.txt + # doesn't exist. + return {}, {} + + def _split_ep(s): + # type: (pkg_resources.EntryPoint) -> Tuple[str, str] + """get the string representation of EntryPoint, + remove space and split on '=' + """ + split_parts = str(s).replace(" ", "").split("=") + return split_parts[0], split_parts[1] + + # convert the EntryPoint objects into strings with module:function + console = dict(_split_ep(v) for v in console.values()) + gui = dict(_split_ep(v) for v in gui.values()) + return console, gui + + +def message_about_scripts_not_on_PATH(scripts): + # type: (Sequence[str]) -> Optional[str] + """Determine if any scripts are not on PATH and format a warning. + Returns a warning message if one or more scripts are not on PATH, + otherwise None. + """ + if not scripts: + return None + + # Group scripts by the path they were installed in + grouped_by_dir = collections.defaultdict(set) # type: Dict[str, Set[str]] + for destfile in scripts: + parent_dir = os.path.dirname(destfile) + script_name = os.path.basename(destfile) + grouped_by_dir[parent_dir].add(script_name) + + # We don't want to warn for directories that are on PATH. + not_warn_dirs = [ + os.path.normcase(i).rstrip(os.sep) for i in + os.environ.get("PATH", "").split(os.pathsep) + ] + # If an executable sits with sys.executable, we don't warn for it. + # This covers the case of venv invocations without activating the venv. + not_warn_dirs.append(os.path.normcase(os.path.dirname(sys.executable))) + warn_for = { + parent_dir: scripts for parent_dir, scripts in grouped_by_dir.items() + if os.path.normcase(parent_dir) not in not_warn_dirs + } # type: Dict[str, Set[str]] + if not warn_for: + return None + + # Format a message + msg_lines = [] + for parent_dir, dir_scripts in warn_for.items(): + sorted_scripts = sorted(dir_scripts) # type: List[str] + if len(sorted_scripts) == 1: + start_text = "script {} is".format(sorted_scripts[0]) + else: + start_text = "scripts {} are".format( + ", ".join(sorted_scripts[:-1]) + " and " + sorted_scripts[-1] + ) + + msg_lines.append( + "The {} installed in '{}' which is not on PATH." + .format(start_text, parent_dir) + ) + + last_line_fmt = ( + "Consider adding {} to PATH or, if you prefer " + "to suppress this warning, use --no-warn-script-location." + ) + if len(msg_lines) == 1: + msg_lines.append(last_line_fmt.format("this directory")) + else: + msg_lines.append(last_line_fmt.format("these directories")) + + # Add a note if any directory starts with ~ + warn_for_tilde = any( + i[0] == "~" for i in os.environ.get("PATH", "").split(os.pathsep) if i + ) + if warn_for_tilde: + tilde_warning_msg = ( + "NOTE: The current PATH contains path(s) starting with `~`, " + "which may not be expanded by all applications." + ) + msg_lines.append(tilde_warning_msg) + + # Returns the formatted multiline message + return "\n".join(msg_lines) + + +def _normalized_outrows(outrows): + # type: (Iterable[InstalledCSVRow]) -> List[Tuple[str, str, str]] + """Normalize the given rows of a RECORD file. + + Items in each row are converted into str. Rows are then sorted to make + the value more predictable for tests. + + Each row is a 3-tuple (path, hash, size) and corresponds to a record of + a RECORD file (see PEP 376 and PEP 427 for details). For the rows + passed to this function, the size can be an integer as an int or string, + or the empty string. + """ + # Normally, there should only be one row per path, in which case the + # second and third elements don't come into play when sorting. + # However, in cases in the wild where a path might happen to occur twice, + # we don't want the sort operation to trigger an error (but still want + # determinism). Since the third element can be an int or string, we + # coerce each element to a string to avoid a TypeError in this case. + # For additional background, see-- + # https://github.com/pypa/pip/issues/5868 + return sorted( + (ensure_str(record_path, encoding='utf-8'), hash_, str(size)) + for record_path, hash_, size in outrows + ) + + +def _record_to_fs_path(record_path): + # type: (RecordPath) -> text_type + return record_path + + +def _fs_to_record_path(path, relative_to=None): + # type: (text_type, Optional[text_type]) -> RecordPath + if relative_to is not None: + # On Windows, do not handle relative paths if they belong to different + # logical disks + if os.path.splitdrive(path)[0].lower() == \ + os.path.splitdrive(relative_to)[0].lower(): + path = os.path.relpath(path, relative_to) + path = path.replace(os.path.sep, '/') + return cast('RecordPath', path) + + +def _parse_record_path(record_column): + # type: (str) -> RecordPath + p = ensure_text(record_column, encoding='utf-8') + return cast('RecordPath', p) + + +def get_csv_rows_for_installed( + old_csv_rows, # type: List[List[str]] + installed, # type: Dict[RecordPath, RecordPath] + changed, # type: Set[RecordPath] + generated, # type: List[str] + lib_dir, # type: str +): + # type: (...) -> List[InstalledCSVRow] + """ + :param installed: A map from archive RECORD path to installation RECORD + path. + """ + installed_rows = [] # type: List[InstalledCSVRow] + for row in old_csv_rows: + if len(row) > 3: + logger.warning('RECORD line has more than three elements: %s', row) + old_record_path = _parse_record_path(row[0]) + new_record_path = installed.pop(old_record_path, old_record_path) + if new_record_path in changed: + digest, length = rehash(_record_to_fs_path(new_record_path)) + else: + digest = row[1] if len(row) > 1 else '' + length = row[2] if len(row) > 2 else '' + installed_rows.append((new_record_path, digest, length)) + for f in generated: + path = _fs_to_record_path(f, lib_dir) + digest, length = rehash(f) + installed_rows.append((path, digest, length)) + for installed_record_path in itervalues(installed): + installed_rows.append((installed_record_path, '', '')) + return installed_rows + + +def get_console_script_specs(console): + # type: (Dict[str, str]) -> List[str] + """ + Given the mapping from entrypoint name to callable, return the relevant + console script specs. + """ + # Don't mutate caller's version + console = console.copy() + + scripts_to_generate = [] + + # Special case pip and setuptools to generate versioned wrappers + # + # The issue is that some projects (specifically, pip and setuptools) use + # code in setup.py to create "versioned" entry points - pip2.7 on Python + # 2.7, pip3.3 on Python 3.3, etc. But these entry points are baked into + # the wheel metadata at build time, and so if the wheel is installed with + # a *different* version of Python the entry points will be wrong. The + # correct fix for this is to enhance the metadata to be able to describe + # such versioned entry points, but that won't happen till Metadata 2.0 is + # available. + # In the meantime, projects using versioned entry points will either have + # incorrect versioned entry points, or they will not be able to distribute + # "universal" wheels (i.e., they will need a wheel per Python version). + # + # Because setuptools and pip are bundled with _ensurepip and virtualenv, + # we need to use universal wheels. So, as a stopgap until Metadata 2.0, we + # override the versioned entry points in the wheel and generate the + # correct ones. This code is purely a short-term measure until Metadata 2.0 + # is available. + # + # To add the level of hack in this section of code, in order to support + # ensurepip this code will look for an ``ENSUREPIP_OPTIONS`` environment + # variable which will control which version scripts get installed. + # + # ENSUREPIP_OPTIONS=altinstall + # - Only pipX.Y and easy_install-X.Y will be generated and installed + # ENSUREPIP_OPTIONS=install + # - pipX.Y, pipX, easy_install-X.Y will be generated and installed. Note + # that this option is technically if ENSUREPIP_OPTIONS is set and is + # not altinstall + # DEFAULT + # - The default behavior is to install pip, pipX, pipX.Y, easy_install + # and easy_install-X.Y. + pip_script = console.pop('pip', None) + if pip_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + scripts_to_generate.append('pip = ' + pip_script) + + if os.environ.get("ENSUREPIP_OPTIONS", "") != "altinstall": + scripts_to_generate.append( + 'pip{} = {}'.format(sys.version_info[0], pip_script) + ) + + scripts_to_generate.append( + 'pip{} = {}'.format(get_major_minor_version(), pip_script) + ) + # Delete any other versioned pip entry points + pip_ep = [k for k in console if re.match(r'pip(\d(\.\d)?)?$', k)] + for k in pip_ep: + del console[k] + easy_install_script = console.pop('easy_install', None) + if easy_install_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + scripts_to_generate.append( + 'easy_install = ' + easy_install_script + ) + + scripts_to_generate.append( + 'easy_install-{} = {}'.format( + get_major_minor_version(), easy_install_script + ) + ) + # Delete any other versioned easy_install entry points + easy_install_ep = [ + k for k in console if re.match(r'easy_install(-\d\.\d)?$', k) + ] + for k in easy_install_ep: + del console[k] + + # Generate the console entry points specified in the wheel + scripts_to_generate.extend(starmap('{} = {}'.format, console.items())) + + return scripts_to_generate + + +class ZipBackedFile(object): + def __init__(self, src_record_path, dest_path, zip_file): + # type: (RecordPath, text_type, ZipFile) -> None + self.src_record_path = src_record_path + self.dest_path = dest_path + self._zip_file = zip_file + self.changed = False + + def _getinfo(self): + # type: () -> ZipInfo + if not PY2: + return self._zip_file.getinfo(self.src_record_path) + # Python 2 does not expose a way to detect a ZIP's encoding, but the + # wheel specification (PEP 427) explicitly mandates that paths should + # use UTF-8, so we assume it is true. + return self._zip_file.getinfo(self.src_record_path.encode("utf-8")) + + def save(self): + # type: () -> None + # directory creation is lazy and after file filtering + # to ensure we don't install empty dirs; empty dirs can't be + # uninstalled. + parent_dir = os.path.dirname(self.dest_path) + ensure_dir(parent_dir) + + # When we open the output file below, any existing file is truncated + # before we start writing the new contents. This is fine in most + # cases, but can cause a segfault if pip has loaded a shared + # object (e.g. from pyopenssl through its vendored urllib3) + # Since the shared object is mmap'd an attempt to call a + # symbol in it will then cause a segfault. Unlinking the file + # allows writing of new contents while allowing the process to + # continue to use the old copy. + if os.path.exists(self.dest_path): + os.unlink(self.dest_path) + + zipinfo = self._getinfo() + + with self._zip_file.open(zipinfo) as f: + with open(self.dest_path, "wb") as dest: + shutil.copyfileobj(f, dest) + + if zip_item_is_executable(zipinfo): + set_extracted_file_to_default_mode_plus_executable(self.dest_path) + + +class ScriptFile(object): + def __init__(self, file): + # type: (File) -> None + self._file = file + self.src_record_path = self._file.src_record_path + self.dest_path = self._file.dest_path + self.changed = False + + def save(self): + # type: () -> None + self._file.save() + self.changed = fix_script(self.dest_path) + + +class MissingCallableSuffix(InstallationError): + def __init__(self, entry_point): + # type: (str) -> None + super(MissingCallableSuffix, self).__init__( + "Invalid script entry point: {} - A callable " + "suffix is required. Cf https://packaging.python.org/" + "specifications/entry-points/#use-for-scripts for more " + "information.".format(entry_point) + ) + + +def _raise_for_invalid_entrypoint(specification): + # type: (str) -> None + entry = get_export_entry(specification) + if entry is not None and entry.suffix is None: + raise MissingCallableSuffix(str(entry)) + + +class PipScriptMaker(ScriptMaker): + def make(self, specification, options=None): + # type: (str, Dict[str, Any]) -> List[str] + _raise_for_invalid_entrypoint(specification) + return super(PipScriptMaker, self).make(specification, options) + + +def _install_wheel( + name, # type: str + wheel_zip, # type: ZipFile + wheel_path, # type: str + scheme, # type: Scheme + pycompile=True, # type: bool + warn_script_location=True, # type: bool + direct_url=None, # type: Optional[DirectUrl] + requested=False, # type: bool +): + # type: (...) -> None + """Install a wheel. + + :param name: Name of the project to install + :param wheel_zip: open ZipFile for wheel being installed + :param scheme: Distutils scheme dictating the install directories + :param req_description: String used in place of the requirement, for + logging + :param pycompile: Whether to byte-compile installed Python files + :param warn_script_location: Whether to check that scripts are installed + into a directory on PATH + :raises UnsupportedWheel: + * when the directory holds an unpacked wheel with incompatible + Wheel-Version + * when the .dist-info dir does not match the wheel + """ + info_dir, metadata = parse_wheel(wheel_zip, name) + + if wheel_root_is_purelib(metadata): + lib_dir = scheme.purelib + else: + lib_dir = scheme.platlib + + # Record details of the files moved + # installed = files copied from the wheel to the destination + # changed = files changed while installing (scripts #! line typically) + # generated = files newly generated during the install (script wrappers) + installed = {} # type: Dict[RecordPath, RecordPath] + changed = set() # type: Set[RecordPath] + generated = [] # type: List[str] + + def record_installed(srcfile, destfile, modified=False): + # type: (RecordPath, text_type, bool) -> None + """Map archive RECORD paths to installation RECORD paths.""" + newpath = _fs_to_record_path(destfile, lib_dir) + installed[srcfile] = newpath + if modified: + changed.add(_fs_to_record_path(destfile)) + + def all_paths(): + # type: () -> Iterable[RecordPath] + names = wheel_zip.namelist() + # If a flag is set, names may be unicode in Python 2. We convert to + # text explicitly so these are valid for lookup in RECORD. + decoded_names = map(ensure_text, names) + for name in decoded_names: + yield cast("RecordPath", name) + + def is_dir_path(path): + # type: (RecordPath) -> bool + return path.endswith("/") + + def assert_no_path_traversal(dest_dir_path, target_path): + # type: (text_type, text_type) -> None + if not is_within_directory(dest_dir_path, target_path): + message = ( + "The wheel {!r} has a file {!r} trying to install" + " outside the target directory {!r}" + ) + raise InstallationError( + message.format(wheel_path, target_path, dest_dir_path) + ) + + def root_scheme_file_maker(zip_file, dest): + # type: (ZipFile, text_type) -> Callable[[RecordPath], File] + def make_root_scheme_file(record_path): + # type: (RecordPath) -> File + normed_path = os.path.normpath(record_path) + dest_path = os.path.join(dest, normed_path) + assert_no_path_traversal(dest, dest_path) + return ZipBackedFile(record_path, dest_path, zip_file) + + return make_root_scheme_file + + def data_scheme_file_maker(zip_file, scheme): + # type: (ZipFile, Scheme) -> Callable[[RecordPath], File] + scheme_paths = {} + for key in SCHEME_KEYS: + encoded_key = ensure_text(key) + scheme_paths[encoded_key] = ensure_text( + getattr(scheme, key), encoding=sys.getfilesystemencoding() + ) + + def make_data_scheme_file(record_path): + # type: (RecordPath) -> File + normed_path = os.path.normpath(record_path) + try: + _, scheme_key, dest_subpath = normed_path.split(os.path.sep, 2) + except ValueError: + message = ( + "Unexpected file in {}: {!r}. .data directory contents" + " should be named like: '/'." + ).format(wheel_path, record_path) + raise InstallationError(message) + + try: + scheme_path = scheme_paths[scheme_key] + except KeyError: + valid_scheme_keys = ", ".join(sorted(scheme_paths)) + message = ( + "Unknown scheme key used in {}: {} (for file {!r}). .data" + " directory contents should be in subdirectories named" + " with a valid scheme key ({})" + ).format( + wheel_path, scheme_key, record_path, valid_scheme_keys + ) + raise InstallationError(message) + + dest_path = os.path.join(scheme_path, dest_subpath) + assert_no_path_traversal(scheme_path, dest_path) + return ZipBackedFile(record_path, dest_path, zip_file) + + return make_data_scheme_file + + def is_data_scheme_path(path): + # type: (RecordPath) -> bool + return path.split("/", 1)[0].endswith(".data") + + paths = all_paths() + file_paths = filterfalse(is_dir_path, paths) + root_scheme_paths, data_scheme_paths = partition( + is_data_scheme_path, file_paths + ) + + make_root_scheme_file = root_scheme_file_maker( + wheel_zip, + ensure_text(lib_dir, encoding=sys.getfilesystemencoding()), + ) + files = map(make_root_scheme_file, root_scheme_paths) + + def is_script_scheme_path(path): + # type: (RecordPath) -> bool + parts = path.split("/", 2) + return ( + len(parts) > 2 and + parts[0].endswith(".data") and + parts[1] == "scripts" + ) + + other_scheme_paths, script_scheme_paths = partition( + is_script_scheme_path, data_scheme_paths + ) + + make_data_scheme_file = data_scheme_file_maker(wheel_zip, scheme) + other_scheme_files = map(make_data_scheme_file, other_scheme_paths) + files = chain(files, other_scheme_files) + + # Get the defined entry points + distribution = pkg_resources_distribution_for_wheel( + wheel_zip, name, wheel_path + ) + console, gui = get_entrypoints(distribution) + + def is_entrypoint_wrapper(file): + # type: (File) -> bool + # EP, EP.exe and EP-script.py are scripts generated for + # entry point EP by setuptools + path = file.dest_path + name = os.path.basename(path) + if name.lower().endswith('.exe'): + matchname = name[:-4] + elif name.lower().endswith('-script.py'): + matchname = name[:-10] + elif name.lower().endswith(".pya"): + matchname = name[:-4] + else: + matchname = name + # Ignore setuptools-generated scripts + return (matchname in console or matchname in gui) + + script_scheme_files = map(make_data_scheme_file, script_scheme_paths) + script_scheme_files = filterfalse( + is_entrypoint_wrapper, script_scheme_files + ) + script_scheme_files = map(ScriptFile, script_scheme_files) + files = chain(files, script_scheme_files) + + for file in files: + file.save() + record_installed(file.src_record_path, file.dest_path, file.changed) + + def pyc_source_file_paths(): + # type: () -> Iterator[text_type] + # We de-duplicate installation paths, since there can be overlap (e.g. + # file in .data maps to same location as file in wheel root). + # Sorting installation paths makes it easier to reproduce and debug + # issues related to permissions on existing files. + for installed_path in sorted(set(installed.values())): + full_installed_path = os.path.join(lib_dir, installed_path) + if not os.path.isfile(full_installed_path): + continue + if not full_installed_path.endswith('.py'): + continue + yield full_installed_path + + def pyc_output_path(path): + # type: (text_type) -> text_type + """Return the path the pyc file would have been written to. + """ + if PY2: + if sys.flags.optimize: + return path + 'o' + else: + return path + 'c' + else: + return importlib.util.cache_from_source(path) + + # Compile all of the pyc files for the installed files + if pycompile: + with captured_stdout() as stdout: + with warnings.catch_warnings(): + warnings.filterwarnings('ignore') + for path in pyc_source_file_paths(): + # Python 2's `compileall.compile_file` requires a str in + # error cases, so we must convert to the native type. + path_arg = ensure_str( + path, encoding=sys.getfilesystemencoding() + ) + success = compileall.compile_file( + path_arg, force=True, quiet=True + ) + if success: + pyc_path = pyc_output_path(path) + assert os.path.exists(pyc_path) + pyc_record_path = cast( + "RecordPath", pyc_path.replace(os.path.sep, "/") + ) + record_installed(pyc_record_path, pyc_path) + logger.debug(stdout.getvalue()) + + maker = PipScriptMaker(None, scheme.scripts) + + # Ensure old scripts are overwritten. + # See https://github.com/pypa/pip/issues/1800 + maker.clobber = True + + # Ensure we don't generate any variants for scripts because this is almost + # never what somebody wants. + # See https://bitbucket.org/pypa/distlib/issue/35/ + maker.variants = {''} + + # This is required because otherwise distlib creates scripts that are not + # executable. + # See https://bitbucket.org/pypa/distlib/issue/32/ + maker.set_mode = True + + # Generate the console and GUI entry points specified in the wheel + scripts_to_generate = get_console_script_specs(console) + + gui_scripts_to_generate = list(starmap('{} = {}'.format, gui.items())) + + generated_console_scripts = maker.make_multiple(scripts_to_generate) + generated.extend(generated_console_scripts) + + generated.extend( + maker.make_multiple(gui_scripts_to_generate, {'gui': True}) + ) + + if warn_script_location: + msg = message_about_scripts_not_on_PATH(generated_console_scripts) + if msg is not None: + logger.warning(msg) + + generated_file_mode = 0o666 & ~current_umask() + + @contextlib.contextmanager + def _generate_file(path, **kwargs): + # type: (str, **Any) -> Iterator[NamedTemporaryFileResult] + with adjacent_tmp_file(path, **kwargs) as f: + yield f + os.chmod(f.name, generated_file_mode) + replace(f.name, path) + + dest_info_dir = os.path.join(lib_dir, info_dir) + + # Record pip as the installer + installer_path = os.path.join(dest_info_dir, 'INSTALLER') + with _generate_file(installer_path) as installer_file: + installer_file.write(b'pip\n') + generated.append(installer_path) + + # Record the PEP 610 direct URL reference + if direct_url is not None: + direct_url_path = os.path.join(dest_info_dir, DIRECT_URL_METADATA_NAME) + with _generate_file(direct_url_path) as direct_url_file: + direct_url_file.write(direct_url.to_json().encode("utf-8")) + generated.append(direct_url_path) + + # Record the REQUESTED file + if requested: + requested_path = os.path.join(dest_info_dir, 'REQUESTED') + with open(requested_path, "w"): + pass + generated.append(requested_path) + + record_text = distribution.get_metadata('RECORD') + record_rows = list(csv.reader(record_text.splitlines())) + + rows = get_csv_rows_for_installed( + record_rows, + installed=installed, + changed=changed, + generated=generated, + lib_dir=lib_dir) + + # Record details of all files installed + record_path = os.path.join(dest_info_dir, 'RECORD') + + with _generate_file(record_path, **csv_io_kwargs('w')) as record_file: + # The type mypy infers for record_file is different for Python 3 + # (typing.IO[Any]) and Python 2 (typing.BinaryIO). We explicitly + # cast to typing.IO[str] as a workaround. + writer = csv.writer(cast('IO[str]', record_file)) + writer.writerows(_normalized_outrows(rows)) + + +@contextlib.contextmanager +def req_error_context(req_description): + # type: (str) -> Iterator[None] + try: + yield + except InstallationError as e: + message = "For req: {}. {}".format(req_description, e.args[0]) + reraise( + InstallationError, InstallationError(message), sys.exc_info()[2] + ) + + +def install_wheel( + name, # type: str + wheel_path, # type: str + scheme, # type: Scheme + req_description, # type: str + pycompile=True, # type: bool + warn_script_location=True, # type: bool + direct_url=None, # type: Optional[DirectUrl] + requested=False, # type: bool +): + # type: (...) -> None + with ZipFile(wheel_path, allowZip64=True) as z: + with req_error_context(req_description): + _install_wheel( + name=name, + wheel_zip=z, + wheel_path=wheel_path, + scheme=scheme, + pycompile=pycompile, + warn_script_location=warn_script_location, + direct_url=direct_url, + requested=requested, + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/prepare.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/prepare.py new file mode 100644 index 0000000..13b2c0b --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/operations/prepare.py @@ -0,0 +1,608 @@ +"""Prepares a distribution for installation +""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import logging +import mimetypes +import os +import shutil + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.six import PY2 + +from pip._internal.distributions import make_distribution_for_install_requirement +from pip._internal.distributions.installed import InstalledDistribution +from pip._internal.exceptions import ( + DirectoryUrlHashUnsupported, + HashMismatch, + HashUnpinned, + InstallationError, + NetworkConnectionError, + PreviousBuildDirError, + VcsHashUnsupported, +) +from pip._internal.models.wheel import Wheel +from pip._internal.network.download import BatchDownloader, Downloader +from pip._internal.network.lazy_wheel import ( + HTTPRangeRequestUnsupported, + dist_from_wheel_url, +) +from pip._internal.utils.filesystem import copy2_fixed +from pip._internal.utils.hashes import MissingHashes +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import display_path, hide_url, path_to_display, rmtree +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.unpacking import unpack_file +from pip._internal.vcs import vcs + +if MYPY_CHECK_RUNNING: + from typing import Callable, Dict, Iterable, List, Optional, Tuple + + from mypy_extensions import TypedDict + from pip._vendor.pkg_resources import Distribution + + from pip._internal.index.package_finder import PackageFinder + from pip._internal.models.link import Link + from pip._internal.network.session import PipSession + from pip._internal.req.req_install import InstallRequirement + from pip._internal.req.req_tracker import RequirementTracker + from pip._internal.utils.hashes import Hashes + + if PY2: + CopytreeKwargs = TypedDict( + 'CopytreeKwargs', + { + 'ignore': Callable[[str, List[str]], List[str]], + 'symlinks': bool, + }, + total=False, + ) + else: + CopytreeKwargs = TypedDict( + 'CopytreeKwargs', + { + 'copy_function': Callable[[str, str], None], + 'ignore': Callable[[str, List[str]], List[str]], + 'ignore_dangling_symlinks': bool, + 'symlinks': bool, + }, + total=False, + ) + +logger = logging.getLogger(__name__) + + +def _get_prepared_distribution( + req, # type: InstallRequirement + req_tracker, # type: RequirementTracker + finder, # type: PackageFinder + build_isolation, # type: bool +): + # type: (...) -> Distribution + """Prepare a distribution for installation.""" + abstract_dist = make_distribution_for_install_requirement(req) + with req_tracker.track(req): + abstract_dist.prepare_distribution_metadata(finder, build_isolation) + return abstract_dist.get_pkg_resources_distribution() + + +def unpack_vcs_link(link, location): + # type: (Link, str) -> None + vcs_backend = vcs.get_backend_for_scheme(link.scheme) + assert vcs_backend is not None + vcs_backend.unpack(location, url=hide_url(link.url)) + + +class File(object): + + def __init__(self, path, content_type): + # type: (str, Optional[str]) -> None + self.path = path + if content_type is None: + self.content_type = mimetypes.guess_type(path)[0] + else: + self.content_type = content_type + + +def get_http_url( + link, # type: Link + download, # type: Downloader + download_dir=None, # type: Optional[str] + hashes=None, # type: Optional[Hashes] +): + # type: (...) -> File + temp_dir = TempDirectory(kind="unpack", globally_managed=True) + # If a download dir is specified, is the file already downloaded there? + already_downloaded_path = None + if download_dir: + already_downloaded_path = _check_download_dir( + link, download_dir, hashes + ) + + if already_downloaded_path: + from_path = already_downloaded_path + content_type = None + else: + # let's download to a tmp dir + from_path, content_type = download(link, temp_dir.path) + if hashes: + hashes.check_against_path(from_path) + + return File(from_path, content_type) + + +def _copy2_ignoring_special_files(src, dest): + # type: (str, str) -> None + """Copying special files is not supported, but as a convenience to users + we skip errors copying them. This supports tools that may create e.g. + socket files in the project source directory. + """ + try: + copy2_fixed(src, dest) + except shutil.SpecialFileError as e: + # SpecialFileError may be raised due to either the source or + # destination. If the destination was the cause then we would actually + # care, but since the destination directory is deleted prior to + # copy we ignore all of them assuming it is caused by the source. + logger.warning( + "Ignoring special file error '%s' encountered copying %s to %s.", + str(e), + path_to_display(src), + path_to_display(dest), + ) + + +def _copy_source_tree(source, target): + # type: (str, str) -> None + target_abspath = os.path.abspath(target) + target_basename = os.path.basename(target_abspath) + target_dirname = os.path.dirname(target_abspath) + + def ignore(d, names): + # type: (str, List[str]) -> List[str] + skipped = [] # type: List[str] + if d == source: + # Pulling in those directories can potentially be very slow, + # exclude the following directories if they appear in the top + # level dir (and only it). + # See discussion at https://github.com/pypa/pip/pull/6770 + skipped += ['.tox', '.nox'] + if os.path.abspath(d) == target_dirname: + # Prevent an infinite recursion if the target is in source. + # This can happen when TMPDIR is set to ${PWD}/... + # and we copy PWD to TMPDIR. + skipped += [target_basename] + return skipped + + kwargs = dict(ignore=ignore, symlinks=True) # type: CopytreeKwargs + + if not PY2: + # Python 2 does not support copy_function, so we only ignore + # errors on special file copy in Python 3. + kwargs['copy_function'] = _copy2_ignoring_special_files + + shutil.copytree(source, target, **kwargs) + + +def get_file_url( + link, # type: Link + download_dir=None, # type: Optional[str] + hashes=None # type: Optional[Hashes] +): + # type: (...) -> File + """Get file and optionally check its hash. + """ + # If a download dir is specified, is the file already there and valid? + already_downloaded_path = None + if download_dir: + already_downloaded_path = _check_download_dir( + link, download_dir, hashes + ) + + if already_downloaded_path: + from_path = already_downloaded_path + else: + from_path = link.file_path + + # If --require-hashes is off, `hashes` is either empty, the + # link's embedded hash, or MissingHashes; it is required to + # match. If --require-hashes is on, we are satisfied by any + # hash in `hashes` matching: a URL-based or an option-based + # one; no internet-sourced hash will be in `hashes`. + if hashes: + hashes.check_against_path(from_path) + return File(from_path, None) + + +def unpack_url( + link, # type: Link + location, # type: str + download, # type: Downloader + download_dir=None, # type: Optional[str] + hashes=None, # type: Optional[Hashes] +): + # type: (...) -> Optional[File] + """Unpack link into location, downloading if required. + + :param hashes: A Hashes object, one of whose embedded hashes must match, + or HashMismatch will be raised. If the Hashes is empty, no matches are + required, and unhashable types of requirements (like VCS ones, which + would ordinarily raise HashUnsupported) are allowed. + """ + # non-editable vcs urls + if link.is_vcs: + unpack_vcs_link(link, location) + return None + + # If it's a url to a local directory + if link.is_existing_dir(): + if os.path.isdir(location): + rmtree(location) + _copy_source_tree(link.file_path, location) + return None + + # file urls + if link.is_file: + file = get_file_url(link, download_dir, hashes=hashes) + + # http urls + else: + file = get_http_url( + link, + download, + download_dir, + hashes=hashes, + ) + + # unpack the archive to the build dir location. even when only downloading + # archives, they have to be unpacked to parse dependencies, except wheels + if not link.is_wheel: + unpack_file(file.path, location, file.content_type) + + return file + + +def _check_download_dir(link, download_dir, hashes): + # type: (Link, str, Optional[Hashes]) -> Optional[str] + """ Check download_dir for previously downloaded file with correct hash + If a correct file is found return its path else None + """ + download_path = os.path.join(download_dir, link.filename) + + if not os.path.exists(download_path): + return None + + # If already downloaded, does its hash match? + logger.info('File was already downloaded %s', download_path) + if hashes: + try: + hashes.check_against_path(download_path) + except HashMismatch: + logger.warning( + 'Previously-downloaded file %s has bad hash. ' + 'Re-downloading.', + download_path + ) + os.unlink(download_path) + return None + return download_path + + +class RequirementPreparer(object): + """Prepares a Requirement + """ + + def __init__( + self, + build_dir, # type: str + download_dir, # type: Optional[str] + src_dir, # type: str + build_isolation, # type: bool + req_tracker, # type: RequirementTracker + session, # type: PipSession + progress_bar, # type: str + finder, # type: PackageFinder + require_hashes, # type: bool + use_user_site, # type: bool + lazy_wheel, # type: bool + ): + # type: (...) -> None + super(RequirementPreparer, self).__init__() + + self.src_dir = src_dir + self.build_dir = build_dir + self.req_tracker = req_tracker + self._session = session + self._download = Downloader(session, progress_bar) + self._batch_download = BatchDownloader(session, progress_bar) + self.finder = finder + + # Where still-packed archives should be written to. If None, they are + # not saved, and are deleted immediately after unpacking. + self.download_dir = download_dir + + # Is build isolation allowed? + self.build_isolation = build_isolation + + # Should hash-checking be required? + self.require_hashes = require_hashes + + # Should install in user site-packages? + self.use_user_site = use_user_site + + # Should wheels be downloaded lazily? + self.use_lazy_wheel = lazy_wheel + + # Memoized downloaded files, as mapping of url: (path, mime type) + self._downloaded = {} # type: Dict[str, Tuple[str, str]] + + # Previous "header" printed for a link-based InstallRequirement + self._previous_requirement_header = ("", "") + + def _log_preparing_link(self, req): + # type: (InstallRequirement) -> None + """Provide context for the requirement being prepared.""" + if req.link.is_file and not req.original_link_is_in_wheel_cache: + message = "Processing %s" + information = str(display_path(req.link.file_path)) + else: + message = "Collecting %s" + information = str(req.req or req) + + if (message, information) != self._previous_requirement_header: + self._previous_requirement_header = (message, information) + logger.info(message, information) + + if req.original_link_is_in_wheel_cache: + with indent_log(): + logger.info("Using cached %s", req.link.filename) + + def _ensure_link_req_src_dir(self, req, parallel_builds): + # type: (InstallRequirement, bool) -> None + """Ensure source_dir of a linked InstallRequirement.""" + # Since source_dir is only set for editable requirements. + if req.link.is_wheel: + # We don't need to unpack wheels, so no need for a source + # directory. + return + assert req.source_dir is None + # We always delete unpacked sdists after pip runs. + req.ensure_has_source_dir( + self.build_dir, + autodelete=True, + parallel_builds=parallel_builds, + ) + + # If a checkout exists, it's unwise to keep going. version + # inconsistencies are logged later, but do not fail the + # installation. + # FIXME: this won't upgrade when there's an existing + # package unpacked in `req.source_dir` + if os.path.exists(os.path.join(req.source_dir, 'setup.py')): + raise PreviousBuildDirError( + "pip can't proceed with requirements '{}' due to a" + "pre-existing build directory ({}). This is likely " + "due to a previous installation that failed . pip is " + "being responsible and not assuming it can delete this. " + "Please delete it and try again.".format(req, req.source_dir) + ) + + def _get_linked_req_hashes(self, req): + # type: (InstallRequirement) -> Hashes + # By the time this is called, the requirement's link should have + # been checked so we can tell what kind of requirements req is + # and raise some more informative errors than otherwise. + # (For example, we can raise VcsHashUnsupported for a VCS URL + # rather than HashMissing.) + if not self.require_hashes: + return req.hashes(trust_internet=True) + + # We could check these first 2 conditions inside unpack_url + # and save repetition of conditions, but then we would + # report less-useful error messages for unhashable + # requirements, complaining that there's no hash provided. + if req.link.is_vcs: + raise VcsHashUnsupported() + if req.link.is_existing_dir(): + raise DirectoryUrlHashUnsupported() + + # Unpinned packages are asking for trouble when a new version + # is uploaded. This isn't a security check, but it saves users + # a surprising hash mismatch in the future. + # file:/// URLs aren't pinnable, so don't complain about them + # not being pinned. + if req.original_link is None and not req.is_pinned: + raise HashUnpinned() + + # If known-good hashes are missing for this requirement, + # shim it with a facade object that will provoke hash + # computation and then raise a HashMissing exception + # showing the user what the hash should be. + return req.hashes(trust_internet=False) or MissingHashes() + + def _fetch_metadata_using_lazy_wheel(self, link): + # type: (Link) -> Optional[Distribution] + """Fetch metadata using lazy wheel, if possible.""" + if not self.use_lazy_wheel: + return None + if self.require_hashes: + logger.debug('Lazy wheel is not used as hash checking is required') + return None + if link.is_file or not link.is_wheel: + logger.debug( + 'Lazy wheel is not used as ' + '%r does not points to a remote wheel', + link, + ) + return None + + wheel = Wheel(link.filename) + name = canonicalize_name(wheel.name) + logger.info( + 'Obtaining dependency information from %s %s', + name, wheel.version, + ) + url = link.url.split('#', 1)[0] + try: + return dist_from_wheel_url(name, url, self._session) + except HTTPRangeRequestUnsupported: + logger.debug('%s does not support range requests', url) + return None + + def prepare_linked_requirement(self, req, parallel_builds=False): + # type: (InstallRequirement, bool) -> Distribution + """Prepare a requirement to be obtained from req.link.""" + assert req.link + link = req.link + self._log_preparing_link(req) + with indent_log(): + # Check if the relevant file is already available + # in the download directory + file_path = None + if self.download_dir is not None and link.is_wheel: + hashes = self._get_linked_req_hashes(req) + file_path = _check_download_dir(req.link, self.download_dir, hashes) + + if file_path is not None: + # The file is already available, so mark it as downloaded + self._downloaded[req.link.url] = file_path, None + else: + # The file is not available, attempt to fetch only metadata + wheel_dist = self._fetch_metadata_using_lazy_wheel(link) + if wheel_dist is not None: + req.needs_more_preparation = True + return wheel_dist + + # None of the optimizations worked, fully prepare the requirement + return self._prepare_linked_requirement(req, parallel_builds) + + def prepare_linked_requirements_more(self, reqs, parallel_builds=False): + # type: (Iterable[InstallRequirement], bool) -> None + """Prepare a linked requirement more, if needed.""" + reqs = [req for req in reqs if req.needs_more_preparation] + links = [req.link for req in reqs] + + # Let's download to a temporary directory. + tmpdir = TempDirectory(kind="unpack", globally_managed=True).path + self._downloaded.update(self._batch_download(links, tmpdir)) + for req in reqs: + self._prepare_linked_requirement(req, parallel_builds) + + def _prepare_linked_requirement(self, req, parallel_builds): + # type: (InstallRequirement, bool) -> Distribution + assert req.link + link = req.link + + self._ensure_link_req_src_dir(req, parallel_builds) + hashes = self._get_linked_req_hashes(req) + if link.url not in self._downloaded: + try: + local_file = unpack_url( + link, req.source_dir, self._download, + self.download_dir, hashes, + ) + except NetworkConnectionError as exc: + raise InstallationError( + 'Could not install requirement {} because of HTTP ' + 'error {} for URL {}'.format(req, exc, link) + ) + else: + file_path, content_type = self._downloaded[link.url] + if hashes: + hashes.check_against_path(file_path) + local_file = File(file_path, content_type) + + # For use in later processing, + # preserve the file path on the requirement. + if local_file: + req.local_file_path = local_file.path + + dist = _get_prepared_distribution( + req, self.req_tracker, self.finder, self.build_isolation, + ) + return dist + + def save_linked_requirement(self, req): + # type: (InstallRequirement) -> None + assert self.download_dir is not None + assert req.link is not None + link = req.link + if link.is_vcs or (link.is_existing_dir() and req.editable): + # Make a .zip of the source_dir we already created. + req.archive(self.download_dir) + return + + if link.is_existing_dir(): + logger.debug( + 'Not copying link to destination directory ' + 'since it is a directory: %s', link, + ) + return + if req.local_file_path is None: + # No distribution was downloaded for this requirement. + return + + download_location = os.path.join(self.download_dir, link.filename) + if not os.path.exists(download_location): + shutil.copy(req.local_file_path, download_location) + download_path = display_path(download_location) + logger.info('Saved %s', download_path) + + def prepare_editable_requirement( + self, + req, # type: InstallRequirement + ): + # type: (...) -> Distribution + """Prepare an editable requirement + """ + assert req.editable, "cannot prepare a non-editable req as editable" + + logger.info('Obtaining %s', req) + + with indent_log(): + if self.require_hashes: + raise InstallationError( + 'The editable requirement {} cannot be installed when ' + 'requiring hashes, because there is no single file to ' + 'hash.'.format(req) + ) + req.ensure_has_source_dir(self.src_dir) + req.update_editable(self.download_dir is None) + + dist = _get_prepared_distribution( + req, self.req_tracker, self.finder, self.build_isolation, + ) + + req.check_if_exists(self.use_user_site) + + return dist + + def prepare_installed_requirement( + self, + req, # type: InstallRequirement + skip_reason # type: str + ): + # type: (...) -> Distribution + """Prepare an already-installed requirement + """ + assert req.satisfied_by, "req should have been satisfied but isn't" + assert skip_reason is not None, ( + "did not get skip reason skipped but req.satisfied_by " + "is set to {}".format(req.satisfied_by) + ) + logger.info( + 'Requirement %s: %s (%s)', + skip_reason, req, req.satisfied_by.version + ) + with indent_log(): + if self.require_hashes: + logger.debug( + 'Since it is already installed, we are trusting this ' + 'package without checking its hash. To ensure a ' + 'completely repeatable environment, install into an ' + 'empty virtualenv.' + ) + return InstalledDistribution(req).get_pkg_resources_distribution() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/pyproject.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/pyproject.py new file mode 100644 index 0000000..4144a9e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/pyproject.py @@ -0,0 +1,196 @@ +from __future__ import absolute_import + +import io +import os +import sys +from collections import namedtuple + +from pip._vendor import six, toml +from pip._vendor.packaging.requirements import InvalidRequirement, Requirement + +from pip._internal.exceptions import InstallationError +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, List, Optional + + +def _is_list_of_str(obj): + # type: (Any) -> bool + return ( + isinstance(obj, list) and + all(isinstance(item, six.string_types) for item in obj) + ) + + +def make_pyproject_path(unpacked_source_directory): + # type: (str) -> str + path = os.path.join(unpacked_source_directory, 'pyproject.toml') + + # Python2 __file__ should not be unicode + if six.PY2 and isinstance(path, six.text_type): + path = path.encode(sys.getfilesystemencoding()) + + return path + + +BuildSystemDetails = namedtuple('BuildSystemDetails', [ + 'requires', 'backend', 'check', 'backend_path' +]) + + +def load_pyproject_toml( + use_pep517, # type: Optional[bool] + pyproject_toml, # type: str + setup_py, # type: str + req_name # type: str +): + # type: (...) -> Optional[BuildSystemDetails] + """Load the pyproject.toml file. + + Parameters: + use_pep517 - Has the user requested PEP 517 processing? None + means the user hasn't explicitly specified. + pyproject_toml - Location of the project's pyproject.toml file + setup_py - Location of the project's setup.py file + req_name - The name of the requirement we're processing (for + error reporting) + + Returns: + None if we should use the legacy code path, otherwise a tuple + ( + requirements from pyproject.toml, + name of PEP 517 backend, + requirements we should check are installed after setting + up the build environment + directory paths to import the backend from (backend-path), + relative to the project root. + ) + """ + has_pyproject = os.path.isfile(pyproject_toml) + has_setup = os.path.isfile(setup_py) + + if has_pyproject: + with io.open(pyproject_toml, encoding="utf-8") as f: + pp_toml = toml.load(f) + build_system = pp_toml.get("build-system") + else: + build_system = None + + # The following cases must use PEP 517 + # We check for use_pep517 being non-None and falsey because that means + # the user explicitly requested --no-use-pep517. The value 0 as + # opposed to False can occur when the value is provided via an + # environment variable or config file option (due to the quirk of + # strtobool() returning an integer in pip's configuration code). + if has_pyproject and not has_setup: + if use_pep517 is not None and not use_pep517: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project does not have a setup.py" + ) + use_pep517 = True + elif build_system and "build-backend" in build_system: + if use_pep517 is not None and not use_pep517: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project specifies a build backend of {} " + "in pyproject.toml".format( + build_system["build-backend"] + ) + ) + use_pep517 = True + + # If we haven't worked out whether to use PEP 517 yet, + # and the user hasn't explicitly stated a preference, + # we do so if the project has a pyproject.toml file. + elif use_pep517 is None: + use_pep517 = has_pyproject + + # At this point, we know whether we're going to use PEP 517. + assert use_pep517 is not None + + # If we're using the legacy code path, there is nothing further + # for us to do here. + if not use_pep517: + return None + + if build_system is None: + # Either the user has a pyproject.toml with no build-system + # section, or the user has no pyproject.toml, but has opted in + # explicitly via --use-pep517. + # In the absence of any explicit backend specification, we + # assume the setuptools backend that most closely emulates the + # traditional direct setup.py execution, and require wheel and + # a version of setuptools that supports that backend. + + build_system = { + "requires": ["setuptools>=40.8.0", "wheel"], + "build-backend": "setuptools.build_meta:__legacy__", + } + + # If we're using PEP 517, we have build system information (either + # from pyproject.toml, or defaulted by the code above). + # Note that at this point, we do not know if the user has actually + # specified a backend, though. + assert build_system is not None + + # Ensure that the build-system section in pyproject.toml conforms + # to PEP 518. + error_template = ( + "{package} has a pyproject.toml file that does not comply " + "with PEP 518: {reason}" + ) + + # Specifying the build-system table but not the requires key is invalid + if "requires" not in build_system: + raise InstallationError( + error_template.format(package=req_name, reason=( + "it has a 'build-system' table but not " + "'build-system.requires' which is mandatory in the table" + )) + ) + + # Error out if requires is not a list of strings + requires = build_system["requires"] + if not _is_list_of_str(requires): + raise InstallationError(error_template.format( + package=req_name, + reason="'build-system.requires' is not a list of strings.", + )) + + # Each requirement must be valid as per PEP 508 + for requirement in requires: + try: + Requirement(requirement) + except InvalidRequirement: + raise InstallationError( + error_template.format( + package=req_name, + reason=( + "'build-system.requires' contains an invalid " + "requirement: {!r}".format(requirement) + ), + ) + ) + + backend = build_system.get("build-backend") + backend_path = build_system.get("backend-path", []) + check = [] # type: List[str] + if backend is None: + # If the user didn't specify a backend, we assume they want to use + # the setuptools backend. But we can't be sure they have included + # a version of setuptools which supplies the backend, or wheel + # (which is needed by the backend) in their requirements. So we + # make a note to check that those requirements are present once + # we have set up the environment. + # This is quite a lot of work to check for a very specific case. But + # the problem is, that case is potentially quite common - projects that + # adopted PEP 518 early for the ability to specify requirements to + # execute setup.py, but never considered needing to mention the build + # tools themselves. The original PEP 518 code had a similar check (but + # implemented in a different way). + backend = "setuptools.build_meta:__legacy__" + check = ["setuptools>=40.8.0", "wheel"] + + return BuildSystemDetails(requires, backend, check, backend_path) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__init__.py new file mode 100644 index 0000000..8568d3f --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__init__.py @@ -0,0 +1,103 @@ +from __future__ import absolute_import + +import collections +import logging + +from pip._internal.utils.logging import indent_log +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +from .req_file import parse_requirements +from .req_install import InstallRequirement +from .req_set import RequirementSet + +if MYPY_CHECK_RUNNING: + from typing import Iterator, List, Optional, Sequence, Tuple + +__all__ = [ + "RequirementSet", "InstallRequirement", + "parse_requirements", "install_given_reqs", +] + +logger = logging.getLogger(__name__) + + +class InstallationResult(object): + def __init__(self, name): + # type: (str) -> None + self.name = name + + def __repr__(self): + # type: () -> str + return "InstallationResult(name={!r})".format(self.name) + + +def _validate_requirements( + requirements, # type: List[InstallRequirement] +): + # type: (...) -> Iterator[Tuple[str, InstallRequirement]] + for req in requirements: + assert req.name, "invalid to-be-installed requirement: {}".format(req) + yield req.name, req + + +def install_given_reqs( + requirements, # type: List[InstallRequirement] + install_options, # type: List[str] + global_options, # type: Sequence[str] + root, # type: Optional[str] + home, # type: Optional[str] + prefix, # type: Optional[str] + warn_script_location, # type: bool + use_user_site, # type: bool + pycompile, # type: bool +): + # type: (...) -> List[InstallationResult] + """ + Install everything in the given list. + + (to be called after having downloaded and unpacked the packages) + """ + to_install = collections.OrderedDict(_validate_requirements(requirements)) + + if to_install: + logger.info( + 'Installing collected packages: %s', + ', '.join(to_install.keys()), + ) + + installed = [] + + with indent_log(): + for req_name, requirement in to_install.items(): + if requirement.should_reinstall: + logger.info('Attempting uninstall: %s', req_name) + with indent_log(): + uninstalled_pathset = requirement.uninstall( + auto_confirm=True + ) + else: + uninstalled_pathset = None + + try: + requirement.install( + install_options, + global_options, + root=root, + home=home, + prefix=prefix, + warn_script_location=warn_script_location, + use_user_site=use_user_site, + pycompile=pycompile, + ) + except Exception: + # if install did not succeed, rollback previous uninstall + if uninstalled_pathset and not requirement.install_succeeded: + uninstalled_pathset.rollback() + raise + else: + if uninstalled_pathset and requirement.install_succeeded: + uninstalled_pathset.commit() + + installed.append(InstallationResult(req_name)) + + return installed diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0a9c256ec00486e331ed4087720b8cbf43bf316 GIT binary patch literal 2525 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__pycache__/req_file.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/__pycache__/req_file.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..38caa5e60c490dbd88f9e3264963eb1f1f6a8425 GIT binary patch literal 12741 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

)i@*a4fmENT_)`PvWh%K?jliD#f-Pah6jN^@ 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 xZ#4L4ecFydiIT4&tP%(P~{ZG799{J-W7wCn%? literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/constructors.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/constructors.py new file mode 100644 index 0000000..2245cb8 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/constructors.py @@ -0,0 +1,476 @@ +"""Backing implementation for InstallRequirement's various constructors + +The idea here is that these formed a major chunk of InstallRequirement's size +so, moving them and support code dedicated to them outside of that class +helps creates for better understandability for the rest of the code. + +These are meant to be used elsewhere within pip to create instances of +InstallRequirement. +""" + +import logging +import os +import re + +from pip._vendor.packaging.markers import Marker +from pip._vendor.packaging.requirements import InvalidRequirement, Requirement +from pip._vendor.packaging.specifiers import Specifier +from pip._vendor.pkg_resources import RequirementParseError, parse_requirements + +from pip._internal.exceptions import InstallationError +from pip._internal.models.index import PyPI, TestPyPI +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.pyproject import make_pyproject_path +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.filetypes import is_archive_file +from pip._internal.utils.misc import is_installable_dir +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.urls import path_to_url +from pip._internal.vcs import is_url, vcs + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, Optional, Set, Tuple, Union + + from pip._internal.req.req_file import ParsedRequirement + + +__all__ = [ + "install_req_from_editable", "install_req_from_line", + "parse_editable" +] + +logger = logging.getLogger(__name__) +operators = Specifier._operators.keys() + + +def _strip_extras(path): + # type: (str) -> Tuple[str, Optional[str]] + m = re.match(r'^(.+)(\[[^\]]+\])$', path) + extras = None + if m: + path_no_extras = m.group(1) + extras = m.group(2) + else: + path_no_extras = path + + return path_no_extras, extras + + +def convert_extras(extras): + # type: (Optional[str]) -> Set[str] + if not extras: + return set() + return Requirement("placeholder" + extras.lower()).extras + + +def parse_editable(editable_req): + # type: (str) -> Tuple[Optional[str], str, Set[str]] + """Parses an editable requirement into: + - a requirement name + - an URL + - extras + - editable options + Accepted requirements: + svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir + .[some_extra] + """ + + url = editable_req + + # If a file path is specified with extras, strip off the extras. + url_no_extras, extras = _strip_extras(url) + + if os.path.isdir(url_no_extras): + if not os.path.exists(os.path.join(url_no_extras, 'setup.py')): + msg = ( + 'File "setup.py" not found. Directory cannot be installed ' + 'in editable mode: {}'.format(os.path.abspath(url_no_extras)) + ) + pyproject_path = make_pyproject_path(url_no_extras) + if os.path.isfile(pyproject_path): + msg += ( + '\n(A "pyproject.toml" file was found, but editable ' + 'mode currently requires a setup.py based build.)' + ) + raise InstallationError(msg) + + # Treating it as code that has already been checked out + url_no_extras = path_to_url(url_no_extras) + + if url_no_extras.lower().startswith('file:'): + package_name = Link(url_no_extras).egg_fragment + if extras: + return ( + package_name, + url_no_extras, + Requirement("placeholder" + extras.lower()).extras, + ) + else: + return package_name, url_no_extras, set() + + for version_control in vcs: + if url.lower().startswith('{}:'.format(version_control)): + url = '{}+{}'.format(version_control, url) + break + + if '+' not in url: + raise InstallationError( + '{} is not a valid editable requirement. ' + 'It should either be a path to a local project or a VCS URL ' + '(beginning with svn+, git+, hg+, or bzr+).'.format(editable_req) + ) + + vc_type = url.split('+', 1)[0].lower() + + if not vcs.get_backend(vc_type): + backends = ", ".join([bends.name + '+URL' for bends in vcs.backends]) + error_message = "For --editable={}, " \ + "only {} are currently supported".format( + editable_req, backends) + raise InstallationError(error_message) + + package_name = Link(url).egg_fragment + if not package_name: + raise InstallationError( + "Could not detect requirement name for '{}', please specify one " + "with #egg=your_package_name".format(editable_req) + ) + return package_name, url, set() + + +def deduce_helpful_msg(req): + # type: (str) -> str + """Returns helpful msg in case requirements file does not exist, + or cannot be parsed. + + :params req: Requirements file path + """ + msg = "" + if os.path.exists(req): + msg = " The path does exist. " + # Try to parse and check if it is a requirements file. + try: + with open(req, 'r') as fp: + # parse first line only + next(parse_requirements(fp.read())) + msg += ( + "The argument you provided " + "({}) appears to be a" + " requirements file. If that is the" + " case, use the '-r' flag to install" + " the packages specified within it." + ).format(req) + except RequirementParseError: + logger.debug( + "Cannot parse '%s' as requirements file", req, exc_info=True + ) + else: + msg += " File '{}' does not exist.".format(req) + return msg + + +class RequirementParts(object): + def __init__( + self, + requirement, # type: Optional[Requirement] + link, # type: Optional[Link] + markers, # type: Optional[Marker] + extras, # type: Set[str] + ): + self.requirement = requirement + self.link = link + self.markers = markers + self.extras = extras + + +def parse_req_from_editable(editable_req): + # type: (str) -> RequirementParts + name, url, extras_override = parse_editable(editable_req) + + if name is not None: + try: + req = Requirement(name) + except InvalidRequirement: + raise InstallationError("Invalid requirement: '{}'".format(name)) + else: + req = None + + link = Link(url) + + return RequirementParts(req, link, None, extras_override) + + +# ---- The actual constructors follow ---- + + +def install_req_from_editable( + editable_req, # type: str + comes_from=None, # type: Optional[Union[InstallRequirement, str]] + use_pep517=None, # type: Optional[bool] + isolated=False, # type: bool + options=None, # type: Optional[Dict[str, Any]] + constraint=False, # type: bool + user_supplied=False, # type: bool +): + # type: (...) -> InstallRequirement + + parts = parse_req_from_editable(editable_req) + + return InstallRequirement( + parts.requirement, + comes_from=comes_from, + user_supplied=user_supplied, + editable=True, + link=parts.link, + constraint=constraint, + use_pep517=use_pep517, + isolated=isolated, + install_options=options.get("install_options", []) if options else [], + global_options=options.get("global_options", []) if options else [], + hash_options=options.get("hashes", {}) if options else {}, + extras=parts.extras, + ) + + +def _looks_like_path(name): + # type: (str) -> bool + """Checks whether the string "looks like" a path on the filesystem. + + This does not check whether the target actually exists, only judge from the + appearance. + + Returns true if any of the following conditions is true: + * a path separator is found (either os.path.sep or os.path.altsep); + * a dot is found (which represents the current directory). + """ + if os.path.sep in name: + return True + if os.path.altsep is not None and os.path.altsep in name: + return True + if name.startswith("."): + return True + return False + + +def _get_url_from_path(path, name): + # type: (str, str) -> Optional[str] + """ + First, it checks whether a provided path is an installable directory + (e.g. it has a setup.py). If it is, returns the path. + + If false, check if the path is an archive file (such as a .whl). + The function checks if the path is a file. If false, if the path has + an @, it will treat it as a PEP 440 URL requirement and return the path. + """ + if _looks_like_path(name) and os.path.isdir(path): + if is_installable_dir(path): + return path_to_url(path) + raise InstallationError( + "Directory {name!r} is not installable. Neither 'setup.py' " + "nor 'pyproject.toml' found.".format(**locals()) + ) + if not is_archive_file(path): + return None + if os.path.isfile(path): + return path_to_url(path) + urlreq_parts = name.split('@', 1) + if len(urlreq_parts) >= 2 and not _looks_like_path(urlreq_parts[0]): + # If the path contains '@' and the part before it does not look + # like a path, try to treat it as a PEP 440 URL req instead. + return None + logger.warning( + 'Requirement %r looks like a filename, but the ' + 'file does not exist', + name + ) + return path_to_url(path) + + +def parse_req_from_line(name, line_source): + # type: (str, Optional[str]) -> RequirementParts + if is_url(name): + marker_sep = '; ' + else: + marker_sep = ';' + if marker_sep in name: + name, markers_as_string = name.split(marker_sep, 1) + markers_as_string = markers_as_string.strip() + if not markers_as_string: + markers = None + else: + markers = Marker(markers_as_string) + else: + markers = None + name = name.strip() + req_as_string = None + path = os.path.normpath(os.path.abspath(name)) + link = None + extras_as_string = None + + if is_url(name): + link = Link(name) + else: + p, extras_as_string = _strip_extras(path) + url = _get_url_from_path(p, name) + if url is not None: + link = Link(url) + + # it's a local file, dir, or url + if link: + # Handle relative file URLs + if link.scheme == 'file' and re.search(r'\.\./', link.url): + link = Link( + path_to_url(os.path.normpath(os.path.abspath(link.path)))) + # wheel file + if link.is_wheel: + wheel = Wheel(link.filename) # can raise InvalidWheelFilename + req_as_string = "{wheel.name}=={wheel.version}".format(**locals()) + else: + # set the req to the egg fragment. when it's not there, this + # will become an 'unnamed' requirement + req_as_string = link.egg_fragment + + # a requirement specifier + else: + req_as_string = name + + extras = convert_extras(extras_as_string) + + def with_source(text): + # type: (str) -> str + if not line_source: + return text + return '{} (from {})'.format(text, line_source) + + if req_as_string is not None: + try: + req = Requirement(req_as_string) + except InvalidRequirement: + if os.path.sep in req_as_string: + add_msg = "It looks like a path." + add_msg += deduce_helpful_msg(req_as_string) + elif ('=' in req_as_string and + not any(op in req_as_string for op in operators)): + add_msg = "= is not a valid operator. Did you mean == ?" + else: + add_msg = '' + msg = with_source( + 'Invalid requirement: {!r}'.format(req_as_string) + ) + if add_msg: + msg += '\nHint: {}'.format(add_msg) + raise InstallationError(msg) + else: + # Deprecate extras after specifiers: "name>=1.0[extras]" + # This currently works by accident because _strip_extras() parses + # any extras in the end of the string and those are saved in + # RequirementParts + for spec in req.specifier: + spec_str = str(spec) + if spec_str.endswith(']'): + msg = "Extras after version '{}'.".format(spec_str) + replace = "moving the extras before version specifiers" + deprecated(msg, replacement=replace, gone_in="21.0") + else: + req = None + + return RequirementParts(req, link, markers, extras) + + +def install_req_from_line( + name, # type: str + comes_from=None, # type: Optional[Union[str, InstallRequirement]] + use_pep517=None, # type: Optional[bool] + isolated=False, # type: bool + options=None, # type: Optional[Dict[str, Any]] + constraint=False, # type: bool + line_source=None, # type: Optional[str] + user_supplied=False, # type: bool +): + # type: (...) -> InstallRequirement + """Creates an InstallRequirement from a name, which might be a + requirement, directory containing 'setup.py', filename, or URL. + + :param line_source: An optional string describing where the line is from, + for logging purposes in case of an error. + """ + parts = parse_req_from_line(name, line_source) + + return InstallRequirement( + parts.requirement, comes_from, link=parts.link, markers=parts.markers, + use_pep517=use_pep517, isolated=isolated, + install_options=options.get("install_options", []) if options else [], + global_options=options.get("global_options", []) if options else [], + hash_options=options.get("hashes", {}) if options else {}, + constraint=constraint, + extras=parts.extras, + user_supplied=user_supplied, + ) + + +def install_req_from_req_string( + req_string, # type: str + comes_from=None, # type: Optional[InstallRequirement] + isolated=False, # type: bool + use_pep517=None, # type: Optional[bool] + user_supplied=False, # type: bool +): + # type: (...) -> InstallRequirement + try: + req = Requirement(req_string) + except InvalidRequirement: + raise InstallationError("Invalid requirement: '{}'".format(req_string)) + + domains_not_allowed = [ + PyPI.file_storage_domain, + TestPyPI.file_storage_domain, + ] + if (req.url and comes_from and comes_from.link and + comes_from.link.netloc in domains_not_allowed): + # Explicitly disallow pypi packages that depend on external urls + raise InstallationError( + "Packages installed from PyPI cannot depend on packages " + "which are not also hosted on PyPI.\n" + "{} depends on {} ".format(comes_from.name, req) + ) + + return InstallRequirement( + req, + comes_from, + isolated=isolated, + use_pep517=use_pep517, + user_supplied=user_supplied, + ) + + +def install_req_from_parsed_requirement( + parsed_req, # type: ParsedRequirement + isolated=False, # type: bool + use_pep517=None, # type: Optional[bool] + user_supplied=False, # type: bool +): + # type: (...) -> InstallRequirement + if parsed_req.is_editable: + req = install_req_from_editable( + parsed_req.requirement, + comes_from=parsed_req.comes_from, + use_pep517=use_pep517, + constraint=parsed_req.constraint, + isolated=isolated, + user_supplied=user_supplied, + ) + + else: + req = install_req_from_line( + parsed_req.requirement, + comes_from=parsed_req.comes_from, + use_pep517=use_pep517, + isolated=isolated, + options=parsed_req.options, + constraint=parsed_req.constraint, + line_source=parsed_req.line_source, + user_supplied=user_supplied, + ) + return req diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_file.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_file.py new file mode 100644 index 0000000..0af60fa --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_file.py @@ -0,0 +1,574 @@ +""" +Requirements file parsing +""" + +from __future__ import absolute_import + +import optparse +import os +import re +import shlex +import sys + +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.cli import cmdoptions +from pip._internal.exceptions import InstallationError, RequirementsFileParseError +from pip._internal.models.search_scope import SearchScope +from pip._internal.network.utils import raise_for_status +from pip._internal.utils.encoding import auto_decode +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.urls import get_url_scheme, url_to_path + +if MYPY_CHECK_RUNNING: + from optparse import Values + from typing import ( + Any, + Callable, + Dict, + Iterator, + List, + NoReturn, + Optional, + Text, + Tuple, + ) + + from pip._internal.index.package_finder import PackageFinder + from pip._internal.network.session import PipSession + + ReqFileLines = Iterator[Tuple[int, Text]] + + LineParser = Callable[[Text], Tuple[str, Values]] + + +__all__ = ['parse_requirements'] + +SCHEME_RE = re.compile(r'^(http|https|file):', re.I) +COMMENT_RE = re.compile(r'(^|\s+)#.*$') + +# Matches environment variable-style values in '${MY_VARIABLE_1}' with the +# variable name consisting of only uppercase letters, digits or the '_' +# (underscore). This follows the POSIX standard defined in IEEE Std 1003.1, +# 2013 Edition. +ENV_VAR_RE = re.compile(r'(?P\$\{(?P[A-Z0-9_]+)\})') + +SUPPORTED_OPTIONS = [ + cmdoptions.index_url, + cmdoptions.extra_index_url, + cmdoptions.no_index, + cmdoptions.constraints, + cmdoptions.requirements, + cmdoptions.editable, + cmdoptions.find_links, + cmdoptions.no_binary, + cmdoptions.only_binary, + cmdoptions.prefer_binary, + cmdoptions.require_hashes, + cmdoptions.pre, + cmdoptions.trusted_host, + cmdoptions.use_new_feature, +] # type: List[Callable[..., optparse.Option]] + +# options to be passed to requirements +SUPPORTED_OPTIONS_REQ = [ + cmdoptions.install_options, + cmdoptions.global_options, + cmdoptions.hash, +] # type: List[Callable[..., optparse.Option]] + +# the 'dest' string values +SUPPORTED_OPTIONS_REQ_DEST = [str(o().dest) for o in SUPPORTED_OPTIONS_REQ] + + +class ParsedRequirement(object): + def __init__( + self, + requirement, # type:str + is_editable, # type: bool + comes_from, # type: str + constraint, # type: bool + options=None, # type: Optional[Dict[str, Any]] + line_source=None, # type: Optional[str] + ): + # type: (...) -> None + self.requirement = requirement + self.is_editable = is_editable + self.comes_from = comes_from + self.options = options + self.constraint = constraint + self.line_source = line_source + + +class ParsedLine(object): + def __init__( + self, + filename, # type: str + lineno, # type: int + args, # type: str + opts, # type: Values + constraint, # type: bool + ): + # type: (...) -> None + self.filename = filename + self.lineno = lineno + self.opts = opts + self.constraint = constraint + + if args: + self.is_requirement = True + self.is_editable = False + self.requirement = args + elif opts.editables: + self.is_requirement = True + self.is_editable = True + # We don't support multiple -e on one line + self.requirement = opts.editables[0] + else: + self.is_requirement = False + + +def parse_requirements( + filename, # type: str + session, # type: PipSession + finder=None, # type: Optional[PackageFinder] + options=None, # type: Optional[optparse.Values] + constraint=False, # type: bool +): + # type: (...) -> Iterator[ParsedRequirement] + """Parse a requirements file and yield ParsedRequirement instances. + + :param filename: Path or url of requirements file. + :param session: PipSession instance. + :param finder: Instance of pip.index.PackageFinder. + :param options: cli options. + :param constraint: If true, parsing a constraint file rather than + requirements file. + """ + line_parser = get_line_parser(finder) + parser = RequirementsFileParser(session, line_parser) + + for parsed_line in parser.parse(filename, constraint): + parsed_req = handle_line( + parsed_line, + options=options, + finder=finder, + session=session + ) + if parsed_req is not None: + yield parsed_req + + +def preprocess(content): + # type: (Text) -> ReqFileLines + """Split, filter, and join lines, and return a line iterator + + :param content: the content of the requirements file + """ + lines_enum = enumerate(content.splitlines(), start=1) # type: ReqFileLines + lines_enum = join_lines(lines_enum) + lines_enum = ignore_comments(lines_enum) + lines_enum = expand_env_variables(lines_enum) + return lines_enum + + +def handle_requirement_line( + line, # type: ParsedLine + options=None, # type: Optional[optparse.Values] +): + # type: (...) -> ParsedRequirement + + # preserve for the nested code path + line_comes_from = '{} {} (line {})'.format( + '-c' if line.constraint else '-r', line.filename, line.lineno, + ) + + assert line.is_requirement + + if line.is_editable: + # For editable requirements, we don't support per-requirement + # options, so just return the parsed requirement. + return ParsedRequirement( + requirement=line.requirement, + is_editable=line.is_editable, + comes_from=line_comes_from, + constraint=line.constraint, + ) + else: + if options: + # Disable wheels if the user has specified build options + cmdoptions.check_install_build_global(options, line.opts) + + # get the options that apply to requirements + req_options = {} + for dest in SUPPORTED_OPTIONS_REQ_DEST: + if dest in line.opts.__dict__ and line.opts.__dict__[dest]: + req_options[dest] = line.opts.__dict__[dest] + + line_source = 'line {} of {}'.format(line.lineno, line.filename) + return ParsedRequirement( + requirement=line.requirement, + is_editable=line.is_editable, + comes_from=line_comes_from, + constraint=line.constraint, + options=req_options, + line_source=line_source, + ) + + +def handle_option_line( + opts, # type: Values + filename, # type: str + lineno, # type: int + finder=None, # type: Optional[PackageFinder] + options=None, # type: Optional[optparse.Values] + session=None, # type: Optional[PipSession] +): + # type: (...) -> None + + if options: + # percolate options upward + if opts.require_hashes: + options.require_hashes = opts.require_hashes + if opts.features_enabled: + options.features_enabled.extend( + f for f in opts.features_enabled + if f not in options.features_enabled + ) + + # set finder options + if finder: + find_links = finder.find_links + index_urls = finder.index_urls + if opts.index_url: + index_urls = [opts.index_url] + if opts.no_index is True: + index_urls = [] + if opts.extra_index_urls: + index_urls.extend(opts.extra_index_urls) + if opts.find_links: + # FIXME: it would be nice to keep track of the source + # of the find_links: support a find-links local path + # relative to a requirements file. + value = opts.find_links[0] + req_dir = os.path.dirname(os.path.abspath(filename)) + relative_to_reqs_file = os.path.join(req_dir, value) + if os.path.exists(relative_to_reqs_file): + value = relative_to_reqs_file + find_links.append(value) + + if session: + # We need to update the auth urls in session + session.update_index_urls(index_urls) + + search_scope = SearchScope( + find_links=find_links, + index_urls=index_urls, + ) + finder.search_scope = search_scope + + if opts.pre: + finder.set_allow_all_prereleases() + + if opts.prefer_binary: + finder.set_prefer_binary() + + if session: + for host in opts.trusted_hosts or []: + source = 'line {} of {}'.format(lineno, filename) + session.add_trusted_host(host, source=source) + + +def handle_line( + line, # type: ParsedLine + options=None, # type: Optional[optparse.Values] + finder=None, # type: Optional[PackageFinder] + session=None, # type: Optional[PipSession] +): + # type: (...) -> Optional[ParsedRequirement] + """Handle a single parsed requirements line; This can result in + creating/yielding requirements, or updating the finder. + + :param line: The parsed line to be processed. + :param options: CLI options. + :param finder: The finder - updated by non-requirement lines. + :param session: The session - updated by non-requirement lines. + + Returns a ParsedRequirement object if the line is a requirement line, + otherwise returns None. + + For lines that contain requirements, the only options that have an effect + are from SUPPORTED_OPTIONS_REQ, and they are scoped to the + requirement. Other options from SUPPORTED_OPTIONS may be present, but are + ignored. + + For lines that do not contain requirements, the only options that have an + effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may + be present, but are ignored. These lines may contain multiple options + (although our docs imply only one is supported), and all our parsed and + affect the finder. + """ + + if line.is_requirement: + parsed_req = handle_requirement_line(line, options) + return parsed_req + else: + handle_option_line( + line.opts, + line.filename, + line.lineno, + finder, + options, + session, + ) + return None + + +class RequirementsFileParser(object): + def __init__( + self, + session, # type: PipSession + line_parser, # type: LineParser + ): + # type: (...) -> None + self._session = session + self._line_parser = line_parser + + def parse(self, filename, constraint): + # type: (str, bool) -> Iterator[ParsedLine] + """Parse a given file, yielding parsed lines. + """ + for line in self._parse_and_recurse(filename, constraint): + yield line + + def _parse_and_recurse(self, filename, constraint): + # type: (str, bool) -> Iterator[ParsedLine] + for line in self._parse_file(filename, constraint): + if ( + not line.is_requirement and + (line.opts.requirements or line.opts.constraints) + ): + # parse a nested requirements file + if line.opts.requirements: + req_path = line.opts.requirements[0] + nested_constraint = False + else: + req_path = line.opts.constraints[0] + nested_constraint = True + + # original file is over http + if SCHEME_RE.search(filename): + # do a url join so relative paths work + req_path = urllib_parse.urljoin(filename, req_path) + # original file and nested file are paths + elif not SCHEME_RE.search(req_path): + # do a join so relative paths work + req_path = os.path.join( + os.path.dirname(filename), req_path, + ) + + for inner_line in self._parse_and_recurse( + req_path, nested_constraint, + ): + yield inner_line + else: + yield line + + def _parse_file(self, filename, constraint): + # type: (str, bool) -> Iterator[ParsedLine] + _, content = get_file_content(filename, self._session) + + lines_enum = preprocess(content) + + for line_number, line in lines_enum: + try: + args_str, opts = self._line_parser(line) + except OptionParsingError as e: + # add offending line + msg = 'Invalid requirement: {}\n{}'.format(line, e.msg) + raise RequirementsFileParseError(msg) + + yield ParsedLine( + filename, + line_number, + args_str, + opts, + constraint, + ) + + +def get_line_parser(finder): + # type: (Optional[PackageFinder]) -> LineParser + def parse_line(line): + # type: (Text) -> Tuple[str, Values] + # Build new parser for each line since it accumulates appendable + # options. + parser = build_parser() + defaults = parser.get_default_values() + defaults.index_url = None + if finder: + defaults.format_control = finder.format_control + + args_str, options_str = break_args_options(line) + # Prior to 2.7.3, shlex cannot deal with unicode entries + if sys.version_info < (2, 7, 3): + # https://github.com/python/mypy/issues/1174 + options_str = options_str.encode('utf8') # type: ignore + + # https://github.com/python/mypy/issues/1174 + opts, _ = parser.parse_args( + shlex.split(options_str), defaults) # type: ignore + + return args_str, opts + + return parse_line + + +def break_args_options(line): + # type: (Text) -> Tuple[str, Text] + """Break up the line into an args and options string. We only want to shlex + (and then optparse) the options, not the args. args can contain markers + which are corrupted by shlex. + """ + tokens = line.split(' ') + args = [] + options = tokens[:] + for token in tokens: + if token.startswith('-') or token.startswith('--'): + break + else: + args.append(token) + options.pop(0) + return ' '.join(args), ' '.join(options) # type: ignore + + +class OptionParsingError(Exception): + def __init__(self, msg): + # type: (str) -> None + self.msg = msg + + +def build_parser(): + # type: () -> optparse.OptionParser + """ + Return a parser for parsing requirement lines + """ + parser = optparse.OptionParser(add_help_option=False) + + option_factories = SUPPORTED_OPTIONS + SUPPORTED_OPTIONS_REQ + for option_factory in option_factories: + option = option_factory() + parser.add_option(option) + + # By default optparse sys.exits on parsing errors. We want to wrap + # that in our own exception. + def parser_exit(self, msg): + # type: (Any, str) -> NoReturn + raise OptionParsingError(msg) + # NOTE: mypy disallows assigning to a method + # https://github.com/python/mypy/issues/2427 + parser.exit = parser_exit # type: ignore + + return parser + + +def join_lines(lines_enum): + # type: (ReqFileLines) -> ReqFileLines + """Joins a line ending in '\' with the previous line (except when following + comments). The joined line takes on the index of the first line. + """ + primary_line_number = None + new_line = [] # type: List[Text] + for line_number, line in lines_enum: + if not line.endswith('\\') or COMMENT_RE.match(line): + if COMMENT_RE.match(line): + # this ensures comments are always matched later + line = ' ' + line + if new_line: + new_line.append(line) + assert primary_line_number is not None + yield primary_line_number, ''.join(new_line) + new_line = [] + else: + yield line_number, line + else: + if not new_line: + primary_line_number = line_number + new_line.append(line.strip('\\')) + + # last line contains \ + if new_line: + assert primary_line_number is not None + yield primary_line_number, ''.join(new_line) + + # TODO: handle space after '\'. + + +def ignore_comments(lines_enum): + # type: (ReqFileLines) -> ReqFileLines + """ + Strips comments and filter empty lines. + """ + for line_number, line in lines_enum: + line = COMMENT_RE.sub('', line) + line = line.strip() + if line: + yield line_number, line + + +def expand_env_variables(lines_enum): + # type: (ReqFileLines) -> ReqFileLines + """Replace all environment variables that can be retrieved via `os.getenv`. + + The only allowed format for environment variables defined in the + requirement file is `${MY_VARIABLE_1}` to ensure two things: + + 1. Strings that contain a `$` aren't accidentally (partially) expanded. + 2. Ensure consistency across platforms for requirement files. + + These points are the result of a discussion on the `github pull + request #3514 `_. + + Valid characters in variable names follow the `POSIX standard + `_ and are limited + to uppercase letter, digits and the `_` (underscore). + """ + for line_number, line in lines_enum: + for env_var, var_name in ENV_VAR_RE.findall(line): + value = os.getenv(var_name) + if not value: + continue + + line = line.replace(env_var, value) + + yield line_number, line + + +def get_file_content(url, session): + # type: (str, PipSession) -> Tuple[str, Text] + """Gets the content of a file; it may be a filename, file: URL, or + http: URL. Returns (location, content). Content is unicode. + Respects # -*- coding: declarations on the retrieved files. + + :param url: File path or url. + :param session: PipSession instance. + """ + scheme = get_url_scheme(url) + + if scheme in ['http', 'https']: + # FIXME: catch some errors + resp = session.get(url) + raise_for_status(resp) + return resp.url, resp.text + + elif scheme == 'file': + url = url_to_path(url) + + try: + with open(url, 'rb') as f: + content = auto_decode(f.read()) + except IOError as exc: + raise InstallationError( + 'Could not open requirements file: {}'.format(exc) + ) + return url, content diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_install.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_install.py new file mode 100644 index 0000000..548c00d --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_install.py @@ -0,0 +1,915 @@ +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +from __future__ import absolute_import + +import logging +import os +import shutil +import sys +import uuid +import zipfile + +from pip._vendor import pkg_resources, six +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import Version +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.pep517.wrappers import Pep517HookCaller + +from pip._internal.build_env import NoOpBuildEnvironment +from pip._internal.exceptions import InstallationError +from pip._internal.locations import get_scheme +from pip._internal.models.link import Link +from pip._internal.operations.build.metadata import generate_metadata +from pip._internal.operations.build.metadata_legacy import ( + generate_metadata as generate_metadata_legacy, +) +from pip._internal.operations.install.editable_legacy import ( + install_editable as install_editable_legacy, +) +from pip._internal.operations.install.legacy import LegacyInstallFailure +from pip._internal.operations.install.legacy import install as install_legacy +from pip._internal.operations.install.wheel import install_wheel +from pip._internal.pyproject import load_pyproject_toml, make_pyproject_path +from pip._internal.req.req_uninstall import UninstallPathSet +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.direct_url_helpers import direct_url_from_link +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + ask_path_exists, + backup_dir, + display_path, + dist_in_site_packages, + dist_in_usersite, + get_distribution, + get_installed_version, + hide_url, + redact_auth_from_url, +) +from pip._internal.utils.packaging import get_metadata +from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.virtualenv import running_under_virtualenv +from pip._internal.vcs import vcs + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, Iterable, List, Optional, Sequence, Union + + from pip._vendor.packaging.markers import Marker + from pip._vendor.packaging.specifiers import SpecifierSet + from pip._vendor.pkg_resources import Distribution + + from pip._internal.build_env import BuildEnvironment + + +logger = logging.getLogger(__name__) + + +def _get_dist(metadata_directory): + # type: (str) -> Distribution + """Return a pkg_resources.Distribution for the provided + metadata directory. + """ + dist_dir = metadata_directory.rstrip(os.sep) + + # Build a PathMetadata object, from path to metadata. :wink: + base_dir, dist_dir_name = os.path.split(dist_dir) + metadata = pkg_resources.PathMetadata(base_dir, dist_dir) + + # Determine the correct Distribution object type. + if dist_dir.endswith(".egg-info"): + dist_cls = pkg_resources.Distribution + dist_name = os.path.splitext(dist_dir_name)[0] + else: + assert dist_dir.endswith(".dist-info") + dist_cls = pkg_resources.DistInfoDistribution + dist_name = os.path.splitext(dist_dir_name)[0].split("-")[0] + + return dist_cls( + base_dir, + project_name=dist_name, + metadata=metadata, + ) + + +class InstallRequirement(object): + """ + Represents something that may be installed later on, may have information + about where to fetch the relevant requirement and also contains logic for + installing the said requirement. + """ + + def __init__( + self, + req, # type: Optional[Requirement] + comes_from, # type: Optional[Union[str, InstallRequirement]] + editable=False, # type: bool + link=None, # type: Optional[Link] + markers=None, # type: Optional[Marker] + use_pep517=None, # type: Optional[bool] + isolated=False, # type: bool + install_options=None, # type: Optional[List[str]] + global_options=None, # type: Optional[List[str]] + hash_options=None, # type: Optional[Dict[str, List[str]]] + constraint=False, # type: bool + extras=(), # type: Iterable[str] + user_supplied=False, # type: bool + ): + # type: (...) -> None + assert req is None or isinstance(req, Requirement), req + self.req = req + self.comes_from = comes_from + self.constraint = constraint + self.editable = editable + self.legacy_install_reason = None # type: Optional[int] + + # source_dir is the local directory where the linked requirement is + # located, or unpacked. In case unpacking is needed, creating and + # populating source_dir is done by the RequirementPreparer. Note this + # is not necessarily the directory where pyproject.toml or setup.py is + # located - that one is obtained via unpacked_source_directory. + self.source_dir = None # type: Optional[str] + if self.editable: + assert link + if link.is_file: + self.source_dir = os.path.normpath( + os.path.abspath(link.file_path) + ) + + if link is None and req and req.url: + # PEP 508 URL requirement + link = Link(req.url) + self.link = self.original_link = link + self.original_link_is_in_wheel_cache = False + + # Path to any downloaded or already-existing package. + self.local_file_path = None # type: Optional[str] + if self.link and self.link.is_file: + self.local_file_path = self.link.file_path + + if extras: + self.extras = extras + elif req: + self.extras = { + pkg_resources.safe_extra(extra) for extra in req.extras + } + else: + self.extras = set() + if markers is None and req: + markers = req.marker + self.markers = markers + + # This holds the pkg_resources.Distribution object if this requirement + # is already available: + self.satisfied_by = None # type: Optional[Distribution] + # Whether the installation process should try to uninstall an existing + # distribution before installing this requirement. + self.should_reinstall = False + # Temporary build location + self._temp_build_dir = None # type: Optional[TempDirectory] + # Set to True after successful installation + self.install_succeeded = None # type: Optional[bool] + # Supplied options + self.install_options = install_options if install_options else [] + self.global_options = global_options if global_options else [] + self.hash_options = hash_options if hash_options else {} + # Set to True after successful preparation of this requirement + self.prepared = False + # User supplied requirement are explicitly requested for installation + # by the user via CLI arguments or requirements files, as opposed to, + # e.g. dependencies, extras or constraints. + self.user_supplied = user_supplied + + self.isolated = isolated + self.build_env = NoOpBuildEnvironment() # type: BuildEnvironment + + # For PEP 517, the directory where we request the project metadata + # gets stored. We need this to pass to build_wheel, so the backend + # can ensure that the wheel matches the metadata (see the PEP for + # details). + self.metadata_directory = None # type: Optional[str] + + # The static build requirements (from pyproject.toml) + self.pyproject_requires = None # type: Optional[List[str]] + + # Build requirements that we will check are available + self.requirements_to_check = [] # type: List[str] + + # The PEP 517 backend we should use to build the project + self.pep517_backend = None # type: Optional[Pep517HookCaller] + + # Are we using PEP 517 for this requirement? + # After pyproject.toml has been loaded, the only valid values are True + # and False. Before loading, None is valid (meaning "use the default"). + # Setting an explicit value before loading pyproject.toml is supported, + # but after loading this flag should be treated as read only. + self.use_pep517 = use_pep517 + + # This requirement needs more preparation before it can be built + self.needs_more_preparation = False + + def __str__(self): + # type: () -> str + if self.req: + s = str(self.req) + if self.link: + s += ' from {}'.format(redact_auth_from_url(self.link.url)) + elif self.link: + s = redact_auth_from_url(self.link.url) + else: + s = '' + if self.satisfied_by is not None: + s += ' in {}'.format(display_path(self.satisfied_by.location)) + if self.comes_from: + if isinstance(self.comes_from, six.string_types): + comes_from = self.comes_from # type: Optional[str] + else: + comes_from = self.comes_from.from_path() + if comes_from: + s += ' (from {})'.format(comes_from) + return s + + def __repr__(self): + # type: () -> str + return '<{} object: {} editable={!r}>'.format( + self.__class__.__name__, str(self), self.editable) + + def format_debug(self): + # type: () -> str + """An un-tested helper for getting state, for debugging. + """ + attributes = vars(self) + names = sorted(attributes) + + state = ( + "{}={!r}".format(attr, attributes[attr]) for attr in sorted(names) + ) + return '<{name} object: {{{state}}}>'.format( + name=self.__class__.__name__, + state=", ".join(state), + ) + + # Things that are valid for all kinds of requirements? + @property + def name(self): + # type: () -> Optional[str] + if self.req is None: + return None + return six.ensure_str(pkg_resources.safe_name(self.req.name)) + + @property + def specifier(self): + # type: () -> SpecifierSet + return self.req.specifier + + @property + def is_pinned(self): + # type: () -> bool + """Return whether I am pinned to an exact version. + + For example, some-package==1.2 is pinned; some-package>1.2 is not. + """ + specifiers = self.specifier + return (len(specifiers) == 1 and + next(iter(specifiers)).operator in {'==', '==='}) + + @property + def installed_version(self): + # type: () -> Optional[str] + return get_installed_version(self.name) + + def match_markers(self, extras_requested=None): + # type: (Optional[Iterable[str]]) -> bool + if not extras_requested: + # Provide an extra to safely evaluate the markers + # without matching any extra + extras_requested = ('',) + if self.markers is not None: + return any( + self.markers.evaluate({'extra': extra}) + for extra in extras_requested) + else: + return True + + @property + def has_hash_options(self): + # type: () -> bool + """Return whether any known-good hashes are specified as options. + + These activate --require-hashes mode; hashes specified as part of a + URL do not. + + """ + return bool(self.hash_options) + + def hashes(self, trust_internet=True): + # type: (bool) -> Hashes + """Return a hash-comparer that considers my option- and URL-based + hashes to be known-good. + + Hashes in URLs--ones embedded in the requirements file, not ones + downloaded from an index server--are almost peers with ones from + flags. They satisfy --require-hashes (whether it was implicitly or + explicitly activated) but do not activate it. md5 and sha224 are not + allowed in flags, which should nudge people toward good algos. We + always OR all hashes together, even ones from URLs. + + :param trust_internet: Whether to trust URL-based (#md5=...) hashes + downloaded from the internet, as by populate_link() + + """ + good_hashes = self.hash_options.copy() + link = self.link if trust_internet else self.original_link + if link and link.hash: + good_hashes.setdefault(link.hash_name, []).append(link.hash) + return Hashes(good_hashes) + + def from_path(self): + # type: () -> Optional[str] + """Format a nice indicator to show where this "comes from" + """ + if self.req is None: + return None + s = str(self.req) + if self.comes_from: + if isinstance(self.comes_from, six.string_types): + comes_from = self.comes_from + else: + comes_from = self.comes_from.from_path() + if comes_from: + s += '->' + comes_from + return s + + def ensure_build_location(self, build_dir, autodelete, parallel_builds): + # type: (str, bool, bool) -> str + assert build_dir is not None + if self._temp_build_dir is not None: + assert self._temp_build_dir.path + return self._temp_build_dir.path + if self.req is None: + # Some systems have /tmp as a symlink which confuses custom + # builds (such as numpy). Thus, we ensure that the real path + # is returned. + self._temp_build_dir = TempDirectory( + kind=tempdir_kinds.REQ_BUILD, globally_managed=True + ) + + return self._temp_build_dir.path + + # This is the only remaining place where we manually determine the path + # for the temporary directory. It is only needed for editables where + # it is the value of the --src option. + + # When parallel builds are enabled, add a UUID to the build directory + # name so multiple builds do not interfere with each other. + dir_name = canonicalize_name(self.name) + if parallel_builds: + dir_name = "{}_{}".format(dir_name, uuid.uuid4().hex) + + # FIXME: Is there a better place to create the build_dir? (hg and bzr + # need this) + if not os.path.exists(build_dir): + logger.debug('Creating directory %s', build_dir) + os.makedirs(build_dir) + actual_build_dir = os.path.join(build_dir, dir_name) + # `None` indicates that we respect the globally-configured deletion + # settings, which is what we actually want when auto-deleting. + delete_arg = None if autodelete else False + return TempDirectory( + path=actual_build_dir, + delete=delete_arg, + kind=tempdir_kinds.REQ_BUILD, + globally_managed=True, + ).path + + def _set_requirement(self): + # type: () -> None + """Set requirement after generating metadata. + """ + assert self.req is None + assert self.metadata is not None + assert self.source_dir is not None + + # Construct a Requirement object from the generated metadata + if isinstance(parse_version(self.metadata["Version"]), Version): + op = "==" + else: + op = "===" + + self.req = Requirement( + "".join([ + self.metadata["Name"], + op, + self.metadata["Version"], + ]) + ) + + def warn_on_mismatching_name(self): + # type: () -> None + metadata_name = canonicalize_name(self.metadata["Name"]) + if canonicalize_name(self.req.name) == metadata_name: + # Everything is fine. + return + + # If we're here, there's a mismatch. Log a warning about it. + logger.warning( + 'Generating metadata for package %s ' + 'produced metadata for project name %s. Fix your ' + '#egg=%s fragments.', + self.name, metadata_name, self.name + ) + self.req = Requirement(metadata_name) + + def check_if_exists(self, use_user_site): + # type: (bool) -> None + """Find an installed distribution that satisfies or conflicts + with this requirement, and set self.satisfied_by or + self.should_reinstall appropriately. + """ + if self.req is None: + return + existing_dist = get_distribution(self.req.name) + if not existing_dist: + return + + # pkg_resouces may contain a different copy of packaging.version from + # pip in if the downstream distributor does a poor job debundling pip. + # We avoid existing_dist.parsed_version and let SpecifierSet.contains + # parses the version instead. + existing_version = existing_dist.version + version_compatible = ( + existing_version is not None and + self.req.specifier.contains(existing_version, prereleases=True) + ) + if not version_compatible: + self.satisfied_by = None + if use_user_site: + if dist_in_usersite(existing_dist): + self.should_reinstall = True + elif (running_under_virtualenv() and + dist_in_site_packages(existing_dist)): + raise InstallationError( + "Will not install to the user site because it will " + "lack sys.path precedence to {} in {}".format( + existing_dist.project_name, existing_dist.location) + ) + else: + self.should_reinstall = True + else: + if self.editable: + self.should_reinstall = True + # when installing editables, nothing pre-existing should ever + # satisfy + self.satisfied_by = None + else: + self.satisfied_by = existing_dist + + # Things valid for wheels + @property + def is_wheel(self): + # type: () -> bool + if not self.link: + return False + return self.link.is_wheel + + # Things valid for sdists + @property + def unpacked_source_directory(self): + # type: () -> str + return os.path.join( + self.source_dir, + self.link and self.link.subdirectory_fragment or '') + + @property + def setup_py_path(self): + # type: () -> str + assert self.source_dir, "No source dir for {}".format(self) + setup_py = os.path.join(self.unpacked_source_directory, 'setup.py') + + # Python2 __file__ should not be unicode + if six.PY2 and isinstance(setup_py, six.text_type): + setup_py = setup_py.encode(sys.getfilesystemencoding()) + + return setup_py + + @property + def pyproject_toml_path(self): + # type: () -> str + assert self.source_dir, "No source dir for {}".format(self) + return make_pyproject_path(self.unpacked_source_directory) + + def load_pyproject_toml(self): + # type: () -> None + """Load the pyproject.toml file. + + After calling this routine, all of the attributes related to PEP 517 + processing for this requirement have been set. In particular, the + use_pep517 attribute can be used to determine whether we should + follow the PEP 517 or legacy (setup.py) code path. + """ + pyproject_toml_data = load_pyproject_toml( + self.use_pep517, + self.pyproject_toml_path, + self.setup_py_path, + str(self) + ) + + if pyproject_toml_data is None: + self.use_pep517 = False + return + + self.use_pep517 = True + requires, backend, check, backend_path = pyproject_toml_data + self.requirements_to_check = check + self.pyproject_requires = requires + self.pep517_backend = Pep517HookCaller( + self.unpacked_source_directory, backend, backend_path=backend_path, + ) + + def _generate_metadata(self): + # type: () -> str + """Invokes metadata generator functions, with the required arguments. + """ + if not self.use_pep517: + assert self.unpacked_source_directory + + return generate_metadata_legacy( + build_env=self.build_env, + setup_py_path=self.setup_py_path, + source_dir=self.unpacked_source_directory, + isolated=self.isolated, + details=self.name or "from {}".format(self.link) + ) + + assert self.pep517_backend is not None + + return generate_metadata( + build_env=self.build_env, + backend=self.pep517_backend, + ) + + def prepare_metadata(self): + # type: () -> None + """Ensure that project metadata is available. + + Under PEP 517, call the backend hook to prepare the metadata. + Under legacy processing, call setup.py egg-info. + """ + assert self.source_dir + + with indent_log(): + self.metadata_directory = self._generate_metadata() + + # Act on the newly generated metadata, based on the name and version. + if not self.name: + self._set_requirement() + else: + self.warn_on_mismatching_name() + + self.assert_source_matches_version() + + @property + def metadata(self): + # type: () -> Any + if not hasattr(self, '_metadata'): + self._metadata = get_metadata(self.get_dist()) + + return self._metadata + + def get_dist(self): + # type: () -> Distribution + return _get_dist(self.metadata_directory) + + def assert_source_matches_version(self): + # type: () -> None + assert self.source_dir + version = self.metadata['version'] + if self.req.specifier and version not in self.req.specifier: + logger.warning( + 'Requested %s, but installing version %s', + self, + version, + ) + else: + logger.debug( + 'Source in %s has version %s, which satisfies requirement %s', + display_path(self.source_dir), + version, + self, + ) + + # For both source distributions and editables + def ensure_has_source_dir( + self, + parent_dir, + autodelete=False, + parallel_builds=False, + ): + # type: (str, bool, bool) -> None + """Ensure that a source_dir is set. + + This will create a temporary build dir if the name of the requirement + isn't known yet. + + :param parent_dir: The ideal pip parent_dir for the source_dir. + Generally src_dir for editables and build_dir for sdists. + :return: self.source_dir + """ + if self.source_dir is None: + self.source_dir = self.ensure_build_location( + parent_dir, + autodelete=autodelete, + parallel_builds=parallel_builds, + ) + + # For editable installations + def update_editable(self, obtain=True): + # type: (bool) -> None + if not self.link: + logger.debug( + "Cannot update repository at %s; repository location is " + "unknown", + self.source_dir, + ) + return + assert self.editable + assert self.source_dir + if self.link.scheme == 'file': + # Static paths don't get updated + return + assert '+' in self.link.url, \ + "bad url: {self.link.url!r}".format(**locals()) + vc_type, url = self.link.url.split('+', 1) + vcs_backend = vcs.get_backend(vc_type) + if vcs_backend: + if not self.link.is_vcs: + reason = ( + "This form of VCS requirement is being deprecated: {}." + ).format( + self.link.url + ) + replacement = None + if self.link.url.startswith("git+git@"): + replacement = ( + "git+https://git@example.com/..., " + "git+ssh://git@example.com/..., " + "or the insecure git+git://git@example.com/..." + ) + deprecated(reason, replacement, gone_in="21.0", issue=7554) + hidden_url = hide_url(self.link.url) + if obtain: + vcs_backend.obtain(self.source_dir, url=hidden_url) + else: + vcs_backend.export(self.source_dir, url=hidden_url) + else: + assert 0, ( + 'Unexpected version control type (in {}): {}'.format( + self.link, vc_type)) + + # Top-level Actions + def uninstall(self, auto_confirm=False, verbose=False): + # type: (bool, bool) -> Optional[UninstallPathSet] + """ + Uninstall the distribution currently satisfying this requirement. + + Prompts before removing or modifying files unless + ``auto_confirm`` is True. + + Refuses to delete or modify files outside of ``sys.prefix`` - + thus uninstallation within a virtual environment can only + modify that virtual environment, even if the virtualenv is + linked to global site-packages. + + """ + assert self.req + dist = get_distribution(self.req.name) + if not dist: + logger.warning("Skipping %s as it is not installed.", self.name) + return None + logger.info('Found existing installation: %s', dist) + + uninstalled_pathset = UninstallPathSet.from_dist(dist) + uninstalled_pathset.remove(auto_confirm, verbose) + return uninstalled_pathset + + def _get_archive_name(self, path, parentdir, rootdir): + # type: (str, str, str) -> str + + def _clean_zip_name(name, prefix): + # type: (str, str) -> str + assert name.startswith(prefix + os.path.sep), ( + "name {name!r} doesn't start with prefix {prefix!r}" + .format(**locals()) + ) + name = name[len(prefix) + 1:] + name = name.replace(os.path.sep, '/') + return name + + path = os.path.join(parentdir, path) + name = _clean_zip_name(path, rootdir) + return self.name + '/' + name + + def archive(self, build_dir): + # type: (Optional[str]) -> None + """Saves archive to provided build_dir. + + Used for saving downloaded VCS requirements as part of `pip download`. + """ + assert self.source_dir + if build_dir is None: + return + + create_archive = True + archive_name = '{}-{}.zip'.format(self.name, self.metadata["version"]) + archive_path = os.path.join(build_dir, archive_name) + + if os.path.exists(archive_path): + response = ask_path_exists( + 'The file {} exists. (i)gnore, (w)ipe, ' + '(b)ackup, (a)bort '.format( + display_path(archive_path)), + ('i', 'w', 'b', 'a')) + if response == 'i': + create_archive = False + elif response == 'w': + logger.warning('Deleting %s', display_path(archive_path)) + os.remove(archive_path) + elif response == 'b': + dest_file = backup_dir(archive_path) + logger.warning( + 'Backing up %s to %s', + display_path(archive_path), + display_path(dest_file), + ) + shutil.move(archive_path, dest_file) + elif response == 'a': + sys.exit(-1) + + if not create_archive: + return + + zip_output = zipfile.ZipFile( + archive_path, 'w', zipfile.ZIP_DEFLATED, allowZip64=True, + ) + with zip_output: + dir = os.path.normcase( + os.path.abspath(self.unpacked_source_directory) + ) + for dirpath, dirnames, filenames in os.walk(dir): + for dirname in dirnames: + dir_arcname = self._get_archive_name( + dirname, parentdir=dirpath, rootdir=dir, + ) + zipdir = zipfile.ZipInfo(dir_arcname + '/') + zipdir.external_attr = 0x1ED << 16 # 0o755 + zip_output.writestr(zipdir, '') + for filename in filenames: + file_arcname = self._get_archive_name( + filename, parentdir=dirpath, rootdir=dir, + ) + filename = os.path.join(dirpath, filename) + zip_output.write(filename, file_arcname) + + logger.info('Saved %s', display_path(archive_path)) + + def install( + self, + install_options, # type: List[str] + global_options=None, # type: Optional[Sequence[str]] + root=None, # type: Optional[str] + home=None, # type: Optional[str] + prefix=None, # type: Optional[str] + warn_script_location=True, # type: bool + use_user_site=False, # type: bool + pycompile=True # type: bool + ): + # type: (...) -> None + scheme = get_scheme( + self.name, + user=use_user_site, + home=home, + root=root, + isolated=self.isolated, + prefix=prefix, + ) + + global_options = global_options if global_options is not None else [] + if self.editable: + install_editable_legacy( + install_options, + global_options, + prefix=prefix, + home=home, + use_user_site=use_user_site, + name=self.name, + setup_py_path=self.setup_py_path, + isolated=self.isolated, + build_env=self.build_env, + unpacked_source_directory=self.unpacked_source_directory, + ) + self.install_succeeded = True + return + + if self.is_wheel: + assert self.local_file_path + direct_url = None + if self.original_link: + direct_url = direct_url_from_link( + self.original_link, + self.source_dir, + self.original_link_is_in_wheel_cache, + ) + install_wheel( + self.name, + self.local_file_path, + scheme=scheme, + req_description=str(self.req), + pycompile=pycompile, + warn_script_location=warn_script_location, + direct_url=direct_url, + requested=self.user_supplied, + ) + self.install_succeeded = True + return + + # TODO: Why don't we do this for editable installs? + + # Extend the list of global and install options passed on to + # the setup.py call with the ones from the requirements file. + # Options specified in requirements file override those + # specified on the command line, since the last option given + # to setup.py is the one that is used. + global_options = list(global_options) + self.global_options + install_options = list(install_options) + self.install_options + + try: + success = install_legacy( + install_options=install_options, + global_options=global_options, + root=root, + home=home, + prefix=prefix, + use_user_site=use_user_site, + pycompile=pycompile, + scheme=scheme, + setup_py_path=self.setup_py_path, + isolated=self.isolated, + req_name=self.name, + build_env=self.build_env, + unpacked_source_directory=self.unpacked_source_directory, + req_description=str(self.req), + ) + except LegacyInstallFailure as exc: + self.install_succeeded = False + six.reraise(*exc.parent) + except Exception: + self.install_succeeded = True + raise + + self.install_succeeded = success + + if success and self.legacy_install_reason == 8368: + deprecated( + reason=( + "{} was installed using the legacy 'setup.py install' " + "method, because a wheel could not be built for it.". + format(self.name) + ), + replacement="to fix the wheel build issue reported above", + gone_in="21.0", + issue=8368, + ) + + +def check_invalid_constraint_type(req): + # type: (InstallRequirement) -> str + + # Check for unsupported forms + problem = "" + if not req.name: + problem = "Unnamed requirements are not allowed as constraints" + elif req.link: + problem = "Links are not allowed as constraints" + elif req.extras: + problem = "Constraints cannot have extras" + + if problem: + deprecated( + reason=( + "Constraints are only allowed to take the form of a package " + "name and a version specifier. Other forms were originally " + "permitted as an accident of the implementation, but were " + "undocumented. The new implementation of the resolver no " + "longer supports these forms." + ), + replacement=( + "replacing the constraint with a requirement." + ), + # No plan yet for when the new resolver becomes default + gone_in=None, + issue=8210 + ) + + return problem diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_set.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_set.py new file mode 100644 index 0000000..c9ea3be --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_set.py @@ -0,0 +1,204 @@ +from __future__ import absolute_import + +import logging +from collections import OrderedDict + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import InstallationError +from pip._internal.models.wheel import Wheel +from pip._internal.utils import compatibility_tags +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Dict, Iterable, List, Optional, Tuple + + from pip._internal.req.req_install import InstallRequirement + + +logger = logging.getLogger(__name__) + + +class RequirementSet(object): + + def __init__(self, check_supported_wheels=True): + # type: (bool) -> None + """Create a RequirementSet. + """ + + self.requirements = OrderedDict() # type: Dict[str, InstallRequirement] # noqa: E501 + self.check_supported_wheels = check_supported_wheels + + self.unnamed_requirements = [] # type: List[InstallRequirement] + + def __str__(self): + # type: () -> str + requirements = sorted( + (req for req in self.requirements.values() if not req.comes_from), + key=lambda req: canonicalize_name(req.name), + ) + return ' '.join(str(req.req) for req in requirements) + + def __repr__(self): + # type: () -> str + requirements = sorted( + self.requirements.values(), + key=lambda req: canonicalize_name(req.name), + ) + + format_string = '<{classname} object; {count} requirement(s): {reqs}>' + return format_string.format( + classname=self.__class__.__name__, + count=len(requirements), + reqs=', '.join(str(req.req) for req in requirements), + ) + + def add_unnamed_requirement(self, install_req): + # type: (InstallRequirement) -> None + assert not install_req.name + self.unnamed_requirements.append(install_req) + + def add_named_requirement(self, install_req): + # type: (InstallRequirement) -> None + assert install_req.name + + project_name = canonicalize_name(install_req.name) + self.requirements[project_name] = install_req + + def add_requirement( + self, + install_req, # type: InstallRequirement + parent_req_name=None, # type: Optional[str] + extras_requested=None # type: Optional[Iterable[str]] + ): + # type: (...) -> Tuple[List[InstallRequirement], Optional[InstallRequirement]] # noqa: E501 + """Add install_req as a requirement to install. + + :param parent_req_name: The name of the requirement that needed this + added. The name is used because when multiple unnamed requirements + resolve to the same name, we could otherwise end up with dependency + links that point outside the Requirements set. parent_req must + already be added. Note that None implies that this is a user + supplied requirement, vs an inferred one. + :param extras_requested: an iterable of extras used to evaluate the + environment markers. + :return: Additional requirements to scan. That is either [] if + the requirement is not applicable, or [install_req] if the + requirement is applicable and has just been added. + """ + # If the markers do not match, ignore this requirement. + if not install_req.match_markers(extras_requested): + logger.info( + "Ignoring %s: markers '%s' don't match your environment", + install_req.name, install_req.markers, + ) + return [], None + + # If the wheel is not supported, raise an error. + # Should check this after filtering out based on environment markers to + # allow specifying different wheels based on the environment/OS, in a + # single requirements file. + if install_req.link and install_req.link.is_wheel: + wheel = Wheel(install_req.link.filename) + tags = compatibility_tags.get_supported() + if (self.check_supported_wheels and not wheel.supported(tags)): + raise InstallationError( + "{} is not a supported wheel on this platform.".format( + wheel.filename) + ) + + # This next bit is really a sanity check. + assert not install_req.user_supplied or parent_req_name is None, ( + "a user supplied req shouldn't have a parent" + ) + + # Unnamed requirements are scanned again and the requirement won't be + # added as a dependency until after scanning. + if not install_req.name: + self.add_unnamed_requirement(install_req) + return [install_req], None + + try: + existing_req = self.get_requirement( + install_req.name) # type: Optional[InstallRequirement] + except KeyError: + existing_req = None + + has_conflicting_requirement = ( + parent_req_name is None and + existing_req and + not existing_req.constraint and + existing_req.extras == install_req.extras and + existing_req.req.specifier != install_req.req.specifier + ) + if has_conflicting_requirement: + raise InstallationError( + "Double requirement given: {} (already in {}, name={!r})" + .format(install_req, existing_req, install_req.name) + ) + + # When no existing requirement exists, add the requirement as a + # dependency and it will be scanned again after. + if not existing_req: + self.add_named_requirement(install_req) + # We'd want to rescan this requirement later + return [install_req], install_req + + # Assume there's no need to scan, and that we've already + # encountered this for scanning. + if install_req.constraint or not existing_req.constraint: + return [], existing_req + + does_not_satisfy_constraint = ( + install_req.link and + not ( + existing_req.link and + install_req.link.path == existing_req.link.path + ) + ) + if does_not_satisfy_constraint: + raise InstallationError( + "Could not satisfy constraints for '{}': " + "installation from path or url cannot be " + "constrained to a version".format(install_req.name) + ) + # If we're now installing a constraint, mark the existing + # object for real installation. + existing_req.constraint = False + # If we're now installing a user supplied requirement, + # mark the existing object as such. + if install_req.user_supplied: + existing_req.user_supplied = True + existing_req.extras = tuple(sorted( + set(existing_req.extras) | set(install_req.extras) + )) + logger.debug( + "Setting %s extras to: %s", + existing_req, existing_req.extras, + ) + # Return the existing requirement for addition to the parent and + # scanning again. + return [existing_req], existing_req + + def has_requirement(self, name): + # type: (str) -> bool + project_name = canonicalize_name(name) + + return ( + project_name in self.requirements and + not self.requirements[project_name].constraint + ) + + def get_requirement(self, name): + # type: (str) -> InstallRequirement + project_name = canonicalize_name(name) + + if project_name in self.requirements: + return self.requirements[project_name] + + raise KeyError("No project with the name {name!r}".format(**locals())) + + @property + def all_requirements(self): + # type: () -> List[InstallRequirement] + return self.unnamed_requirements + list(self.requirements.values()) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_tracker.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_tracker.py new file mode 100644 index 0000000..7379c30 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_tracker.py @@ -0,0 +1,151 @@ +from __future__ import absolute_import + +import contextlib +import errno +import hashlib +import logging +import os + +from pip._vendor import contextlib2 + +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from types import TracebackType + from typing import Dict, Iterator, Optional, Set, Type, Union + + from pip._internal.models.link import Link + from pip._internal.req.req_install import InstallRequirement + +logger = logging.getLogger(__name__) + + +@contextlib.contextmanager +def update_env_context_manager(**changes): + # type: (str) -> Iterator[None] + target = os.environ + + # Save values from the target and change them. + non_existent_marker = object() + saved_values = {} # type: Dict[str, Union[object, str]] + for name, new_value in changes.items(): + try: + saved_values[name] = target[name] + except KeyError: + saved_values[name] = non_existent_marker + target[name] = new_value + + try: + yield + finally: + # Restore original values in the target. + for name, original_value in saved_values.items(): + if original_value is non_existent_marker: + del target[name] + else: + assert isinstance(original_value, str) # for mypy + target[name] = original_value + + +@contextlib.contextmanager +def get_requirement_tracker(): + # type: () -> Iterator[RequirementTracker] + root = os.environ.get('PIP_REQ_TRACKER') + with contextlib2.ExitStack() as ctx: + if root is None: + root = ctx.enter_context( + TempDirectory(kind='req-tracker') + ).path + ctx.enter_context(update_env_context_manager(PIP_REQ_TRACKER=root)) + logger.debug("Initialized build tracking at %s", root) + + with RequirementTracker(root) as tracker: + yield tracker + + +class RequirementTracker(object): + + def __init__(self, root): + # type: (str) -> None + self._root = root + self._entries = set() # type: Set[InstallRequirement] + logger.debug("Created build tracker: %s", self._root) + + def __enter__(self): + # type: () -> RequirementTracker + logger.debug("Entered build tracker: %s", self._root) + return self + + def __exit__( + self, + exc_type, # type: Optional[Type[BaseException]] + exc_val, # type: Optional[BaseException] + exc_tb # type: Optional[TracebackType] + ): + # type: (...) -> None + self.cleanup() + + def _entry_path(self, link): + # type: (Link) -> str + hashed = hashlib.sha224(link.url_without_fragment.encode()).hexdigest() + return os.path.join(self._root, hashed) + + def add(self, req): + # type: (InstallRequirement) -> None + """Add an InstallRequirement to build tracking. + """ + + assert req.link + # Get the file to write information about this requirement. + entry_path = self._entry_path(req.link) + + # Try reading from the file. If it exists and can be read from, a build + # is already in progress, so a LookupError is raised. + try: + with open(entry_path) as fp: + contents = fp.read() + except IOError as e: + # if the error is anything other than "file does not exist", raise. + if e.errno != errno.ENOENT: + raise + else: + message = '{} is already being built: {}'.format( + req.link, contents) + raise LookupError(message) + + # If we're here, req should really not be building already. + assert req not in self._entries + + # Start tracking this requirement. + with open(entry_path, 'w') as fp: + fp.write(str(req)) + self._entries.add(req) + + logger.debug('Added %s to build tracker %r', req, self._root) + + def remove(self, req): + # type: (InstallRequirement) -> None + """Remove an InstallRequirement from build tracking. + """ + + assert req.link + # Delete the created file and the corresponding entries. + os.unlink(self._entry_path(req.link)) + self._entries.remove(req) + + logger.debug('Removed %s from build tracker %r', req, self._root) + + def cleanup(self): + # type: () -> None + for req in set(self._entries): + self.remove(req) + + logger.debug("Removed build tracker: %r", self._root) + + @contextlib.contextmanager + def track(self, req): + # type: (InstallRequirement) -> Iterator[None] + self.add(req) + yield + self.remove(req) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_uninstall.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_uninstall.py new file mode 100644 index 0000000..2e7dfcc --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/req/req_uninstall.py @@ -0,0 +1,657 @@ +from __future__ import absolute_import + +import csv +import functools +import logging +import os +import sys +import sysconfig + +from pip._vendor import pkg_resources + +from pip._internal.exceptions import UninstallationError +from pip._internal.locations import bin_py, bin_user +from pip._internal.utils.compat import WINDOWS, cache_from_source, uses_pycache +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + FakeFile, + ask, + dist_in_usersite, + dist_is_local, + egg_link_path, + is_local, + normalize_path, + renames, + rmtree, +) +from pip._internal.utils.temp_dir import AdjacentTempDirectory, TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import ( + Any, + Callable, + Dict, + Iterable, + Iterator, + List, + Optional, + Set, + Tuple, + ) + + from pip._vendor.pkg_resources import Distribution + +logger = logging.getLogger(__name__) + + +def _script_names(dist, script_name, is_gui): + # type: (Distribution, str, bool) -> List[str] + """Create the fully qualified name of the files created by + {console,gui}_scripts for the given ``dist``. + Returns the list of file names + """ + if dist_in_usersite(dist): + bin_dir = bin_user + else: + bin_dir = bin_py + exe_name = os.path.join(bin_dir, script_name) + paths_to_remove = [exe_name] + if WINDOWS: + paths_to_remove.append(exe_name + '.exe') + paths_to_remove.append(exe_name + '.exe.manifest') + if is_gui: + paths_to_remove.append(exe_name + '-script.pyw') + else: + paths_to_remove.append(exe_name + '-script.py') + return paths_to_remove + + +def _unique(fn): + # type: (Callable[..., Iterator[Any]]) -> Callable[..., Iterator[Any]] + @functools.wraps(fn) + def unique(*args, **kw): + # type: (Any, Any) -> Iterator[Any] + seen = set() # type: Set[Any] + for item in fn(*args, **kw): + if item not in seen: + seen.add(item) + yield item + return unique + + +@_unique +def uninstallation_paths(dist): + # type: (Distribution) -> Iterator[str] + """ + Yield all the uninstallation paths for dist based on RECORD-without-.py[co] + + Yield paths to all the files in RECORD. For each .py file in RECORD, add + the .pyc and .pyo in the same directory. + + UninstallPathSet.add() takes care of the __pycache__ .py[co]. + """ + r = csv.reader(FakeFile(dist.get_metadata_lines('RECORD'))) + for row in r: + path = os.path.join(dist.location, row[0]) + yield path + if path.endswith('.py'): + dn, fn = os.path.split(path) + base = fn[:-3] + path = os.path.join(dn, base + '.pyc') + yield path + path = os.path.join(dn, base + '.pyo') + yield path + + +def compact(paths): + # type: (Iterable[str]) -> Set[str] + """Compact a path set to contain the minimal number of paths + necessary to contain all paths in the set. If /a/path/ and + /a/path/to/a/file.txt are both in the set, leave only the + shorter path.""" + + sep = os.path.sep + short_paths = set() # type: Set[str] + for path in sorted(paths, key=len): + should_skip = any( + path.startswith(shortpath.rstrip("*")) and + path[len(shortpath.rstrip("*").rstrip(sep))] == sep + for shortpath in short_paths + ) + if not should_skip: + short_paths.add(path) + return short_paths + + +def compress_for_rename(paths): + # type: (Iterable[str]) -> Set[str] + """Returns a set containing the paths that need to be renamed. + + This set may include directories when the original sequence of paths + included every file on disk. + """ + case_map = dict((os.path.normcase(p), p) for p in paths) + remaining = set(case_map) + unchecked = sorted(set(os.path.split(p)[0] + for p in case_map.values()), key=len) + wildcards = set() # type: Set[str] + + def norm_join(*a): + # type: (str) -> str + return os.path.normcase(os.path.join(*a)) + + for root in unchecked: + if any(os.path.normcase(root).startswith(w) + for w in wildcards): + # This directory has already been handled. + continue + + all_files = set() # type: Set[str] + all_subdirs = set() # type: Set[str] + for dirname, subdirs, files in os.walk(root): + all_subdirs.update(norm_join(root, dirname, d) + for d in subdirs) + all_files.update(norm_join(root, dirname, f) + for f in files) + # If all the files we found are in our remaining set of files to + # remove, then remove them from the latter set and add a wildcard + # for the directory. + if not (all_files - remaining): + remaining.difference_update(all_files) + wildcards.add(root + os.sep) + + return set(map(case_map.__getitem__, remaining)) | wildcards + + +def compress_for_output_listing(paths): + # type: (Iterable[str]) -> Tuple[Set[str], Set[str]] + """Returns a tuple of 2 sets of which paths to display to user + + The first set contains paths that would be deleted. Files of a package + are not added and the top-level directory of the package has a '*' added + at the end - to signify that all it's contents are removed. + + The second set contains files that would have been skipped in the above + folders. + """ + + will_remove = set(paths) + will_skip = set() + + # Determine folders and files + folders = set() + files = set() + for path in will_remove: + if path.endswith(".pyc"): + continue + if path.endswith("__init__.py") or ".dist-info" in path: + folders.add(os.path.dirname(path)) + files.add(path) + + # probably this one https://github.com/python/mypy/issues/390 + _normcased_files = set(map(os.path.normcase, files)) # type: ignore + + folders = compact(folders) + + # This walks the tree using os.walk to not miss extra folders + # that might get added. + for folder in folders: + for dirpath, _, dirfiles in os.walk(folder): + for fname in dirfiles: + if fname.endswith(".pyc"): + continue + + file_ = os.path.join(dirpath, fname) + if (os.path.isfile(file_) and + os.path.normcase(file_) not in _normcased_files): + # We are skipping this file. Add it to the set. + will_skip.add(file_) + + will_remove = files | { + os.path.join(folder, "*") for folder in folders + } + + return will_remove, will_skip + + +class StashedUninstallPathSet(object): + """A set of file rename operations to stash files while + tentatively uninstalling them.""" + def __init__(self): + # type: () -> None + # Mapping from source file root to [Adjacent]TempDirectory + # for files under that directory. + self._save_dirs = {} # type: Dict[str, TempDirectory] + # (old path, new path) tuples for each move that may need + # to be undone. + self._moves = [] # type: List[Tuple[str, str]] + + def _get_directory_stash(self, path): + # type: (str) -> str + """Stashes a directory. + + Directories are stashed adjacent to their original location if + possible, or else moved/copied into the user's temp dir.""" + + try: + save_dir = AdjacentTempDirectory(path) # type: TempDirectory + except OSError: + save_dir = TempDirectory(kind="uninstall") + self._save_dirs[os.path.normcase(path)] = save_dir + + return save_dir.path + + def _get_file_stash(self, path): + # type: (str) -> str + """Stashes a file. + + If no root has been provided, one will be created for the directory + in the user's temp directory.""" + path = os.path.normcase(path) + head, old_head = os.path.dirname(path), None + save_dir = None + + while head != old_head: + try: + save_dir = self._save_dirs[head] + break + except KeyError: + pass + head, old_head = os.path.dirname(head), head + else: + # Did not find any suitable root + head = os.path.dirname(path) + save_dir = TempDirectory(kind='uninstall') + self._save_dirs[head] = save_dir + + relpath = os.path.relpath(path, head) + if relpath and relpath != os.path.curdir: + return os.path.join(save_dir.path, relpath) + return save_dir.path + + def stash(self, path): + # type: (str) -> str + """Stashes the directory or file and returns its new location. + Handle symlinks as files to avoid modifying the symlink targets. + """ + path_is_dir = os.path.isdir(path) and not os.path.islink(path) + if path_is_dir: + new_path = self._get_directory_stash(path) + else: + new_path = self._get_file_stash(path) + + self._moves.append((path, new_path)) + if (path_is_dir and os.path.isdir(new_path)): + # If we're moving a directory, we need to + # remove the destination first or else it will be + # moved to inside the existing directory. + # We just created new_path ourselves, so it will + # be removable. + os.rmdir(new_path) + renames(path, new_path) + return new_path + + def commit(self): + # type: () -> None + """Commits the uninstall by removing stashed files.""" + for _, save_dir in self._save_dirs.items(): + save_dir.cleanup() + self._moves = [] + self._save_dirs = {} + + def rollback(self): + # type: () -> None + """Undoes the uninstall by moving stashed files back.""" + for p in self._moves: + logger.info("Moving to %s\n from %s", *p) + + for new_path, path in self._moves: + try: + logger.debug('Replacing %s from %s', new_path, path) + if os.path.isfile(new_path) or os.path.islink(new_path): + os.unlink(new_path) + elif os.path.isdir(new_path): + rmtree(new_path) + renames(path, new_path) + except OSError as ex: + logger.error("Failed to restore %s", new_path) + logger.debug("Exception: %s", ex) + + self.commit() + + @property + def can_rollback(self): + # type: () -> bool + return bool(self._moves) + + +class UninstallPathSet(object): + """A set of file paths to be removed in the uninstallation of a + requirement.""" + def __init__(self, dist): + # type: (Distribution) -> None + self.paths = set() # type: Set[str] + self._refuse = set() # type: Set[str] + self.pth = {} # type: Dict[str, UninstallPthEntries] + self.dist = dist + self._moved_paths = StashedUninstallPathSet() + + def _permitted(self, path): + # type: (str) -> bool + """ + Return True if the given path is one we are permitted to + remove/modify, False otherwise. + + """ + return is_local(path) + + def add(self, path): + # type: (str) -> None + head, tail = os.path.split(path) + + # we normalize the head to resolve parent directory symlinks, but not + # the tail, since we only want to uninstall symlinks, not their targets + path = os.path.join(normalize_path(head), os.path.normcase(tail)) + + if not os.path.exists(path): + return + if self._permitted(path): + self.paths.add(path) + else: + self._refuse.add(path) + + # __pycache__ files can show up after 'installed-files.txt' is created, + # due to imports + if os.path.splitext(path)[1] == '.py' and uses_pycache: + self.add(cache_from_source(path)) + + def add_pth(self, pth_file, entry): + # type: (str, str) -> None + pth_file = normalize_path(pth_file) + if self._permitted(pth_file): + if pth_file not in self.pth: + self.pth[pth_file] = UninstallPthEntries(pth_file) + self.pth[pth_file].add(entry) + else: + self._refuse.add(pth_file) + + def remove(self, auto_confirm=False, verbose=False): + # type: (bool, bool) -> None + """Remove paths in ``self.paths`` with confirmation (unless + ``auto_confirm`` is True).""" + + if not self.paths: + logger.info( + "Can't uninstall '%s'. No files were found to uninstall.", + self.dist.project_name, + ) + return + + dist_name_version = ( + self.dist.project_name + "-" + self.dist.version + ) + logger.info('Uninstalling %s:', dist_name_version) + + with indent_log(): + if auto_confirm or self._allowed_to_proceed(verbose): + moved = self._moved_paths + + for_rename = compress_for_rename(self.paths) + + for path in sorted(compact(for_rename)): + moved.stash(path) + logger.debug('Removing file or directory %s', path) + + for pth in self.pth.values(): + pth.remove() + + logger.info('Successfully uninstalled %s', dist_name_version) + + def _allowed_to_proceed(self, verbose): + # type: (bool) -> bool + """Display which files would be deleted and prompt for confirmation + """ + + def _display(msg, paths): + # type: (str, Iterable[str]) -> None + if not paths: + return + + logger.info(msg) + with indent_log(): + for path in sorted(compact(paths)): + logger.info(path) + + if not verbose: + will_remove, will_skip = compress_for_output_listing(self.paths) + else: + # In verbose mode, display all the files that are going to be + # deleted. + will_remove = set(self.paths) + will_skip = set() + + _display('Would remove:', will_remove) + _display('Would not remove (might be manually added):', will_skip) + _display('Would not remove (outside of prefix):', self._refuse) + if verbose: + _display('Will actually move:', compress_for_rename(self.paths)) + + return ask('Proceed (y/n)? ', ('y', 'n')) == 'y' + + def rollback(self): + # type: () -> None + """Rollback the changes previously made by remove().""" + if not self._moved_paths.can_rollback: + logger.error( + "Can't roll back %s; was not uninstalled", + self.dist.project_name, + ) + return + logger.info('Rolling back uninstall of %s', self.dist.project_name) + self._moved_paths.rollback() + for pth in self.pth.values(): + pth.rollback() + + def commit(self): + # type: () -> None + """Remove temporary save dir: rollback will no longer be possible.""" + self._moved_paths.commit() + + @classmethod + def from_dist(cls, dist): + # type: (Distribution) -> UninstallPathSet + dist_path = normalize_path(dist.location) + if not dist_is_local(dist): + logger.info( + "Not uninstalling %s at %s, outside environment %s", + dist.key, + dist_path, + sys.prefix, + ) + return cls(dist) + + if dist_path in {p for p in {sysconfig.get_path("stdlib"), + sysconfig.get_path("platstdlib")} + if p}: + logger.info( + "Not uninstalling %s at %s, as it is in the standard library.", + dist.key, + dist_path, + ) + return cls(dist) + + paths_to_remove = cls(dist) + develop_egg_link = egg_link_path(dist) + develop_egg_link_egg_info = '{}.egg-info'.format( + pkg_resources.to_filename(dist.project_name)) + egg_info_exists = dist.egg_info and os.path.exists(dist.egg_info) + # Special case for distutils installed package + distutils_egg_info = getattr(dist._provider, 'path', None) + + # Uninstall cases order do matter as in the case of 2 installs of the + # same package, pip needs to uninstall the currently detected version + if (egg_info_exists and dist.egg_info.endswith('.egg-info') and + not dist.egg_info.endswith(develop_egg_link_egg_info)): + # if dist.egg_info.endswith(develop_egg_link_egg_info), we + # are in fact in the develop_egg_link case + paths_to_remove.add(dist.egg_info) + if dist.has_metadata('installed-files.txt'): + for installed_file in dist.get_metadata( + 'installed-files.txt').splitlines(): + path = os.path.normpath( + os.path.join(dist.egg_info, installed_file) + ) + paths_to_remove.add(path) + # FIXME: need a test for this elif block + # occurs with --single-version-externally-managed/--record outside + # of pip + elif dist.has_metadata('top_level.txt'): + if dist.has_metadata('namespace_packages.txt'): + namespaces = dist.get_metadata('namespace_packages.txt') + else: + namespaces = [] + for top_level_pkg in [ + p for p + in dist.get_metadata('top_level.txt').splitlines() + if p and p not in namespaces]: + path = os.path.join(dist.location, top_level_pkg) + paths_to_remove.add(path) + paths_to_remove.add(path + '.py') + paths_to_remove.add(path + '.pyc') + paths_to_remove.add(path + '.pyo') + + elif distutils_egg_info: + raise UninstallationError( + "Cannot uninstall {!r}. It is a distutils installed project " + "and thus we cannot accurately determine which files belong " + "to it which would lead to only a partial uninstall.".format( + dist.project_name, + ) + ) + + elif dist.location.endswith('.egg'): + # package installed by easy_install + # We cannot match on dist.egg_name because it can slightly vary + # i.e. setuptools-0.6c11-py2.6.egg vs setuptools-0.6rc11-py2.6.egg + paths_to_remove.add(dist.location) + easy_install_egg = os.path.split(dist.location)[1] + easy_install_pth = os.path.join(os.path.dirname(dist.location), + 'easy-install.pth') + paths_to_remove.add_pth(easy_install_pth, './' + easy_install_egg) + + elif egg_info_exists and dist.egg_info.endswith('.dist-info'): + for path in uninstallation_paths(dist): + paths_to_remove.add(path) + + elif develop_egg_link: + # develop egg + with open(develop_egg_link, 'r') as fh: + link_pointer = os.path.normcase(fh.readline().strip()) + assert (link_pointer == dist.location), ( + 'Egg-link {} does not match installed location of {} ' + '(at {})'.format( + link_pointer, dist.project_name, dist.location) + ) + paths_to_remove.add(develop_egg_link) + easy_install_pth = os.path.join(os.path.dirname(develop_egg_link), + 'easy-install.pth') + paths_to_remove.add_pth(easy_install_pth, dist.location) + + else: + logger.debug( + 'Not sure how to uninstall: %s - Check: %s', + dist, dist.location, + ) + + # find distutils scripts= scripts + if dist.has_metadata('scripts') and dist.metadata_isdir('scripts'): + for script in dist.metadata_listdir('scripts'): + if dist_in_usersite(dist): + bin_dir = bin_user + else: + bin_dir = bin_py + paths_to_remove.add(os.path.join(bin_dir, script)) + if WINDOWS: + paths_to_remove.add(os.path.join(bin_dir, script) + '.bat') + + # find console_scripts + _scripts_to_remove = [] + console_scripts = dist.get_entry_map(group='console_scripts') + for name in console_scripts.keys(): + _scripts_to_remove.extend(_script_names(dist, name, False)) + # find gui_scripts + gui_scripts = dist.get_entry_map(group='gui_scripts') + for name in gui_scripts.keys(): + _scripts_to_remove.extend(_script_names(dist, name, True)) + + for s in _scripts_to_remove: + paths_to_remove.add(s) + + return paths_to_remove + + +class UninstallPthEntries(object): + def __init__(self, pth_file): + # type: (str) -> None + self.file = pth_file + self.entries = set() # type: Set[str] + self._saved_lines = None # type: Optional[List[bytes]] + + def add(self, entry): + # type: (str) -> None + entry = os.path.normcase(entry) + # On Windows, os.path.normcase converts the entry to use + # backslashes. This is correct for entries that describe absolute + # paths outside of site-packages, but all the others use forward + # slashes. + # os.path.splitdrive is used instead of os.path.isabs because isabs + # treats non-absolute paths with drive letter markings like c:foo\bar + # as absolute paths. It also does not recognize UNC paths if they don't + # have more than "\\sever\share". Valid examples: "\\server\share\" or + # "\\server\share\folder". Python 2.7.8+ support UNC in splitdrive. + if WINDOWS and not os.path.splitdrive(entry)[0]: + entry = entry.replace('\\', '/') + self.entries.add(entry) + + def remove(self): + # type: () -> None + logger.debug('Removing pth entries from %s:', self.file) + + # If the file doesn't exist, log a warning and return + if not os.path.isfile(self.file): + logger.warning( + "Cannot remove entries from nonexistent file %s", self.file + ) + return + with open(self.file, 'rb') as fh: + # windows uses '\r\n' with py3k, but uses '\n' with py2.x + lines = fh.readlines() + self._saved_lines = lines + if any(b'\r\n' in line for line in lines): + endline = '\r\n' + else: + endline = '\n' + # handle missing trailing newline + if lines and not lines[-1].endswith(endline.encode("utf-8")): + lines[-1] = lines[-1] + endline.encode("utf-8") + for entry in self.entries: + try: + logger.debug('Removing entry: %s', entry) + lines.remove((entry + endline).encode("utf-8")) + except ValueError: + pass + with open(self.file, 'wb') as fh: + fh.writelines(lines) + + def rollback(self): + # type: () -> bool + if self._saved_lines is None: + logger.error( + 'Cannot roll back changes to %s, none were made', self.file + ) + return False + logger.debug('Rolling %s back to previous state', self.file) + with open(self.file, 'wb') as fh: + fh.writelines(self._saved_lines) + return True diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb041e4ac05e0ec87d2f2e7007f18135877c28f7 GIT binary patch literal 224 zcmYk0F%H5o3`J9k0U>b^2I_$c2_a6v!U3YtT5TYWqc|<&vp4&u2>1Uf(9qXU4w@S$1Nc2x@gui(-FQF~>iAZqQPPfX-P;=|rt(^1!izh=CZ) z1z8Hq+9ZMP(6g07gC3(qP!8w^aP|mcOfC6Uxdyh<4W>Gq1{s14psi0By>W7t$@MAU X(30Aubs5ITbkkAYJKW~?USjnH<7Ggk literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/__pycache__/base.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/__pycache__/base.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..02924db781312369b688d7a38e4d590016abd376 GIT binary patch literal 1056 zcmZ`&&rjPh6t=EAL;WgnQ zEMNI)m$#2eFZzKekRG+`?@ta-*kFHm@Rl8YNRoqOujkolkO`3u1=!$Sp^fW1sI;LK<@>$CZ{sHKjx3q)7KbDkMA z1!|xRY#2cW3R7`^2GuMU#W1cf%~)11`a7{Mu(!_g^K1kSb?OoC)8j>9`nL^vQ*;fuoc|wzRD?CPgr?`IWqi0JCQO5AIM0nc z&2EmsAhza~GY5)E#X)Ug?GDMadq^JcPkJpIF;-&`gs7mNd=+Gt!}yI&%rQP52c0G@Feg~~T1M?W~ literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/base.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/base.py new file mode 100644 index 0000000..6d50555 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/base.py @@ -0,0 +1,21 @@ +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Callable, List + + from pip._internal.req.req_install import InstallRequirement + from pip._internal.req.req_set import RequirementSet + + InstallRequirementProvider = Callable[ + [str, InstallRequirement], InstallRequirement + ] + + +class BaseResolver(object): + def resolve(self, root_reqs, check_supported_wheels): + # type: (List[InstallRequirement], bool) -> RequirementSet + raise NotImplementedError() + + def get_installation_order(self, req_set): + # type: (RequirementSet) -> List[InstallRequirement] + raise NotImplementedError() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..184339a9344fabe7efac61afd18757c8c8833fe1 GIT binary patch literal 231 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/resolver.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/resolver.py new file mode 100644 index 0000000..d0fc1a7 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/resolver.py @@ -0,0 +1,473 @@ +"""Dependency Resolution + +The dependency resolution in pip is performed as follows: + +for top-level requirements: + a. only one spec allowed per project, regardless of conflicts or not. + otherwise a "double requirement" exception is raised + b. they override sub-dependency requirements. +for sub-dependencies + a. "first found, wins" (where the order is breadth first) +""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False +# mypy: disallow-untyped-defs=False + +import logging +import sys +from collections import defaultdict +from itertools import chain + +from pip._vendor.packaging import specifiers + +from pip._internal.exceptions import ( + BestVersionAlreadyInstalled, + DistributionNotFound, + HashError, + HashErrors, + UnsupportedPythonVersion, +) +from pip._internal.req.req_install import check_invalid_constraint_type +from pip._internal.req.req_set import RequirementSet +from pip._internal.resolution.base import BaseResolver +from pip._internal.utils.compatibility_tags import get_supported +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import dist_in_usersite, normalize_version_info +from pip._internal.utils.packaging import check_requires_python, get_requires_python +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import DefaultDict, List, Optional, Set, Tuple + + from pip._vendor.pkg_resources import Distribution + + from pip._internal.cache import WheelCache + from pip._internal.index.package_finder import PackageFinder + from pip._internal.models.link import Link + from pip._internal.operations.prepare import RequirementPreparer + from pip._internal.req.req_install import InstallRequirement + from pip._internal.resolution.base import InstallRequirementProvider + + DiscoveredDependencies = DefaultDict[str, List[InstallRequirement]] + +logger = logging.getLogger(__name__) + + +def _check_dist_requires_python( + dist, # type: Distribution + version_info, # type: Tuple[int, int, int] + ignore_requires_python=False, # type: bool +): + # type: (...) -> None + """ + Check whether the given Python version is compatible with a distribution's + "Requires-Python" value. + + :param version_info: A 3-tuple of ints representing the Python + major-minor-micro version to check. + :param ignore_requires_python: Whether to ignore the "Requires-Python" + value if the given Python version isn't compatible. + + :raises UnsupportedPythonVersion: When the given Python version isn't + compatible. + """ + requires_python = get_requires_python(dist) + try: + is_compatible = check_requires_python( + requires_python, version_info=version_info, + ) + except specifiers.InvalidSpecifier as exc: + logger.warning( + "Package %r has an invalid Requires-Python: %s", + dist.project_name, exc, + ) + return + + if is_compatible: + return + + version = '.'.join(map(str, version_info)) + if ignore_requires_python: + logger.debug( + 'Ignoring failed Requires-Python check for package %r: ' + '%s not in %r', + dist.project_name, version, requires_python, + ) + return + + raise UnsupportedPythonVersion( + 'Package {!r} requires a different Python: {} not in {!r}'.format( + dist.project_name, version, requires_python, + )) + + +class Resolver(BaseResolver): + """Resolves which packages need to be installed/uninstalled to perform \ + the requested operation without breaking the requirements of any package. + """ + + _allowed_strategies = {"eager", "only-if-needed", "to-satisfy-only"} + + def __init__( + self, + preparer, # type: RequirementPreparer + finder, # type: PackageFinder + wheel_cache, # type: Optional[WheelCache] + make_install_req, # type: InstallRequirementProvider + use_user_site, # type: bool + ignore_dependencies, # type: bool + ignore_installed, # type: bool + ignore_requires_python, # type: bool + force_reinstall, # type: bool + upgrade_strategy, # type: str + py_version_info=None, # type: Optional[Tuple[int, ...]] + ): + # type: (...) -> None + super(Resolver, self).__init__() + assert upgrade_strategy in self._allowed_strategies + + if py_version_info is None: + py_version_info = sys.version_info[:3] + else: + py_version_info = normalize_version_info(py_version_info) + + self._py_version_info = py_version_info + + self.preparer = preparer + self.finder = finder + self.wheel_cache = wheel_cache + + self.upgrade_strategy = upgrade_strategy + self.force_reinstall = force_reinstall + self.ignore_dependencies = ignore_dependencies + self.ignore_installed = ignore_installed + self.ignore_requires_python = ignore_requires_python + self.use_user_site = use_user_site + self._make_install_req = make_install_req + + self._discovered_dependencies = \ + defaultdict(list) # type: DiscoveredDependencies + + def resolve(self, root_reqs, check_supported_wheels): + # type: (List[InstallRequirement], bool) -> RequirementSet + """Resolve what operations need to be done + + As a side-effect of this method, the packages (and their dependencies) + are downloaded, unpacked and prepared for installation. This + preparation is done by ``pip.operations.prepare``. + + Once PyPI has static dependency metadata available, it would be + possible to move the preparation to become a step separated from + dependency resolution. + """ + requirement_set = RequirementSet( + check_supported_wheels=check_supported_wheels + ) + for req in root_reqs: + if req.constraint: + check_invalid_constraint_type(req) + requirement_set.add_requirement(req) + + # Actually prepare the files, and collect any exceptions. Most hash + # exceptions cannot be checked ahead of time, because + # _populate_link() needs to be called before we can make decisions + # based on link type. + discovered_reqs = [] # type: List[InstallRequirement] + hash_errors = HashErrors() + for req in chain(requirement_set.all_requirements, discovered_reqs): + try: + discovered_reqs.extend(self._resolve_one(requirement_set, req)) + except HashError as exc: + exc.req = req + hash_errors.append(exc) + + if hash_errors: + raise hash_errors + + return requirement_set + + def _is_upgrade_allowed(self, req): + # type: (InstallRequirement) -> bool + if self.upgrade_strategy == "to-satisfy-only": + return False + elif self.upgrade_strategy == "eager": + return True + else: + assert self.upgrade_strategy == "only-if-needed" + return req.user_supplied or req.constraint + + def _set_req_to_reinstall(self, req): + # type: (InstallRequirement) -> None + """ + Set a requirement to be installed. + """ + # Don't uninstall the conflict if doing a user install and the + # conflict is not a user install. + if not self.use_user_site or dist_in_usersite(req.satisfied_by): + req.should_reinstall = True + req.satisfied_by = None + + def _check_skip_installed(self, req_to_install): + # type: (InstallRequirement) -> Optional[str] + """Check if req_to_install should be skipped. + + This will check if the req is installed, and whether we should upgrade + or reinstall it, taking into account all the relevant user options. + + After calling this req_to_install will only have satisfied_by set to + None if the req_to_install is to be upgraded/reinstalled etc. Any + other value will be a dist recording the current thing installed that + satisfies the requirement. + + Note that for vcs urls and the like we can't assess skipping in this + routine - we simply identify that we need to pull the thing down, + then later on it is pulled down and introspected to assess upgrade/ + reinstalls etc. + + :return: A text reason for why it was skipped, or None. + """ + if self.ignore_installed: + return None + + req_to_install.check_if_exists(self.use_user_site) + if not req_to_install.satisfied_by: + return None + + if self.force_reinstall: + self._set_req_to_reinstall(req_to_install) + return None + + if not self._is_upgrade_allowed(req_to_install): + if self.upgrade_strategy == "only-if-needed": + return 'already satisfied, skipping upgrade' + return 'already satisfied' + + # Check for the possibility of an upgrade. For link-based + # requirements we have to pull the tree down and inspect to assess + # the version #, so it's handled way down. + if not req_to_install.link: + try: + self.finder.find_requirement(req_to_install, upgrade=True) + except BestVersionAlreadyInstalled: + # Then the best version is installed. + return 'already up-to-date' + except DistributionNotFound: + # No distribution found, so we squash the error. It will + # be raised later when we re-try later to do the install. + # Why don't we just raise here? + pass + + self._set_req_to_reinstall(req_to_install) + return None + + def _find_requirement_link(self, req): + # type: (InstallRequirement) -> Optional[Link] + upgrade = self._is_upgrade_allowed(req) + best_candidate = self.finder.find_requirement(req, upgrade) + if not best_candidate: + return None + + # Log a warning per PEP 592 if necessary before returning. + link = best_candidate.link + if link.is_yanked: + reason = link.yanked_reason or '' + msg = ( + # Mark this as a unicode string to prevent + # "UnicodeEncodeError: 'ascii' codec can't encode character" + # in Python 2 when the reason contains non-ascii characters. + u'The candidate selected for download or install is a ' + 'yanked version: {candidate}\n' + 'Reason for being yanked: {reason}' + ).format(candidate=best_candidate, reason=reason) + logger.warning(msg) + + return link + + def _populate_link(self, req): + # type: (InstallRequirement) -> None + """Ensure that if a link can be found for this, that it is found. + + Note that req.link may still be None - if the requirement is already + installed and not needed to be upgraded based on the return value of + _is_upgrade_allowed(). + + If preparer.require_hashes is True, don't use the wheel cache, because + cached wheels, always built locally, have different hashes than the + files downloaded from the index server and thus throw false hash + mismatches. Furthermore, cached wheels at present have undeterministic + contents due to file modification times. + """ + if req.link is None: + req.link = self._find_requirement_link(req) + + if self.wheel_cache is None or self.preparer.require_hashes: + return + cache_entry = self.wheel_cache.get_cache_entry( + link=req.link, + package_name=req.name, + supported_tags=get_supported(), + ) + if cache_entry is not None: + logger.debug('Using cached wheel link: %s', cache_entry.link) + if req.link is req.original_link and cache_entry.persistent: + req.original_link_is_in_wheel_cache = True + req.link = cache_entry.link + + def _get_dist_for(self, req): + # type: (InstallRequirement) -> Distribution + """Takes a InstallRequirement and returns a single AbstractDist \ + representing a prepared variant of the same. + """ + if req.editable: + return self.preparer.prepare_editable_requirement(req) + + # satisfied_by is only evaluated by calling _check_skip_installed, + # so it must be None here. + assert req.satisfied_by is None + skip_reason = self._check_skip_installed(req) + + if req.satisfied_by: + return self.preparer.prepare_installed_requirement( + req, skip_reason + ) + + # We eagerly populate the link, since that's our "legacy" behavior. + self._populate_link(req) + dist = self.preparer.prepare_linked_requirement(req) + + # NOTE + # The following portion is for determining if a certain package is + # going to be re-installed/upgraded or not and reporting to the user. + # This should probably get cleaned up in a future refactor. + + # req.req is only avail after unpack for URL + # pkgs repeat check_if_exists to uninstall-on-upgrade + # (#14) + if not self.ignore_installed: + req.check_if_exists(self.use_user_site) + + if req.satisfied_by: + should_modify = ( + self.upgrade_strategy != "to-satisfy-only" or + self.force_reinstall or + self.ignore_installed or + req.link.scheme == 'file' + ) + if should_modify: + self._set_req_to_reinstall(req) + else: + logger.info( + 'Requirement already satisfied (use --upgrade to upgrade):' + ' %s', req, + ) + return dist + + def _resolve_one( + self, + requirement_set, # type: RequirementSet + req_to_install, # type: InstallRequirement + ): + # type: (...) -> List[InstallRequirement] + """Prepare a single requirements file. + + :return: A list of additional InstallRequirements to also install. + """ + # Tell user what we are doing for this requirement: + # obtain (editable), skipping, processing (local url), collecting + # (remote url or package name) + if req_to_install.constraint or req_to_install.prepared: + return [] + + req_to_install.prepared = True + + # Parse and return dependencies + dist = self._get_dist_for(req_to_install) + # This will raise UnsupportedPythonVersion if the given Python + # version isn't compatible with the distribution's Requires-Python. + _check_dist_requires_python( + dist, version_info=self._py_version_info, + ignore_requires_python=self.ignore_requires_python, + ) + + more_reqs = [] # type: List[InstallRequirement] + + def add_req(subreq, extras_requested): + sub_install_req = self._make_install_req( + str(subreq), + req_to_install, + ) + parent_req_name = req_to_install.name + to_scan_again, add_to_parent = requirement_set.add_requirement( + sub_install_req, + parent_req_name=parent_req_name, + extras_requested=extras_requested, + ) + if parent_req_name and add_to_parent: + self._discovered_dependencies[parent_req_name].append( + add_to_parent + ) + more_reqs.extend(to_scan_again) + + with indent_log(): + # We add req_to_install before its dependencies, so that we + # can refer to it when adding dependencies. + if not requirement_set.has_requirement(req_to_install.name): + # 'unnamed' requirements will get added here + # 'unnamed' requirements can only come from being directly + # provided by the user. + assert req_to_install.user_supplied + requirement_set.add_requirement( + req_to_install, parent_req_name=None, + ) + + if not self.ignore_dependencies: + if req_to_install.extras: + logger.debug( + "Installing extra requirements: %r", + ','.join(req_to_install.extras), + ) + missing_requested = sorted( + set(req_to_install.extras) - set(dist.extras) + ) + for missing in missing_requested: + logger.warning( + "%s does not provide the extra '%s'", + dist, missing + ) + + available_requested = sorted( + set(dist.extras) & set(req_to_install.extras) + ) + for subreq in dist.requires(available_requested): + add_req(subreq, extras_requested=available_requested) + + return more_reqs + + def get_installation_order(self, req_set): + # type: (RequirementSet) -> List[InstallRequirement] + """Create the installation order. + + The installation order is topological - requirements are installed + before the requiring thing. We break cycles at an arbitrary point, + and make no other guarantees. + """ + # The current implementation, which we may change at any point + # installs the user specified things in the order given, except when + # dependencies must come earlier to achieve topological order. + order = [] + ordered_reqs = set() # type: Set[InstallRequirement] + + def schedule(req): + if req.satisfied_by or req in ordered_reqs: + return + if req.constraint: + return + ordered_reqs.add(req) + for dep in self._discovered_dependencies[req.name]: + schedule(dep) + order.append(req) + + for install_req in req_set.requirements.values(): + schedule(install_req) + return order diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3a073bc450ebdcdbf00d397397aa04d26b3fd35 GIT binary patch literal 235 zcmYjLF%H5o3``{kgw%&HP!CK<2=M|I9uS4rY658z#c5Fo{=hf*5-U%Di3x`VEZx~Y zoljO}ITKv^@>01!GW}P<%a%bCrbg_=yx84D%<_-kSJ1vgKx>Up>FBj1?|@*o#u`;V1Xsp7|?wg%+=vUc1`tz#)8u~R>K);~+ z=h?!#)>!-}cA+)&xV%2#U2oIlVx32adc4qegD~*AuI~-G6S#d2qQ$j9My~IF%pYxg zg7^|JH6EBPl}NDQEF-S&cqabeXBn8)0RcMXzt^qBa~qpYIH%cypB zY42+5S_G3Y;{g2+w0(VF-!qu`OyAX*^~~5cp6kyIY&+NP>X$AMJZ|~kMr*JW^}^uY=6fyafp*|_AG!~? zYz@3Y%kcte4=Tf|GW54ee@XK(r@0%@UURS$7p~I6pAE#dWeE2#6m9tCW+?h@qzu`- z>W8qayw*$!hxyO^?}dK3Va9nGiioo~pG=Cat}YW*!}cs*NSmZFEZx!4kHYh}$DsqX84r~X8^CHK2 z6YnL#hi2sU;hBjn%`wH4Q<8&{U`nVe8j%+1`&wk|Yy0rwL?lzts)B?U6b=X*v+K)Q z8FIWoh<4rrfh1DR9M&@I)! zF%l`&N5c@rIJSTok7flcY>Ke&(8$}M84I_R5iTV-qMX!XBLTH7MC)J?qH0^lzMiTm zwl>1hpBU&+7Z<^7R+N(C0P%)ggpPA16~-8z%LtPpIawU?@m=ki_B?eQU3{Mye(xBr z@D7sBaek0tIqe(C_>_Ifi>N63{1^?g54^*W)d-e>0!-M-T+#O6!dn*F7KPAL9dFDi z2gf#*4}BL?8~M2CNso{{=yE}3kE`u4TI&Or3F0}M=uWv?!%_;2b79ouA~QJS`E!l~ z>~@?VVM(d7s!>Gbml6BJ#VM^SvZ)=Canl{ry4VK{oO&RkxY@n~|0@jy7u@GSKMCg} zzl-f|7(@tj8P7dV^2wo*$XozqCFx|={_~!6q#Jn>Nsu`kJ3l9>RkY-W7c$b$khL47 z7)GQF={RxGarzI4Jz`}b+){rh!qvmOyiW_EpS@_LerE~krmLH$Y3>-OqhxX5IUC*iiw z#-4c%=voAesXEv!832H8>hWMOzdV~b{%=o=X(Cc~(GK(HY4Hg~+> zf!gzwa-l=oq&j$D7pE~*R-~^nS*o*<>7aR79rl=6BQaSJMlUhj!~lXEzAY$@kJYS2 z+x|_eQF~a+YLo_#AQI)|RhmK2#E@bdM*Bt*sz1b=Owg)$r9i$*z;zT!rzl$o zU=~pd1e$`zNTjL9L~jK}`l!ARG6A3IITUSm5(TWzp{-7%XxnJ36Diu6GbyX#Y+7Oq zY!Sa@b_VXWBuK_nYCnP2FDQbKLMw%9>H?>US917FoThWfu_pg-fOYAk5s=maOL7FV zCkMK67LUw1Le6um<1@g2kDGr#88;`Idv&NeS#zA`{zsTeaq<#Xu3$JyRcQ~a6ICj} zB!C=0)FzEnT*|34!3e~N*NMm>-o@zeXsWWBIb4{q8lCA*876cLr^I<8tGEm-RtI3; z=WIX2Gvg^)l2^vKgjG57BDxa!Lx%6!$zC%Qua2z@w?&sbJ}y|E9?v#IaU=_#Xw-?C z@zHk?3&)iwUet3$a>zUKS-OBb4&g99-~kRFU60E@rP3fL~~e1Msm)JPE|Zc=rNsx_)Ur0O&KJf z77N!Ebe!tEp(w_eTunF)m9cS>57P_NG-`G;xrtHtAMvpS(ar!Oi8*kI^P`T9jwnz? zU#6mjY9zstt&HGC5QfFe(-PookNdJokt8a##(ZkA+v?b*Zn@%oxIs5($!!gtIaHoM sPW`ccHTi>(*DlBo|UQIbVj8Yv*cThy5A8 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..acefb40d71a398a10c5053079e4dc73d23e8368c GIT binary patch literal 11584 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 Kp*o`H^#2DW-+P$= literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f613e9cc8b528ed3d35691f4df3564d4aa13354 GIT binary patch literal 3493 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21cf53ce6c92f14a8f2ca3c5aacee178f72dcb99 GIT binary patch literal 3242 zcmb7GNpsvp6xK5Pj1$K(R7_Ypge+5WGzSi;xF`y6APLKmGH}RTRI<7~BS%t;?jD;l zP8C(*N)B=d0PMr9jG#j>oil)@l%j?(Q`}+0Q3RYHH7M{`5KZ9=Dvi_jP z@>4Vvv%iMsk0cGb9%GzZP3 zHE3bH#_MrA=?pr_%3uXHt~mG19-O~#@dj`HZ1JY3K63}FXt#J9?RL?=z&qbq-IbR> zVRh}i&Bb0Yjt!4OgJyFm%$IUF6bg;bCxI3_B9qD#?X|BSKYHwMKlpU}3xDUke*a+}&O(`Ffr)nE<1jKKCe27FrWV0#k9|8T4978NCU_!PKyG5;1@9t;Vi4mP zAyBbQu@%gWf|QN*IEX#=SdLi|4M&EhLcoP&nUV()7qAk*mWh;$G@M{nEn`GdBGE=+ zYtRZ2mr+5K8muB=#mAvwYMh!V5gvQE$0k_eFh~sz2fNsOcm^bxY!+i7z+~{Q*|t$J zyT!H(RwUCB(Mc91gh;TFJY+<2Ce)r(iQZ&J#4+MPz+ih6WWb6LK#|yDBV#hX)$3t~ zmrb(3i)2ra)q$Ak-Y&KPm_y>E>#7F!_+?S7pw_J@%AnjuNcn4XQ|<3g{OR81ulot` zVi&a^7=Lc_!pF9D>tC+@_qq z&B0enY0?`a427T9$s2p4S*0H^B zSFH_5&>hRQKA87ySWlf}2NuqOtvos>R6lmm?;7{_3U`j({VL7o?l1Opha{>vOT~s9 zH6Hdq`+AFA)1(~Bho)Oo=dpBNp%bK5salH*jmaxfx+n7*rAJ_}k!v*AM1oCqqZ&#i zW?rA}Ua?DMu}+qq`A#A+ZlOnaP*~2o)3IB2#cA0`mzFtNHt%<<#4cg-{k-M-iR9y$ z>K)(z9!ISlQLn+FdYcN`f~A5GC@8&k0k0;e8&2a=(ev*T_W))KiG#dBmkN1K$^#sJMb6ulqiiq3^5rsOvfvH>v1Su}MXt z*dEmuj1;wkmUl652d^giXyB%3R2Dx)qy6q$-VS9Pi;(VTU4CQK>E1$wiq3RSUpJl) z0p(J8iwhjpQhc?dW1qiKn9VMI5BGhnJu^XcLq)lq*QO1+sa2hND!cgdR!wTtonMAu ms487J1;Df7${Qb)x7dgDIjkuwI(EmQU&UT^R^5iXdi`&%kwLNm literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..90c0eeea5c3b6980cb4c0096cc63718b07295c96 GIT binary patch literal 7080 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 X4k9I~DpjS1kL}{B)*7|%*53XvZnpR3 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d819926542433fa4ed04a1500ecb19b37384d92e GIT binary patch literal 7929 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/base.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/base.py new file mode 100644 index 0000000..7eb8a17 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/base.py @@ -0,0 +1,156 @@ +from pip._vendor.packaging.specifiers import SpecifierSet +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import FrozenSet, Iterable, Optional, Tuple + + from pip._vendor.packaging.version import _BaseVersion + + from pip._internal.models.link import Link + + CandidateLookup = Tuple[ + Optional["Candidate"], + Optional[InstallRequirement], + ] + + +def format_name(project, extras): + # type: (str, FrozenSet[str]) -> str + if not extras: + return project + canonical_extras = sorted(canonicalize_name(e) for e in extras) + return "{}[{}]".format(project, ",".join(canonical_extras)) + + +class Constraint(object): + def __init__(self, specifier, hashes): + # type: (SpecifierSet, Hashes) -> None + self.specifier = specifier + self.hashes = hashes + + @classmethod + def empty(cls): + # type: () -> Constraint + return Constraint(SpecifierSet(), Hashes()) + + @classmethod + def from_ireq(cls, ireq): + # type: (InstallRequirement) -> Constraint + return Constraint(ireq.specifier, ireq.hashes(trust_internet=False)) + + def __nonzero__(self): + # type: () -> bool + return bool(self.specifier) or bool(self.hashes) + + def __bool__(self): + # type: () -> bool + return self.__nonzero__() + + def __and__(self, other): + # type: (InstallRequirement) -> Constraint + if not isinstance(other, InstallRequirement): + return NotImplemented + specifier = self.specifier & other.specifier + hashes = self.hashes & other.hashes(trust_internet=False) + return Constraint(specifier, hashes) + + def is_satisfied_by(self, candidate): + # type: (Candidate) -> bool + # We can safely always allow prereleases here since PackageFinder + # already implements the prerelease logic, and would have filtered out + # prerelease candidates if the user does not expect them. + return self.specifier.contains(candidate.version, prereleases=True) + + +class Requirement(object): + @property + def project_name(self): + # type: () -> str + """The "project name" of a requirement. + + This is different from ``name`` if this requirement contains extras, + in which case ``name`` would contain the ``[...]`` part, while this + refers to the name of the project. + """ + raise NotImplementedError("Subclass should override") + + @property + def name(self): + # type: () -> str + """The name identifying this requirement in the resolver. + + This is different from ``project_name`` if this requirement contains + extras, where ``project_name`` would not contain the ``[...]`` part. + """ + raise NotImplementedError("Subclass should override") + + def is_satisfied_by(self, candidate): + # type: (Candidate) -> bool + return False + + def get_candidate_lookup(self): + # type: () -> CandidateLookup + raise NotImplementedError("Subclass should override") + + def format_for_error(self): + # type: () -> str + raise NotImplementedError("Subclass should override") + + +class Candidate(object): + @property + def project_name(self): + # type: () -> str + """The "project name" of the candidate. + + This is different from ``name`` if this candidate contains extras, + in which case ``name`` would contain the ``[...]`` part, while this + refers to the name of the project. + """ + raise NotImplementedError("Override in subclass") + + @property + def name(self): + # type: () -> str + """The name identifying this candidate in the resolver. + + This is different from ``project_name`` if this candidate contains + extras, where ``project_name`` would not contain the ``[...]`` part. + """ + raise NotImplementedError("Override in subclass") + + @property + def version(self): + # type: () -> _BaseVersion + raise NotImplementedError("Override in subclass") + + @property + def is_installed(self): + # type: () -> bool + raise NotImplementedError("Override in subclass") + + @property + def is_editable(self): + # type: () -> bool + raise NotImplementedError("Override in subclass") + + @property + def source_link(self): + # type: () -> Optional[Link] + raise NotImplementedError("Override in subclass") + + def iter_dependencies(self, with_requires): + # type: (bool) -> Iterable[Optional[Requirement]] + raise NotImplementedError("Override in subclass") + + def get_install_requirement(self): + # type: () -> Optional[InstallRequirement] + raise NotImplementedError("Override in subclass") + + def format_for_error(self): + # type: () -> str + raise NotImplementedError("Subclass should override") diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/candidates.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/candidates.py new file mode 100644 index 0000000..5211a17 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/candidates.py @@ -0,0 +1,604 @@ +import logging +import sys + +from pip._vendor.packaging.specifiers import InvalidSpecifier, SpecifierSet +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import Version, parse as parse_version + +from pip._internal.exceptions import HashError, MetadataInconsistent +from pip._internal.models.wheel import Wheel +from pip._internal.req.constructors import ( + install_req_from_editable, + install_req_from_line, +) +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.misc import dist_is_editable, normalize_version_info +from pip._internal.utils.packaging import get_requires_python +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +from .base import Candidate, format_name + +if MYPY_CHECK_RUNNING: + from typing import Any, FrozenSet, Iterable, Optional, Tuple, Union + + from pip._vendor.packaging.version import _BaseVersion + from pip._vendor.pkg_resources import Distribution + + from pip._internal.models.link import Link + + from .base import Requirement + from .factory import Factory + + BaseCandidate = Union[ + "AlreadyInstalledCandidate", + "EditableCandidate", + "LinkCandidate", + ] + + +logger = logging.getLogger(__name__) + + +def make_install_req_from_link(link, template): + # type: (Link, InstallRequirement) -> InstallRequirement + assert not template.editable, "template is editable" + if template.req: + line = str(template.req) + else: + line = link.url + ireq = install_req_from_line( + line, + user_supplied=template.user_supplied, + comes_from=template.comes_from, + use_pep517=template.use_pep517, + isolated=template.isolated, + constraint=template.constraint, + options=dict( + install_options=template.install_options, + global_options=template.global_options, + hashes=template.hash_options + ), + ) + ireq.original_link = template.original_link + ireq.link = link + return ireq + + +def make_install_req_from_editable(link, template): + # type: (Link, InstallRequirement) -> InstallRequirement + assert template.editable, "template not editable" + return install_req_from_editable( + link.url, + user_supplied=template.user_supplied, + comes_from=template.comes_from, + use_pep517=template.use_pep517, + isolated=template.isolated, + constraint=template.constraint, + options=dict( + install_options=template.install_options, + global_options=template.global_options, + hashes=template.hash_options + ), + ) + + +def make_install_req_from_dist(dist, template): + # type: (Distribution, InstallRequirement) -> InstallRequirement + project_name = canonicalize_name(dist.project_name) + if template.req: + line = str(template.req) + elif template.link: + line = "{} @ {}".format(project_name, template.link.url) + else: + line = "{}=={}".format(project_name, dist.parsed_version) + ireq = install_req_from_line( + line, + user_supplied=template.user_supplied, + comes_from=template.comes_from, + use_pep517=template.use_pep517, + isolated=template.isolated, + constraint=template.constraint, + options=dict( + install_options=template.install_options, + global_options=template.global_options, + hashes=template.hash_options + ), + ) + ireq.satisfied_by = dist + return ireq + + +class _InstallRequirementBackedCandidate(Candidate): + """A candidate backed by an ``InstallRequirement``. + + This represents a package request with the target not being already + in the environment, and needs to be fetched and installed. The backing + ``InstallRequirement`` is responsible for most of the leg work; this + class exposes appropriate information to the resolver. + + :param link: The link passed to the ``InstallRequirement``. The backing + ``InstallRequirement`` will use this link to fetch the distribution. + :param source_link: The link this candidate "originates" from. This is + different from ``link`` when the link is found in the wheel cache. + ``link`` would point to the wheel cache, while this points to the + found remote link (e.g. from pypi.org). + """ + is_installed = False + + def __init__( + self, + link, # type: Link + source_link, # type: Link + ireq, # type: InstallRequirement + factory, # type: Factory + name=None, # type: Optional[str] + version=None, # type: Optional[_BaseVersion] + ): + # type: (...) -> None + self._link = link + self._source_link = source_link + self._factory = factory + self._ireq = ireq + self._name = name + self._version = version + self.dist = self._prepare() + + def __str__(self): + # type: () -> str + return "{} {}".format(self.name, self.version) + + def __repr__(self): + # type: () -> str + return "{class_name}({link!r})".format( + class_name=self.__class__.__name__, + link=str(self._link), + ) + + def __hash__(self): + # type: () -> int + return hash((self.__class__, self._link)) + + def __eq__(self, other): + # type: (Any) -> bool + if isinstance(other, self.__class__): + return self._link == other._link + return False + + # Needed for Python 2, which does not implement this by default + def __ne__(self, other): + # type: (Any) -> bool + return not self.__eq__(other) + + @property + def source_link(self): + # type: () -> Optional[Link] + return self._source_link + + @property + def project_name(self): + # type: () -> str + """The normalised name of the project the candidate refers to""" + if self._name is None: + self._name = canonicalize_name(self.dist.project_name) + return self._name + + @property + def name(self): + # type: () -> str + return self.project_name + + @property + def version(self): + # type: () -> _BaseVersion + if self._version is None: + self._version = parse_version(self.dist.version) + return self._version + + def format_for_error(self): + # type: () -> str + return "{} {} (from {})".format( + self.name, + self.version, + self._link.file_path if self._link.is_file else self._link + ) + + def _prepare_distribution(self): + # type: () -> Distribution + raise NotImplementedError("Override in subclass") + + def _check_metadata_consistency(self, dist): + # type: (Distribution) -> None + """Check for consistency of project name and version of dist.""" + name = canonicalize_name(dist.project_name) + if self._name is not None and self._name != name: + raise MetadataInconsistent(self._ireq, "name", dist.project_name) + version = parse_version(dist.version) + if self._version is not None and self._version != version: + raise MetadataInconsistent(self._ireq, "version", dist.version) + + def _prepare(self): + # type: () -> Distribution + try: + dist = self._prepare_distribution() + except HashError as e: + # Provide HashError the underlying ireq that caused it. This + # provides context for the resulting error message to show the + # offending line to the user. + e.req = self._ireq + raise + self._check_metadata_consistency(dist) + return dist + + def _get_requires_python_dependency(self): + # type: () -> Optional[Requirement] + requires_python = get_requires_python(self.dist) + if requires_python is None: + return None + try: + spec = SpecifierSet(requires_python) + except InvalidSpecifier as e: + message = "Package %r has an invalid Requires-Python: %s" + logger.warning(message, self.name, e) + return None + return self._factory.make_requires_python_requirement(spec) + + def iter_dependencies(self, with_requires): + # type: (bool) -> Iterable[Optional[Requirement]] + requires = self.dist.requires() if with_requires else () + for r in requires: + yield self._factory.make_requirement_from_spec(str(r), self._ireq) + yield self._get_requires_python_dependency() + + def get_install_requirement(self): + # type: () -> Optional[InstallRequirement] + return self._ireq + + +class LinkCandidate(_InstallRequirementBackedCandidate): + is_editable = False + + def __init__( + self, + link, # type: Link + template, # type: InstallRequirement + factory, # type: Factory + name=None, # type: Optional[str] + version=None, # type: Optional[_BaseVersion] + ): + # type: (...) -> None + source_link = link + cache_entry = factory.get_wheel_cache_entry(link, name) + if cache_entry is not None: + logger.debug("Using cached wheel link: %s", cache_entry.link) + link = cache_entry.link + ireq = make_install_req_from_link(link, template) + assert ireq.link == link + if ireq.link.is_wheel and not ireq.link.is_file: + wheel = Wheel(ireq.link.filename) + wheel_name = canonicalize_name(wheel.name) + assert name == wheel_name, ( + "{!r} != {!r} for wheel".format(name, wheel_name) + ) + # Version may not be present for PEP 508 direct URLs + if version is not None: + wheel_version = Version(wheel.version) + assert version == wheel_version, ( + "{!r} != {!r} for wheel {}".format( + version, wheel_version, name + ) + ) + + if (cache_entry is not None and + cache_entry.persistent and + template.link is template.original_link): + ireq.original_link_is_in_wheel_cache = True + + super(LinkCandidate, self).__init__( + link=link, + source_link=source_link, + ireq=ireq, + factory=factory, + name=name, + version=version, + ) + + def _prepare_distribution(self): + # type: () -> Distribution + return self._factory.preparer.prepare_linked_requirement( + self._ireq, parallel_builds=True, + ) + + +class EditableCandidate(_InstallRequirementBackedCandidate): + is_editable = True + + def __init__( + self, + link, # type: Link + template, # type: InstallRequirement + factory, # type: Factory + name=None, # type: Optional[str] + version=None, # type: Optional[_BaseVersion] + ): + # type: (...) -> None + super(EditableCandidate, self).__init__( + link=link, + source_link=link, + ireq=make_install_req_from_editable(link, template), + factory=factory, + name=name, + version=version, + ) + + def _prepare_distribution(self): + # type: () -> Distribution + return self._factory.preparer.prepare_editable_requirement(self._ireq) + + +class AlreadyInstalledCandidate(Candidate): + is_installed = True + source_link = None + + def __init__( + self, + dist, # type: Distribution + template, # type: InstallRequirement + factory, # type: Factory + ): + # type: (...) -> None + self.dist = dist + self._ireq = make_install_req_from_dist(dist, template) + self._factory = factory + + # This is just logging some messages, so we can do it eagerly. + # The returned dist would be exactly the same as self.dist because we + # set satisfied_by in make_install_req_from_dist. + # TODO: Supply reason based on force_reinstall and upgrade_strategy. + skip_reason = "already satisfied" + factory.preparer.prepare_installed_requirement(self._ireq, skip_reason) + + def __str__(self): + # type: () -> str + return str(self.dist) + + def __repr__(self): + # type: () -> str + return "{class_name}({distribution!r})".format( + class_name=self.__class__.__name__, + distribution=self.dist, + ) + + def __hash__(self): + # type: () -> int + return hash((self.__class__, self.name, self.version)) + + def __eq__(self, other): + # type: (Any) -> bool + if isinstance(other, self.__class__): + return self.name == other.name and self.version == other.version + return False + + # Needed for Python 2, which does not implement this by default + def __ne__(self, other): + # type: (Any) -> bool + return not self.__eq__(other) + + @property + def project_name(self): + # type: () -> str + return canonicalize_name(self.dist.project_name) + + @property + def name(self): + # type: () -> str + return self.project_name + + @property + def version(self): + # type: () -> _BaseVersion + return parse_version(self.dist.version) + + @property + def is_editable(self): + # type: () -> bool + return dist_is_editable(self.dist) + + def format_for_error(self): + # type: () -> str + return "{} {} (Installed)".format(self.name, self.version) + + def iter_dependencies(self, with_requires): + # type: (bool) -> Iterable[Optional[Requirement]] + if not with_requires: + return + for r in self.dist.requires(): + yield self._factory.make_requirement_from_spec(str(r), self._ireq) + + def get_install_requirement(self): + # type: () -> Optional[InstallRequirement] + return None + + +class ExtrasCandidate(Candidate): + """A candidate that has 'extras', indicating additional dependencies. + + Requirements can be for a project with dependencies, something like + foo[extra]. The extras don't affect the project/version being installed + directly, but indicate that we need additional dependencies. We model that + by having an artificial ExtrasCandidate that wraps the "base" candidate. + + The ExtrasCandidate differs from the base in the following ways: + + 1. It has a unique name, of the form foo[extra]. This causes the resolver + to treat it as a separate node in the dependency graph. + 2. When we're getting the candidate's dependencies, + a) We specify that we want the extra dependencies as well. + b) We add a dependency on the base candidate. + See below for why this is needed. + 3. We return None for the underlying InstallRequirement, as the base + candidate will provide it, and we don't want to end up with duplicates. + + The dependency on the base candidate is needed so that the resolver can't + decide that it should recommend foo[extra1] version 1.0 and foo[extra2] + version 2.0. Having those candidates depend on foo=1.0 and foo=2.0 + respectively forces the resolver to recognise that this is a conflict. + """ + def __init__( + self, + base, # type: BaseCandidate + extras, # type: FrozenSet[str] + ): + # type: (...) -> None + self.base = base + self.extras = extras + + def __str__(self): + # type: () -> str + name, rest = str(self.base).split(" ", 1) + return "{}[{}] {}".format(name, ",".join(self.extras), rest) + + def __repr__(self): + # type: () -> str + return "{class_name}(base={base!r}, extras={extras!r})".format( + class_name=self.__class__.__name__, + base=self.base, + extras=self.extras, + ) + + def __hash__(self): + # type: () -> int + return hash((self.base, self.extras)) + + def __eq__(self, other): + # type: (Any) -> bool + if isinstance(other, self.__class__): + return self.base == other.base and self.extras == other.extras + return False + + # Needed for Python 2, which does not implement this by default + def __ne__(self, other): + # type: (Any) -> bool + return not self.__eq__(other) + + @property + def project_name(self): + # type: () -> str + return self.base.project_name + + @property + def name(self): + # type: () -> str + """The normalised name of the project the candidate refers to""" + return format_name(self.base.project_name, self.extras) + + @property + def version(self): + # type: () -> _BaseVersion + return self.base.version + + def format_for_error(self): + # type: () -> str + return "{} [{}]".format( + self.base.format_for_error(), + ", ".join(sorted(self.extras)) + ) + + @property + def is_installed(self): + # type: () -> bool + return self.base.is_installed + + @property + def is_editable(self): + # type: () -> bool + return self.base.is_editable + + @property + def source_link(self): + # type: () -> Optional[Link] + return self.base.source_link + + def iter_dependencies(self, with_requires): + # type: (bool) -> Iterable[Optional[Requirement]] + factory = self.base._factory + + # Add a dependency on the exact base + # (See note 2b in the class docstring) + yield factory.make_requirement_from_candidate(self.base) + if not with_requires: + return + + # The user may have specified extras that the candidate doesn't + # support. We ignore any unsupported extras here. + valid_extras = self.extras.intersection(self.base.dist.extras) + invalid_extras = self.extras.difference(self.base.dist.extras) + for extra in sorted(invalid_extras): + logger.warning( + "%s %s does not provide the extra '%s'", + self.base.name, + self.version, + extra + ) + + for r in self.base.dist.requires(valid_extras): + requirement = factory.make_requirement_from_spec( + str(r), self.base._ireq, valid_extras, + ) + if requirement: + yield requirement + + def get_install_requirement(self): + # type: () -> Optional[InstallRequirement] + # We don't return anything here, because we always + # depend on the base candidate, and we'll get the + # install requirement from that. + return None + + +class RequiresPythonCandidate(Candidate): + is_installed = False + source_link = None + + def __init__(self, py_version_info): + # type: (Optional[Tuple[int, ...]]) -> None + if py_version_info is not None: + version_info = normalize_version_info(py_version_info) + else: + version_info = sys.version_info[:3] + self._version = Version(".".join(str(c) for c in version_info)) + + # We don't need to implement __eq__() and __ne__() since there is always + # only one RequiresPythonCandidate in a resolution, i.e. the host Python. + # The built-in object.__eq__() and object.__ne__() do exactly what we want. + + def __str__(self): + # type: () -> str + return "Python {}".format(self._version) + + @property + def project_name(self): + # type: () -> str + # Avoid conflicting with the PyPI package "Python". + return "" + + @property + def name(self): + # type: () -> str + return self.project_name + + @property + def version(self): + # type: () -> _BaseVersion + return self._version + + def format_for_error(self): + # type: () -> str + return "Python {}".format(self.version) + + def iter_dependencies(self, with_requires): + # type: (bool) -> Iterable[Optional[Requirement]] + return () + + def get_install_requirement(self): + # type: () -> Optional[InstallRequirement] + return None diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/factory.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/factory.py new file mode 100644 index 0000000..e81595b --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/factory.py @@ -0,0 +1,504 @@ +import logging + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import ( + DistributionNotFound, + InstallationError, + InstallationSubprocessError, + MetadataInconsistent, + UnsupportedPythonVersion, + UnsupportedWheel, +) +from pip._internal.models.wheel import Wheel +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.compatibility_tags import get_supported +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.misc import ( + dist_in_site_packages, + dist_in_usersite, + get_installed_distributions, +) +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.virtualenv import running_under_virtualenv + +from .base import Constraint +from .candidates import ( + AlreadyInstalledCandidate, + EditableCandidate, + ExtrasCandidate, + LinkCandidate, + RequiresPythonCandidate, +) +from .found_candidates import FoundCandidates +from .requirements import ( + ExplicitRequirement, + RequiresPythonRequirement, + SpecifierRequirement, + UnsatisfiableRequirement, +) + +if MYPY_CHECK_RUNNING: + from typing import ( + Dict, + FrozenSet, + Iterable, + Iterator, + List, + Optional, + Sequence, + Set, + Tuple, + TypeVar, + ) + + from pip._vendor.packaging.specifiers import SpecifierSet + from pip._vendor.packaging.version import _BaseVersion + from pip._vendor.pkg_resources import Distribution + from pip._vendor.resolvelib import ResolutionImpossible + + from pip._internal.cache import CacheEntry, WheelCache + from pip._internal.index.package_finder import PackageFinder + from pip._internal.models.link import Link + from pip._internal.operations.prepare import RequirementPreparer + from pip._internal.resolution.base import InstallRequirementProvider + + from .base import Candidate, Requirement + from .candidates import BaseCandidate + + C = TypeVar("C") + Cache = Dict[Link, C] + VersionCandidates = Dict[_BaseVersion, Candidate] + + +logger = logging.getLogger(__name__) + + +class Factory(object): + def __init__( + self, + finder, # type: PackageFinder + preparer, # type: RequirementPreparer + make_install_req, # type: InstallRequirementProvider + wheel_cache, # type: Optional[WheelCache] + use_user_site, # type: bool + force_reinstall, # type: bool + ignore_installed, # type: bool + ignore_requires_python, # type: bool + py_version_info=None, # type: Optional[Tuple[int, ...]] + ): + # type: (...) -> None + self._finder = finder + self.preparer = preparer + self._wheel_cache = wheel_cache + self._python_candidate = RequiresPythonCandidate(py_version_info) + self._make_install_req_from_spec = make_install_req + self._use_user_site = use_user_site + self._force_reinstall = force_reinstall + self._ignore_requires_python = ignore_requires_python + + self._build_failures = {} # type: Cache[InstallationError] + self._link_candidate_cache = {} # type: Cache[LinkCandidate] + self._editable_candidate_cache = {} # type: Cache[EditableCandidate] + self._installed_candidate_cache = { + } # type: Dict[str, AlreadyInstalledCandidate] + + if not ignore_installed: + self._installed_dists = { + canonicalize_name(dist.project_name): dist + for dist in get_installed_distributions(local_only=False) + } + else: + self._installed_dists = {} + + @property + def force_reinstall(self): + # type: () -> bool + return self._force_reinstall + + def _make_candidate_from_dist( + self, + dist, # type: Distribution + extras, # type: FrozenSet[str] + template, # type: InstallRequirement + ): + # type: (...) -> Candidate + try: + base = self._installed_candidate_cache[dist.key] + except KeyError: + base = AlreadyInstalledCandidate(dist, template, factory=self) + self._installed_candidate_cache[dist.key] = base + if extras: + return ExtrasCandidate(base, extras) + return base + + def _make_candidate_from_link( + self, + link, # type: Link + extras, # type: FrozenSet[str] + template, # type: InstallRequirement + name, # type: Optional[str] + version, # type: Optional[_BaseVersion] + ): + # type: (...) -> Optional[Candidate] + # TODO: Check already installed candidate, and use it if the link and + # editable flag match. + + if link in self._build_failures: + # We already tried this candidate before, and it does not build. + # Don't bother trying again. + return None + + if template.editable: + if link not in self._editable_candidate_cache: + try: + self._editable_candidate_cache[link] = EditableCandidate( + link, template, factory=self, + name=name, version=version, + ) + except (InstallationSubprocessError, MetadataInconsistent) as e: + logger.warning("Discarding %s. %s", link, e) + self._build_failures[link] = e + return None + base = self._editable_candidate_cache[link] # type: BaseCandidate + else: + if link not in self._link_candidate_cache: + try: + self._link_candidate_cache[link] = LinkCandidate( + link, template, factory=self, + name=name, version=version, + ) + except (InstallationSubprocessError, MetadataInconsistent) as e: + logger.warning("Discarding %s. %s", link, e) + self._build_failures[link] = e + return None + base = self._link_candidate_cache[link] + + if extras: + return ExtrasCandidate(base, extras) + return base + + def _iter_found_candidates( + self, + ireqs, # type: Sequence[InstallRequirement] + specifier, # type: SpecifierSet + hashes, # type: Hashes + prefers_installed, # type: bool + ): + # type: (...) -> Iterable[Candidate] + if not ireqs: + return () + + # The InstallRequirement implementation requires us to give it a + # "template". Here we just choose the first requirement to represent + # all of them. + # Hopefully the Project model can correct this mismatch in the future. + template = ireqs[0] + name = canonicalize_name(template.req.name) + + extras = frozenset() # type: FrozenSet[str] + for ireq in ireqs: + specifier &= ireq.req.specifier + hashes &= ireq.hashes(trust_internet=False) + extras |= frozenset(ireq.extras) + + # Get the installed version, if it matches, unless the user + # specified `--force-reinstall`, when we want the version from + # the index instead. + installed_candidate = None + if not self._force_reinstall and name in self._installed_dists: + installed_dist = self._installed_dists[name] + if specifier.contains(installed_dist.version, prereleases=True): + installed_candidate = self._make_candidate_from_dist( + dist=installed_dist, + extras=extras, + template=template, + ) + + def iter_index_candidates(): + # type: () -> Iterator[Candidate] + result = self._finder.find_best_candidate( + project_name=name, + specifier=specifier, + hashes=hashes, + ) + icans = list(result.iter_applicable()) + + # PEP 592: Yanked releases must be ignored unless only yanked + # releases can satisfy the version range. So if this is false, + # all yanked icans need to be skipped. + all_yanked = all(ican.link.is_yanked for ican in icans) + + # PackageFinder returns earlier versions first, so we reverse. + versions_found = set() # type: Set[_BaseVersion] + for ican in reversed(icans): + if not all_yanked and ican.link.is_yanked: + continue + if ican.version in versions_found: + continue + candidate = self._make_candidate_from_link( + link=ican.link, + extras=extras, + template=template, + name=name, + version=ican.version, + ) + if candidate is None: + continue + yield candidate + versions_found.add(ican.version) + + return FoundCandidates( + iter_index_candidates, + installed_candidate, + prefers_installed, + ) + + def find_candidates( + self, + requirements, # type: Sequence[Requirement] + constraint, # type: Constraint + prefers_installed, # type: bool + ): + # type: (...) -> Iterable[Candidate] + explicit_candidates = set() # type: Set[Candidate] + ireqs = [] # type: List[InstallRequirement] + for req in requirements: + cand, ireq = req.get_candidate_lookup() + if cand is not None: + explicit_candidates.add(cand) + if ireq is not None: + ireqs.append(ireq) + + # If none of the requirements want an explicit candidate, we can ask + # the finder for candidates. + if not explicit_candidates: + return self._iter_found_candidates( + ireqs, + constraint.specifier, + constraint.hashes, + prefers_installed, + ) + + return ( + c for c in explicit_candidates + if constraint.is_satisfied_by(c) + and all(req.is_satisfied_by(c) for req in requirements) + ) + + def make_requirement_from_install_req(self, ireq, requested_extras): + # type: (InstallRequirement, Iterable[str]) -> Optional[Requirement] + if not ireq.match_markers(requested_extras): + logger.info( + "Ignoring %s: markers '%s' don't match your environment", + ireq.name, ireq.markers, + ) + return None + if not ireq.link: + return SpecifierRequirement(ireq) + if ireq.link.is_wheel: + wheel = Wheel(ireq.link.filename) + if not wheel.supported(self._finder.target_python.get_tags()): + msg = "{} is not a supported wheel on this platform.".format( + wheel.filename, + ) + raise UnsupportedWheel(msg) + cand = self._make_candidate_from_link( + ireq.link, + extras=frozenset(ireq.extras), + template=ireq, + name=canonicalize_name(ireq.name) if ireq.name else None, + version=None, + ) + if cand is None: + # There's no way we can satisfy a URL requirement if the underlying + # candidate fails to build. An unnamed URL must be user-supplied, so + # we fail eagerly. If the URL is named, an unsatisfiable requirement + # can make the resolver do the right thing, either backtrack (and + # maybe find some other requirement that's buildable) or raise a + # ResolutionImpossible eventually. + if not ireq.name: + raise self._build_failures[ireq.link] + return UnsatisfiableRequirement(canonicalize_name(ireq.name)) + return self.make_requirement_from_candidate(cand) + + def make_requirement_from_candidate(self, candidate): + # type: (Candidate) -> ExplicitRequirement + return ExplicitRequirement(candidate) + + def make_requirement_from_spec( + self, + specifier, # type: str + comes_from, # type: InstallRequirement + requested_extras=(), # type: Iterable[str] + ): + # type: (...) -> Optional[Requirement] + ireq = self._make_install_req_from_spec(specifier, comes_from) + return self.make_requirement_from_install_req(ireq, requested_extras) + + def make_requires_python_requirement(self, specifier): + # type: (Optional[SpecifierSet]) -> Optional[Requirement] + if self._ignore_requires_python or specifier is None: + return None + return RequiresPythonRequirement(specifier, self._python_candidate) + + def get_wheel_cache_entry(self, link, name): + # type: (Link, Optional[str]) -> Optional[CacheEntry] + """Look up the link in the wheel cache. + + If ``preparer.require_hashes`` is True, don't use the wheel cache, + because cached wheels, always built locally, have different hashes + than the files downloaded from the index server and thus throw false + hash mismatches. Furthermore, cached wheels at present have + nondeterministic contents due to file modification times. + """ + if self._wheel_cache is None or self.preparer.require_hashes: + return None + return self._wheel_cache.get_cache_entry( + link=link, + package_name=name, + supported_tags=get_supported(), + ) + + def get_dist_to_uninstall(self, candidate): + # type: (Candidate) -> Optional[Distribution] + # TODO: Are there more cases this needs to return True? Editable? + dist = self._installed_dists.get(candidate.name) + if dist is None: # Not installed, no uninstallation required. + return None + + # We're installing into global site. The current installation must + # be uninstalled, no matter it's in global or user site, because the + # user site installation has precedence over global. + if not self._use_user_site: + return dist + + # We're installing into user site. Remove the user site installation. + if dist_in_usersite(dist): + return dist + + # We're installing into user site, but the installed incompatible + # package is in global site. We can't uninstall that, and would let + # the new user installation to "shadow" it. But shadowing won't work + # in virtual environments, so we error out. + if running_under_virtualenv() and dist_in_site_packages(dist): + raise InstallationError( + "Will not install to the user site because it will " + "lack sys.path precedence to {} in {}".format( + dist.project_name, dist.location, + ) + ) + return None + + def _report_requires_python_error( + self, + requirement, # type: RequiresPythonRequirement + template, # type: Candidate + ): + # type: (...) -> UnsupportedPythonVersion + message_format = ( + "Package {package!r} requires a different Python: " + "{version} not in {specifier!r}" + ) + message = message_format.format( + package=template.name, + version=self._python_candidate.version, + specifier=str(requirement.specifier), + ) + return UnsupportedPythonVersion(message) + + def get_installation_error(self, e): + # type: (ResolutionImpossible) -> InstallationError + + assert e.causes, "Installation error reported with no cause" + + # If one of the things we can't solve is "we need Python X.Y", + # that is what we report. + for cause in e.causes: + if isinstance(cause.requirement, RequiresPythonRequirement): + return self._report_requires_python_error( + cause.requirement, + cause.parent, + ) + + # Otherwise, we have a set of causes which can't all be satisfied + # at once. + + # The simplest case is when we have *one* cause that can't be + # satisfied. We just report that case. + if len(e.causes) == 1: + req, parent = e.causes[0] + if parent is None: + req_disp = str(req) + else: + req_disp = '{} (from {})'.format(req, parent.name) + logger.critical( + "Could not find a version that satisfies the requirement %s", + req_disp, + ) + return DistributionNotFound( + 'No matching distribution found for {}'.format(req) + ) + + # OK, we now have a list of requirements that can't all be + # satisfied at once. + + # A couple of formatting helpers + def text_join(parts): + # type: (List[str]) -> str + if len(parts) == 1: + return parts[0] + + return ", ".join(parts[:-1]) + " and " + parts[-1] + + def describe_trigger(parent): + # type: (Candidate) -> str + ireq = parent.get_install_requirement() + if not ireq or not ireq.comes_from: + return "{}=={}".format(parent.name, parent.version) + if isinstance(ireq.comes_from, InstallRequirement): + return str(ireq.comes_from.name) + return str(ireq.comes_from) + + triggers = set() + for req, parent in e.causes: + if parent is None: + # This is a root requirement, so we can report it directly + trigger = req.format_for_error() + else: + trigger = describe_trigger(parent) + triggers.add(trigger) + + if triggers: + info = text_join(sorted(triggers)) + else: + info = "the requested packages" + + msg = "Cannot install {} because these package versions " \ + "have conflicting dependencies.".format(info) + logger.critical(msg) + msg = "\nThe conflict is caused by:" + for req, parent in e.causes: + msg = msg + "\n " + if parent: + msg = msg + "{} {} depends on ".format( + parent.name, + parent.version + ) + else: + msg = msg + "The user requested " + msg = msg + req.format_for_error() + + msg = msg + "\n\n" + \ + "To fix this you could try to:\n" + \ + "1. loosen the range of package versions you've specified\n" + \ + "2. remove package versions to allow pip attempt to solve " + \ + "the dependency conflict\n" + + logger.info(msg) + + return DistributionNotFound( + "ResolutionImpossible: for help visit " + "https://pip.pypa.io/en/latest/user_guide/" + "#fixing-conflicting-dependencies" + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py new file mode 100644 index 0000000..50359b6 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py @@ -0,0 +1,101 @@ +"""Utilities to lazily create and visit candidates found. + +Creating and visiting a candidate is a *very* costly operation. It involves +fetching, extracting, potentially building modules from source, and verifying +distribution metadata. It is therefore crucial for performance to keep +everything here lazy all the way down, so we only touch candidates that we +absolutely need, and not "download the world" when we only need one version of +something. +""" + +import itertools + +from pip._vendor.six.moves import collections_abc # type: ignore + +from pip._internal.utils.compat import lru_cache +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Callable, Iterator, Optional + + from .base import Candidate + + +def _insert_installed(installed, others): + # type: (Candidate, Iterator[Candidate]) -> Iterator[Candidate] + """Iterator for ``FoundCandidates``. + + This iterator is used when the resolver prefers to upgrade an + already-installed package. Candidates from index are returned in their + normal ordering, except replaced when the version is already installed. + + The implementation iterates through and yields other candidates, inserting + the installed candidate exactly once before we start yielding older or + equivalent candidates, or after all other candidates if they are all newer. + """ + installed_yielded = False + for candidate in others: + # If the installed candidate is better, yield it first. + if not installed_yielded and installed.version >= candidate.version: + yield installed + installed_yielded = True + yield candidate + + # If the installed candidate is older than all other candidates. + if not installed_yielded: + yield installed + + +class FoundCandidates(collections_abc.Sequence): + """A lazy sequence to provide candidates to the resolver. + + The intended usage is to return this from `find_matches()` so the resolver + can iterate through the sequence multiple times, but only access the index + page when remote packages are actually needed. This improve performances + when suitable candidates are already installed on disk. + """ + def __init__( + self, + get_others, # type: Callable[[], Iterator[Candidate]] + installed, # type: Optional[Candidate] + prefers_installed, # type: bool + ): + self._get_others = get_others + self._installed = installed + self._prefers_installed = prefers_installed + + def __getitem__(self, index): + # type: (int) -> Candidate + # Implemented to satisfy the ABC check. This is not needed by the + # resolver, and should not be used by the provider either (for + # performance reasons). + raise NotImplementedError("don't do this") + + def __iter__(self): + # type: () -> Iterator[Candidate] + if not self._installed: + return self._get_others() + others = ( + candidate + for candidate in self._get_others() + if candidate.version != self._installed.version + ) + if self._prefers_installed: + return itertools.chain([self._installed], others) + return _insert_installed(self._installed, others) + + def __len__(self): + # type: () -> int + # Implemented to satisfy the ABC check. This is not needed by the + # resolver, and should not be used by the provider either (for + # performance reasons). + raise NotImplementedError("don't do this") + + @lru_cache(maxsize=1) + def __bool__(self): + # type: () -> bool + if self._prefers_installed and self._installed: + return True + return any(self) + + __nonzero__ = __bool__ # XXX: Python 2. diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/provider.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/provider.py new file mode 100644 index 0000000..40a641a --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/provider.py @@ -0,0 +1,174 @@ +from pip._vendor.resolvelib.providers import AbstractProvider + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +from .base import Constraint + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, Iterable, Optional, Sequence, Set, Tuple, Union + + from .base import Candidate, Requirement + from .factory import Factory + +# Notes on the relationship between the provider, the factory, and the +# candidate and requirement classes. +# +# The provider is a direct implementation of the resolvelib class. Its role +# is to deliver the API that resolvelib expects. +# +# Rather than work with completely abstract "requirement" and "candidate" +# concepts as resolvelib does, pip has concrete classes implementing these two +# ideas. The API of Requirement and Candidate objects are defined in the base +# classes, but essentially map fairly directly to the equivalent provider +# methods. In particular, `find_matches` and `is_satisfied_by` are +# requirement methods, and `get_dependencies` is a candidate method. +# +# The factory is the interface to pip's internal mechanisms. It is stateless, +# and is created by the resolver and held as a property of the provider. It is +# responsible for creating Requirement and Candidate objects, and provides +# services to those objects (access to pip's finder and preparer). + + +class PipProvider(AbstractProvider): + """Pip's provider implementation for resolvelib. + + :params constraints: A mapping of constraints specified by the user. Keys + are canonicalized project names. + :params ignore_dependencies: Whether the user specified ``--no-deps``. + :params upgrade_strategy: The user-specified upgrade strategy. + :params user_requested: A set of canonicalized package names that the user + supplied for pip to install/upgrade. + """ + + def __init__( + self, + factory, # type: Factory + constraints, # type: Dict[str, Constraint] + ignore_dependencies, # type: bool + upgrade_strategy, # type: str + user_requested, # type: Set[str] + ): + # type: (...) -> None + self._factory = factory + self._constraints = constraints + self._ignore_dependencies = ignore_dependencies + self._upgrade_strategy = upgrade_strategy + self._user_requested = user_requested + + def identify(self, dependency): + # type: (Union[Requirement, Candidate]) -> str + return dependency.name + + def get_preference( + self, + resolution, # type: Optional[Candidate] + candidates, # type: Sequence[Candidate] + information # type: Sequence[Tuple[Requirement, Candidate]] + ): + # type: (...) -> Any + """Produce a sort key for given requirement based on preference. + + The lower the return value is, the more preferred this group of + arguments is. + + Currently pip considers the followings in order: + + * Prefer if any of the known requirements points to an explicit URL. + * If equal, prefer if any requirements contain ``===`` and ``==``. + * If equal, prefer if requirements include version constraints, e.g. + ``>=`` and ``<``. + * If equal, prefer user-specified (non-transitive) requirements. + * If equal, order alphabetically for consistency (helps debuggability). + """ + + def _get_restrictive_rating(requirements): + # type: (Iterable[Requirement]) -> int + """Rate how restrictive a set of requirements are. + + ``Requirement.get_candidate_lookup()`` returns a 2-tuple for + lookup. The first element is ``Optional[Candidate]`` and the + second ``Optional[InstallRequirement]``. + + * If the requirement is an explicit one, the explicitly-required + candidate is returned as the first element. + * If the requirement is based on a PEP 508 specifier, the backing + ``InstallRequirement`` is returned as the second element. + + We use the first element to check whether there is an explicit + requirement, and the second for equality operator. + """ + lookups = (r.get_candidate_lookup() for r in requirements) + cands, ireqs = zip(*lookups) + if any(cand is not None for cand in cands): + return 0 + spec_sets = (ireq.specifier for ireq in ireqs if ireq) + operators = [ + specifier.operator + for spec_set in spec_sets + for specifier in spec_set + ] + if any(op in ("==", "===") for op in operators): + return 1 + if operators: + return 2 + # A "bare" requirement without any version requirements. + return 3 + + restrictive = _get_restrictive_rating(req for req, _ in information) + transitive = all(parent is not None for _, parent in information) + key = next(iter(candidates)).name if candidates else "" + + # HACK: Setuptools have a very long and solid backward compatibility + # track record, and extremely few projects would request a narrow, + # non-recent version range of it since that would break a lot things. + # (Most projects specify it only to request for an installer feature, + # which does not work, but that's another topic.) Intentionally + # delaying Setuptools helps reduce branches the resolver has to check. + # This serves as a temporary fix for issues like "apache-airlfow[all]" + # while we work on "proper" branch pruning techniques. + delay_this = (key == "setuptools") + + return (delay_this, restrictive, transitive, key) + + def find_matches(self, requirements): + # type: (Sequence[Requirement]) -> Iterable[Candidate] + if not requirements: + return [] + name = requirements[0].project_name + + def _eligible_for_upgrade(name): + # type: (str) -> bool + """Are upgrades allowed for this project? + + This checks the upgrade strategy, and whether the project was one + that the user specified in the command line, in order to decide + whether we should upgrade if there's a newer version available. + + (Note that we don't need access to the `--upgrade` flag, because + an upgrade strategy of "to-satisfy-only" means that `--upgrade` + was not specified). + """ + if self._upgrade_strategy == "eager": + return True + elif self._upgrade_strategy == "only-if-needed": + return (name in self._user_requested) + return False + + return self._factory.find_candidates( + requirements, + constraint=self._constraints.get(name, Constraint.empty()), + prefers_installed=(not _eligible_for_upgrade(name)), + ) + + def is_satisfied_by(self, requirement, candidate): + # type: (Requirement, Candidate) -> bool + return requirement.is_satisfied_by(candidate) + + def get_dependencies(self, candidate): + # type: (Candidate) -> Sequence[Requirement] + with_requires = not self._ignore_dependencies + return [ + r + for r in candidate.iter_dependencies(with_requires) + if r is not None + ] diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/reporter.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/reporter.py new file mode 100644 index 0000000..d0ef3fa --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/reporter.py @@ -0,0 +1,84 @@ +from collections import defaultdict +from logging import getLogger + +from pip._vendor.resolvelib.reporters import BaseReporter + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, DefaultDict + + from .base import Candidate, Requirement + + +logger = getLogger(__name__) + + +class PipReporter(BaseReporter): + + def __init__(self): + # type: () -> None + self.backtracks_by_package = defaultdict(int) # type: DefaultDict[str, int] + + self._messages_at_backtrack = { + 1: ( + "pip is looking at multiple versions of {package_name} to " + "determine which version is compatible with other " + "requirements. This could take a while." + ), + 8: ( + "pip is looking at multiple versions of {package_name} to " + "determine which version is compatible with other " + "requirements. This could take a while." + ), + 13: ( + "This is taking longer than usual. You might need to provide " + "the dependency resolver with stricter constraints to reduce " + "runtime. If you want to abort this run, you can press " + "Ctrl + C to do so. To improve how pip performs, tell us what " + "happened here: https://pip.pypa.io/surveys/backtracking" + ) + } + + def backtracking(self, candidate): + # type: (Candidate) -> None + self.backtracks_by_package[candidate.name] += 1 + + count = self.backtracks_by_package[candidate.name] + if count not in self._messages_at_backtrack: + return + + message = self._messages_at_backtrack[count] + logger.info("INFO: %s", message.format(package_name=candidate.name)) + + +class PipDebuggingReporter(BaseReporter): + """A reporter that does an info log for every event it sees.""" + + def starting(self): + # type: () -> None + logger.info("Reporter.starting()") + + def starting_round(self, index): + # type: (int) -> None + logger.info("Reporter.starting_round(%r)", index) + + def ending_round(self, index, state): + # type: (int, Any) -> None + logger.info("Reporter.ending_round(%r, state)", index) + + def ending(self, state): + # type: (Any) -> None + logger.info("Reporter.ending(%r)", state) + + def adding_requirement(self, requirement, parent): + # type: (Requirement, Candidate) -> None + logger.info("Reporter.adding_requirement(%r, %r)", requirement, parent) + + def backtracking(self, candidate): + # type: (Candidate) -> None + logger.info("Reporter.backtracking(%r)", candidate) + + def pinning(self, candidate): + # type: (Candidate) -> None + logger.info("Reporter.pinning(%r)", candidate) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/requirements.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/requirements.py new file mode 100644 index 0000000..1229f35 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/requirements.py @@ -0,0 +1,201 @@ +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +from .base import Requirement, format_name + +if MYPY_CHECK_RUNNING: + from pip._vendor.packaging.specifiers import SpecifierSet + + from pip._internal.req.req_install import InstallRequirement + + from .base import Candidate, CandidateLookup + + +class ExplicitRequirement(Requirement): + def __init__(self, candidate): + # type: (Candidate) -> None + self.candidate = candidate + + def __str__(self): + # type: () -> str + return str(self.candidate) + + def __repr__(self): + # type: () -> str + return "{class_name}({candidate!r})".format( + class_name=self.__class__.__name__, + candidate=self.candidate, + ) + + @property + def project_name(self): + # type: () -> str + # No need to canonicalise - the candidate did this + return self.candidate.project_name + + @property + def name(self): + # type: () -> str + # No need to canonicalise - the candidate did this + return self.candidate.name + + def format_for_error(self): + # type: () -> str + return self.candidate.format_for_error() + + def get_candidate_lookup(self): + # type: () -> CandidateLookup + return self.candidate, None + + def is_satisfied_by(self, candidate): + # type: (Candidate) -> bool + return candidate == self.candidate + + +class SpecifierRequirement(Requirement): + def __init__(self, ireq): + # type: (InstallRequirement) -> None + assert ireq.link is None, "This is a link, not a specifier" + self._ireq = ireq + self._extras = frozenset(ireq.extras) + + def __str__(self): + # type: () -> str + return str(self._ireq.req) + + def __repr__(self): + # type: () -> str + return "{class_name}({requirement!r})".format( + class_name=self.__class__.__name__, + requirement=str(self._ireq.req), + ) + + @property + def project_name(self): + # type: () -> str + return canonicalize_name(self._ireq.req.name) + + @property + def name(self): + # type: () -> str + return format_name(self.project_name, self._extras) + + def format_for_error(self): + # type: () -> str + + # Convert comma-separated specifiers into "A, B, ..., F and G" + # This makes the specifier a bit more "human readable", without + # risking a change in meaning. (Hopefully! Not all edge cases have + # been checked) + parts = [s.strip() for s in str(self).split(",")] + if len(parts) == 0: + return "" + elif len(parts) == 1: + return parts[0] + + return ", ".join(parts[:-1]) + " and " + parts[-1] + + def get_candidate_lookup(self): + # type: () -> CandidateLookup + return None, self._ireq + + def is_satisfied_by(self, candidate): + # type: (Candidate) -> bool + assert candidate.name == self.name, \ + "Internal issue: Candidate is not for this requirement " \ + " {} vs {}".format(candidate.name, self.name) + # We can safely always allow prereleases here since PackageFinder + # already implements the prerelease logic, and would have filtered out + # prerelease candidates if the user does not expect them. + spec = self._ireq.req.specifier + return spec.contains(candidate.version, prereleases=True) + + +class RequiresPythonRequirement(Requirement): + """A requirement representing Requires-Python metadata. + """ + def __init__(self, specifier, match): + # type: (SpecifierSet, Candidate) -> None + self.specifier = specifier + self._candidate = match + + def __str__(self): + # type: () -> str + return "Python {}".format(self.specifier) + + def __repr__(self): + # type: () -> str + return "{class_name}({specifier!r})".format( + class_name=self.__class__.__name__, + specifier=str(self.specifier), + ) + + @property + def project_name(self): + # type: () -> str + return self._candidate.project_name + + @property + def name(self): + # type: () -> str + return self._candidate.name + + def format_for_error(self): + # type: () -> str + return str(self) + + def get_candidate_lookup(self): + # type: () -> CandidateLookup + if self.specifier.contains(self._candidate.version, prereleases=True): + return self._candidate, None + return None, None + + def is_satisfied_by(self, candidate): + # type: (Candidate) -> bool + assert candidate.name == self._candidate.name, "Not Python candidate" + # We can safely always allow prereleases here since PackageFinder + # already implements the prerelease logic, and would have filtered out + # prerelease candidates if the user does not expect them. + return self.specifier.contains(candidate.version, prereleases=True) + + +class UnsatisfiableRequirement(Requirement): + """A requirement that cannot be satisfied. + """ + def __init__(self, name): + # type: (str) -> None + self._name = name + + def __str__(self): + # type: () -> str + return "{} (unavailable)".format(self._name) + + def __repr__(self): + # type: () -> str + return "{class_name}({name!r})".format( + class_name=self.__class__.__name__, + name=str(self._name), + ) + + @property + def project_name(self): + # type: () -> str + return self._name + + @property + def name(self): + # type: () -> str + return self._name + + def format_for_error(self): + # type: () -> str + return str(self) + + def get_candidate_lookup(self): + # type: () -> CandidateLookup + return None, None + + def is_satisfied_by(self, candidate): + # type: (Candidate) -> bool + return False diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/resolver.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/resolver.py new file mode 100644 index 0000000..84421d4 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/resolver.py @@ -0,0 +1,297 @@ +import functools +import logging +import os + +from pip._vendor import six +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.resolvelib import ResolutionImpossible +from pip._vendor.resolvelib import Resolver as RLResolver + +from pip._internal.exceptions import InstallationError +from pip._internal.req.req_install import check_invalid_constraint_type +from pip._internal.req.req_set import RequirementSet +from pip._internal.resolution.base import BaseResolver +from pip._internal.resolution.resolvelib.provider import PipProvider +from pip._internal.resolution.resolvelib.reporter import ( + PipDebuggingReporter, + PipReporter, +) +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.filetypes import is_archive_file +from pip._internal.utils.misc import dist_is_editable +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +from .base import Constraint +from .factory import Factory + +if MYPY_CHECK_RUNNING: + from typing import Dict, List, Optional, Set, Tuple + + from pip._vendor.resolvelib.resolvers import Result + from pip._vendor.resolvelib.structs import Graph + + from pip._internal.cache import WheelCache + from pip._internal.index.package_finder import PackageFinder + from pip._internal.operations.prepare import RequirementPreparer + from pip._internal.req.req_install import InstallRequirement + from pip._internal.resolution.base import InstallRequirementProvider + + +logger = logging.getLogger(__name__) + + +class Resolver(BaseResolver): + _allowed_strategies = {"eager", "only-if-needed", "to-satisfy-only"} + + def __init__( + self, + preparer, # type: RequirementPreparer + finder, # type: PackageFinder + wheel_cache, # type: Optional[WheelCache] + make_install_req, # type: InstallRequirementProvider + use_user_site, # type: bool + ignore_dependencies, # type: bool + ignore_installed, # type: bool + ignore_requires_python, # type: bool + force_reinstall, # type: bool + upgrade_strategy, # type: str + py_version_info=None, # type: Optional[Tuple[int, ...]] + ): + super(Resolver, self).__init__() + assert upgrade_strategy in self._allowed_strategies + + self.factory = Factory( + finder=finder, + preparer=preparer, + make_install_req=make_install_req, + wheel_cache=wheel_cache, + use_user_site=use_user_site, + force_reinstall=force_reinstall, + ignore_installed=ignore_installed, + ignore_requires_python=ignore_requires_python, + py_version_info=py_version_info, + ) + self.ignore_dependencies = ignore_dependencies + self.upgrade_strategy = upgrade_strategy + self._result = None # type: Optional[Result] + + def resolve(self, root_reqs, check_supported_wheels): + # type: (List[InstallRequirement], bool) -> RequirementSet + + constraints = {} # type: Dict[str, Constraint] + user_requested = set() # type: Set[str] + requirements = [] + for req in root_reqs: + if req.constraint: + # Ensure we only accept valid constraints + problem = check_invalid_constraint_type(req) + if problem: + raise InstallationError(problem) + if not req.match_markers(): + continue + name = canonicalize_name(req.name) + if name in constraints: + constraints[name] &= req + else: + constraints[name] = Constraint.from_ireq(req) + else: + if req.user_supplied and req.name: + user_requested.add(canonicalize_name(req.name)) + r = self.factory.make_requirement_from_install_req( + req, requested_extras=(), + ) + if r is not None: + requirements.append(r) + + provider = PipProvider( + factory=self.factory, + constraints=constraints, + ignore_dependencies=self.ignore_dependencies, + upgrade_strategy=self.upgrade_strategy, + user_requested=user_requested, + ) + if "PIP_RESOLVER_DEBUG" in os.environ: + reporter = PipDebuggingReporter() + else: + reporter = PipReporter() + resolver = RLResolver(provider, reporter) + + try: + try_to_avoid_resolution_too_deep = 2000000 + self._result = resolver.resolve( + requirements, max_rounds=try_to_avoid_resolution_too_deep, + ) + + except ResolutionImpossible as e: + error = self.factory.get_installation_error(e) + six.raise_from(error, e) + + req_set = RequirementSet(check_supported_wheels=check_supported_wheels) + for candidate in self._result.mapping.values(): + ireq = candidate.get_install_requirement() + if ireq is None: + continue + + # Check if there is already an installation under the same name, + # and set a flag for later stages to uninstall it, if needed. + installed_dist = self.factory.get_dist_to_uninstall(candidate) + if installed_dist is None: + # There is no existing installation -- nothing to uninstall. + ireq.should_reinstall = False + elif self.factory.force_reinstall: + # The --force-reinstall flag is set -- reinstall. + ireq.should_reinstall = True + elif parse_version(installed_dist.version) != candidate.version: + # The installation is different in version -- reinstall. + ireq.should_reinstall = True + elif candidate.is_editable or dist_is_editable(installed_dist): + # The incoming distribution is editable, or different in + # editable-ness to installation -- reinstall. + ireq.should_reinstall = True + elif candidate.source_link.is_file: + # The incoming distribution is under file:// + if candidate.source_link.is_wheel: + # is a local wheel -- do nothing. + logger.info( + "%s is already installed with the same version as the " + "provided wheel. Use --force-reinstall to force an " + "installation of the wheel.", + ireq.name, + ) + continue + + looks_like_sdist = ( + is_archive_file(candidate.source_link.file_path) + and candidate.source_link.ext != ".zip" + ) + if looks_like_sdist: + # is a local sdist -- show a deprecation warning! + reason = ( + "Source distribution is being reinstalled despite an " + "installed package having the same name and version as " + "the installed package." + ) + replacement = "use --force-reinstall" + deprecated( + reason=reason, + replacement=replacement, + gone_in="21.1", + issue=8711, + ) + + # is a local sdist or path -- reinstall + ireq.should_reinstall = True + else: + continue + + link = candidate.source_link + if link and link.is_yanked: + # The reason can contain non-ASCII characters, Unicode + # is required for Python 2. + msg = ( + u'The candidate selected for download or install is a ' + u'yanked version: {name!r} candidate (version {version} ' + u'at {link})\nReason for being yanked: {reason}' + ).format( + name=candidate.name, + version=candidate.version, + link=link, + reason=link.yanked_reason or u'', + ) + logger.warning(msg) + + req_set.add_named_requirement(ireq) + + reqs = req_set.all_requirements + self.factory.preparer.prepare_linked_requirements_more(reqs) + return req_set + + def get_installation_order(self, req_set): + # type: (RequirementSet) -> List[InstallRequirement] + """Get order for installation of requirements in RequirementSet. + + The returned list contains a requirement before another that depends on + it. This helps ensure that the environment is kept consistent as they + get installed one-by-one. + + The current implementation creates a topological ordering of the + dependency graph, while breaking any cycles in the graph at arbitrary + points. We make no guarantees about where the cycle would be broken, + other than they would be broken. + """ + assert self._result is not None, "must call resolve() first" + + graph = self._result.graph + weights = get_topological_weights( + graph, + expected_node_count=len(self._result.mapping) + 1, + ) + + sorted_items = sorted( + req_set.requirements.items(), + key=functools.partial(_req_set_item_sorter, weights=weights), + reverse=True, + ) + return [ireq for _, ireq in sorted_items] + + +def get_topological_weights(graph, expected_node_count): + # type: (Graph, int) -> Dict[Optional[str], int] + """Assign weights to each node based on how "deep" they are. + + This implementation may change at any point in the future without prior + notice. + + We take the length for the longest path to any node from root, ignoring any + paths that contain a single node twice (i.e. cycles). This is done through + a depth-first search through the graph, while keeping track of the path to + the node. + + Cycles in the graph result would result in node being revisited while also + being it's own path. In this case, take no action. This helps ensure we + don't get stuck in a cycle. + + When assigning weight, the longer path (i.e. larger length) is preferred. + """ + path = set() # type: Set[Optional[str]] + weights = {} # type: Dict[Optional[str], int] + + def visit(node): + # type: (Optional[str]) -> None + if node in path: + # We hit a cycle, so we'll break it here. + return + + # Time to visit the children! + path.add(node) + for child in graph.iter_children(node): + visit(child) + path.remove(node) + + last_known_parent_count = weights.get(node, 0) + weights[node] = max(last_known_parent_count, len(path)) + + # `None` is guaranteed to be the root node by resolvelib. + visit(None) + + # Sanity checks + assert weights[None] == 0 + assert len(weights) == expected_node_count + + return weights + + +def _req_set_item_sorter( + item, # type: Tuple[str, InstallRequirement] + weights, # type: Dict[Optional[str], int] +): + # type: (...) -> Tuple[int, str] + """Key function used to sort install requirements for installation. + + Based on the "weight" mapping calculated in ``get_installation_order()``. + The canonical package name is returned as the second member as a tie- + breaker to ensure the result is predictable, which is useful in tests. + """ + name = canonicalize_name(item[0]) + return weights[name], name diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/self_outdated_check.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/self_outdated_check.py new file mode 100644 index 0000000..c2d166b --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/self_outdated_check.py @@ -0,0 +1,197 @@ +from __future__ import absolute_import + +import datetime +import hashlib +import json +import logging +import os.path +import sys + +from pip._vendor.packaging import version as packaging_version +from pip._vendor.six import ensure_binary + +from pip._internal.index.collector import LinkCollector +from pip._internal.index.package_finder import PackageFinder +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.utils.filesystem import adjacent_tmp_file, check_path_owner, replace +from pip._internal.utils.misc import ensure_dir, get_distribution, get_installed_version +from pip._internal.utils.packaging import get_installer +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + import optparse + from typing import Any, Dict, Text, Union + + from pip._internal.network.session import PipSession + + +SELFCHECK_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" + + +logger = logging.getLogger(__name__) + + +def _get_statefile_name(key): + # type: (Union[str, Text]) -> str + key_bytes = ensure_binary(key) + name = hashlib.sha224(key_bytes).hexdigest() + return name + + +class SelfCheckState(object): + def __init__(self, cache_dir): + # type: (str) -> None + self.state = {} # type: Dict[str, Any] + self.statefile_path = None + + # Try to load the existing state + if cache_dir: + self.statefile_path = os.path.join( + cache_dir, "selfcheck", _get_statefile_name(self.key) + ) + try: + with open(self.statefile_path) as statefile: + self.state = json.load(statefile) + except (IOError, ValueError, KeyError): + # Explicitly suppressing exceptions, since we don't want to + # error out if the cache file is invalid. + pass + + @property + def key(self): + # type: () -> str + return sys.prefix + + def save(self, pypi_version, current_time): + # type: (str, datetime.datetime) -> None + # If we do not have a path to cache in, don't bother saving. + if not self.statefile_path: + return + + # Check to make sure that we own the directory + if not check_path_owner(os.path.dirname(self.statefile_path)): + return + + # Now that we've ensured the directory is owned by this user, we'll go + # ahead and make sure that all our directories are created. + ensure_dir(os.path.dirname(self.statefile_path)) + + state = { + # Include the key so it's easy to tell which pip wrote the + # file. + "key": self.key, + "last_check": current_time.strftime(SELFCHECK_DATE_FMT), + "pypi_version": pypi_version, + } + + text = json.dumps(state, sort_keys=True, separators=(",", ":")) + + with adjacent_tmp_file(self.statefile_path) as f: + f.write(ensure_binary(text)) + + try: + # Since we have a prefix-specific state file, we can just + # overwrite whatever is there, no need to check. + replace(f.name, self.statefile_path) + except OSError: + # Best effort. + pass + + +def was_installed_by_pip(pkg): + # type: (str) -> bool + """Checks whether pkg was installed by pip + + This is used not to display the upgrade message when pip is in fact + installed by system package manager, such as dnf on Fedora. + """ + dist = get_distribution(pkg) + if not dist: + return False + return "pip" == get_installer(dist) + + +def pip_self_version_check(session, options): + # type: (PipSession, optparse.Values) -> None + """Check for an update for pip. + + Limit the frequency of checks to once per week. State is stored either in + the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix + of the pip script path. + """ + installed_version = get_installed_version("pip") + if not installed_version: + return + + pip_version = packaging_version.parse(installed_version) + pypi_version = None + + try: + state = SelfCheckState(cache_dir=options.cache_dir) + + current_time = datetime.datetime.utcnow() + # Determine if we need to refresh the state + if "last_check" in state.state and "pypi_version" in state.state: + last_check = datetime.datetime.strptime( + state.state["last_check"], + SELFCHECK_DATE_FMT + ) + if (current_time - last_check).total_seconds() < 7 * 24 * 60 * 60: + pypi_version = state.state["pypi_version"] + + # Refresh the version if we need to or just see if we need to warn + if pypi_version is None: + # Lets use PackageFinder to see what the latest pip version is + link_collector = LinkCollector.create( + session, + options=options, + suppress_no_index=True, + ) + + # Pass allow_yanked=False so we don't suggest upgrading to a + # yanked version. + selection_prefs = SelectionPreferences( + allow_yanked=False, + allow_all_prereleases=False, # Explicitly set to False + ) + + finder = PackageFinder.create( + link_collector=link_collector, + selection_prefs=selection_prefs, + ) + best_candidate = finder.find_best_candidate("pip").best_candidate + if best_candidate is None: + return + pypi_version = str(best_candidate.version) + + # save that we've performed a check + state.save(pypi_version, current_time) + + remote_version = packaging_version.parse(pypi_version) + + local_version_is_older = ( + pip_version < remote_version and + pip_version.base_version != remote_version.base_version and + was_installed_by_pip('pip') + ) + + # Determine if our pypi_version is older + if not local_version_is_older: + return + + # We cannot tell how the current pip is available in the current + # command context, so be pragmatic here and suggest the command + # that's always available. This does not accommodate spaces in + # `sys.executable`. + pip_cmd = "{} -m pip".format(sys.executable) + logger.warning( + "You are using pip version %s; however, version %s is " + "available.\nYou should consider upgrading via the " + "'%s install --upgrade pip' command.", + pip_version, pypi_version, pip_cmd + ) + except Exception: + logger.debug( + "There was an error checking the latest version of pip", + exc_info=True, + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1494cc0e340659a3706e895b2f44ec4408924356 GIT binary patch literal 219 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 F_!s?%?05hG literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f417b8272de9dca238f97f4409e03dd5c86c60ba GIT binary patch literal 540 zcmYjOy>1jS5cbb*xEu)-ynu^H(G^)2R7eORAyKBGyT)?X&e=Jyy|TSI9omy9c#x#b zE4ihjr=ntffRvGDJmdNF&7V9!Um_55_$4nfLO*KoTnGdoLDK~oh1N)6MI0W;n&9eF zN7qy}s{M}EjiO)B>f~$pIYhQI+OyG)Y$ttAEC<#b-EUbonkktz15CDq?v_7+8Le=6 zEpJkAQ`W)`V~F{>r#16WT6n8|0!<7|MtAsuJfZ{5=mF1Y#xr@Ohi0a8vu&Uee7&M& zQESyYrKw(Nb5L@>YD=@%GM07-KAS?}FIM)_ZtT7GPbk*4{QkyG7&O<;*^u*HFg^v( zQ|x)vV@O=?bOOLtrM^;7#U~4ZjrKai7w>@Uo;!QP$9*=zzwO@fWC1(Mek(URao7+S z)@L2PbbQLzCH}wVZrqnQ$9{!P!U16v*+_p1t)&w%h%E6d63@VciCzeyLN7#F3UNE- lDQY2Ny*LLi-Mhvh(fJR6w74B0F!^pyR9ixq6IL?QK1QTjVNwXde zCnQH}t+g**zXr%pupj$F`X}bKPkAr$5ClliozZHQxCjMt_|1C`FVCge+v|8pvy=ad z@4KG&AF6Dp5S91wx8EX@-pG?o`YD_HBcD+@NP|&OeZx_RZW+~h2v7?M#aJZ2sTcW&ipwf)0hP`0Be6LS?sWhaVi7Eta+ z(bt7Y>z;pkhL)_dA5I4|Jy!#jripg$P|q@}vw=17z^Gi?fjCkY1O6n1LzaL>0y&tf zOc^u{`U{mU25B-LpR`oWj|%n~trR z^G|(q&jqjGh_Bg6bJcv+Sb47*`Y*pZM|#BW@c24x?r&`FZ&_=5&GKrbO)^b@CbBbq zw054dlUQ4f<5XB%0VrFko?_Uv+?gu(50sTDTkFxiR@s^>Yr#<2hO4QmHt>x}lEN?N zs%*kdRi?|3TFQ`WXsgyZKRmMsCUCY}R{Wj_x`xbSZTx)J{izvrf)4BYR5sVq^M&WD>kdUk2X<%yR)4_K4}jPz0{wya?Qbr*K%dq?(8#bx+{(O_Ap+li;U) zcAd(ut?nK$;Pfj}%mr*w?rvFJnY4wea?J|ZwIs7nq-nHXFRJn1#0r)?#tZhtHfu7& zQI1KK&JwxK2Gk6d6<|sB8*k#T01P=)3V9&Ii9ZcbLfLr5WK*_Y!m;jor{pRPjBLZT zo;cqHryykIpR#8S)XBlvKbdPBHdhT7l133xvJFyp#lPXhAE-1}hE(Rvbs#j)6YEHO zCPfz43Xr&EztiDJ1~R0xTUD9rPt%qG;z|?W+|w5DRG6x>U)dM3D(Fx%sN_OzcKaDNvUbU1k&(&u##5a^ zKDU7a&{{aTo^aedF13PCzljPY6shF6OQ2=07fSLZtCuCp9*e|cBK%An%adxYKUf|Y z#z6Wvn}Dn-*oNuY1Ey)i6-gu5-Jqb&>xJn`t8iAfQ6?8vNU8AI0apBh@tA_;Sqe}fHL&!5 z2ieN|^6fAD6Lv!Pp27w0@+*Xk*X&b|d0+dLoH2^$O<5e*I9uvEwOGy`XBW0mc|QM)MxB z@)sewdPel!GRHhaQeQUL71Dk~Zw1q%=GJHR+vq&{)B%Un2(o+&{CVhU->#odcgU~o d+sMLJ*GEM4yM7n3G-Ufhi0~7JolEWR{{Ub>EA0RP literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f37a6d438a8dbe9725183a9eb11feee05635e88 GIT binary patch literal 2687 zcmZWr&2Jn@6|d^A>FJsAR~#psAhr=K((o~3Ez8%6UB$8;HcK)=ak8tl5WVf`@=QDZ zF;vw!c-+l_tPnzq#2>(6EOCJ&2gH%TqpqB|b0H#H-m4zl6X;e~y?S3&_3Bseb=2v2 z1fFsAujt)1LjHk+<;R7=9r(oGpovLLQxafrq%<=EBQpatvjQu#13Pm9Cu;-^igGh` zvu4oLw3T{UD`-(NTLX!mwzE#qq2yDNZ&`$`oE}kvFIx>dPf2cU6V~Lv2Tdnk%hrQ+ z?W2)yWY>agns(F8?0Rq=EXaI|-8iSg&A1tRpOfINcr9+nozH1-D_)6Lfpa^i2c*0H zPgp$}bRBhb@7|;R-N)gRNB6@A`;T|_b{_A9gPjNasCPlu_dBIf!BwD-i$xtBCrE25B)1N*KcR$+S{Ym)f$zX7A@MGYbCqn_< z>c9d%pm*Tgg-`qynv%@P zImE7{F}*=5V?-)b(vln-(tKg?4@)C9<`#~RZD<`$HO|fNgKqxOLemA!v@}qTe67>u zzbVbRSJUT|lKj>}yY<2l<;UdL^bLzP{{!mBCRns@5VR;w{uh|vitTx)G|ypu+PeYg z;mo#oi~NLf=|}!$e0^EKaFR@X&VDh4sAnvfK87S8^=77j$Dg@p)i=+oJ7?9bBc_M3 zKAD1_e(;KZ^%ebkcSX4;^&v6kB_hd%jPfBR!%gTusr4%Zq;6%Oj*Z8l6NiT)$@nw#LA$*CL{`FDCh?280+C(-a(G-9F;!Rv=fE*S?%^#Mq!=wGce9J6%7xadtz)jLb< zNQ4tMdGEdLaKYs4h;asy!)1%FK|@TJy40d=>d>_>T(eC*7_S*?&;th~8+BA84svHS&#; zin|M4r=(!rkd4xkZfPDj%SLI(^d$n&i;b7&0bY*QIpMzr9dc~T_6wYSA&W`n!l+X< z%O?M0Y|dB8CX83ljmll!;2VGNxhhK;7s0}=ECM1hP&Q1VwaC1$* z2_n9M%}r=#_F478S=FU{3r5{_46j8J26Ys6%D2nPsg3jv&=7>)t?%31WAC3%?0&U^@+HovEsYO>b2XOqFZ-bv9MQ@7-^DM$uLp25hbE^c9i509Nvkhs?0bFwn zdFS*~azHF1ZRyCyk$L)aN-D^CGhe#%W^CwO=>bG7taDGHZdUYHkfRS4)Hc}$3gBeU z{`~MzMoI23CqmpaFecANaGG_Td&|Y4=XpLnkC>eDT=;_`XMS?z%Q5rgr5fVHA^LgY ze|8nl-Z7+{&-{$Z2(nD{E$ye^X#M|MiSUzLC)A$S8_aI&y5&zI4#{=ozaxA=EOhU~ z*KMgbOc-AH<`_{8LQI8lh&Xi((MuH@RWRym<4K-iVO%PY%1MjSh(V!!9`PLJQ|$>a zj-f7VV0H~<;cgXW|BIh%$Pe){TZ{qNzy&&ag?i%`zOQ41UeZ)rzRDB^uh8n*aa+ literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/distutils_args.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/distutils_args.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b24be26f186d9872cc7095e75f966c6a2630e996 GIT binary patch literal 1159 zcmZ`(&2Q5%6u0xyrdx-)G3~$s%NuYQOjM`*z5}!W;rh#(&7RjnFTBm?Z-aPhrV7z#^C!~?_d<8$o_%*Eo#!%C)}Tl8d38z z>d!~cYt(K12Fs|6tHn(wRjF7i*G0S~L@q!$zfE{J+@UHj6dadc?(gjf8@pQ@&x2QQ zd%b79ovu+?n=Dk7^#bm9+gH> zBCiuiM3E`FGeIYmL{!MBrajT5>|iRr!WSt~|Iw6!Uayg%V1=6T(VQeQ3EmcYuCBaQ zRw=2t$SlOVmX`$WL@ihwu;eZJnImgpeTSwWJ0lD&GtNKm5h1Bti2Q^_G;)cE%Zzd*@3?}hQgFs& zmvA>f7|>9;Dj~{Eh=dKDbAd9V!esWIH&@Ho`Oq!-5zkNg)F$kx%VM4j8hJGgCcy%i zvTIk1K{OegAg;%xYFzvaJ-bz-ETEaRasmK`DhRr^&{e4#g32;gl?jF_98`84(@!Lp zK>PQLuLs7bY07e?26@6|&V4CDU(h0#J~^cl0IS;eYQ!LS$p8>jP6dd3?}YLbA3E$8 zLzU$Gp7+p~46p?Wk4Q|VU$DXt7*|wqlKS=B`_oi(c3v^8mJ40znH;s^Hbf{pz);h| z4mR)#Zd(oG1{TX8>vh{z=gN{t^-Gc$#aNk&5B0mcte7z2T6GH|@~$HC>WDlwETEOb z(tyV0K@XN_Xo(ZRvxK~*&|i_-dtJU6cC*Gk&hn^C=@UJl@&>RrZX0dG!X49Dbj*LG Cltb|V literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f1fea2ab24e4b298a0d6f9b8d5d084b8b42cf134 GIT binary patch literal 1339 zcmZuwO>f&q5Zxu0ltjs?>o`Fhqy>RqthN>r3kcGpEs98TzZ@lqokJKK0>xcPj8`PP zyNV-20*ZcI`U85Fj=l8IpR?DVd~Pr8rJbd0!H2G}^XAPAcbzDxIs$=-k{|I-=LKOH>o$UhNbXLW-Yd8b&129v_?06MBz5Yhp2wz z0<@uS9qX+}&!0T+wZ81MzUe)E*6n`P{i1Gba*#-+$q{?4v~x7cIXibIYOwp@+%<6T z{&{7EyM4BHp{U3<_g10i-Z~2|XYw}mj5C^~!xtZadU7n^-+8fneAYPmpdMqR=W@YN zk=ZTS@^>%_wb99k$JQLrtr=S28D3&RW=L5x`~#-=C+lsruxHj1TL_~=^eyBTgaW6S z+9nInAIQkn`@zsd=EM1Mr^L$wQ5$F8~&Vh2C#Sv$XAyc_v0|w91tKuD~ldSIZvR|)h0@AG*5fu@lit&gb|s5MJkst^WRqNKccoEp|DQ;0%c;~`kfLl5O}M&JUw1U2 zk&3k4&&IlZ71o3&DbucC5{iFC;x4HE=euB(jak4rPco%mW}{SQX&^-$2$p9uh|ZXV zf?YTeOfqJvOrT)MQYIi2G+wdvRlt*ekgulG_$ZJG)aEeeXvk!cCwb6IQpH3X@nE77 zE`uvgjeM%B(L`mv)l}XBNzxeP)Ub!|TDS2Xz#87do0#Cuf5p3ytKZVDnPDu&O`zHm zOx!Zg9q83q_i7Zq8fu!uRT1WGY4?)YKm;+yd>Oh7ud4U#X#at(TzdEJ>)P7wJ?va( z2c30Ub8nq!?p-efcF+-3b9gDv#(Bb-*fjl&{$ldi%sYjKPsSOYaQ2zGOwtEa#>LO7 QSp;v}muwaLn|Pl6A2w8TQvd(} literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..459c4a5b9ea44e8cdbccb0b79278e27d9d28126a GIT binary patch literal 1363 zcmZ8hL674!6i(Vqr<559q17G`hj&|5>Ldr)!>kZucZ3)Ol+iK>Z7(BF{L*;Wu`NF* zB@#$T%MXDgf2mhaToETO@SGG>h!n?;?eBf>eV;AP&ld?l_4j{>AF?F*H4cuSDGxs4 zm!5GW6PfB{6TcIkHj~XHjs2;fHrXai6U_YkJkIniXlW&+eXoyIZcx={VsVOBTdBbyzmN5@Iu4R3+K>7WjzS3!D1<;{9JQT>s84sdT`1?Er?$UgdIkhqb(q@QU+xX&#)9NA=nBOQHwNS39m?*EmYn% zaP#!`dIi)|?nJ0p(6l-zrx9-YP+LPQ2sJ7X%!T8WF=_rMjD*Hg81NXK*ECG0i?Cwg zrwj!qi*g0bz!OkgRh(v|+e1(dGRP5Y*kTyzHMV2!W7@Yi)&x5x0&);V;8>e6zVo(I zl3}31vKB^BGZb+ryoo%c*BFdyswF3bMS)92AhPsSn<++*aVOlM!Ag!?|y ziWZ>KD;NGj&EYmCzf)|GN+``6IPa@+uPa7J6ptTYUXJFIo#F~GP^G>-6bf1+(d&NT7#)-^q9mPF@*sz|_nNiu zZ3`t+9}_v4hxvvY9$hq%*CU>zfNWXj>02{s6rDUOqx*cZ%=S}u;(kVfqx${H&MS7^ zgbz|Ymcno8m&C_w;m_AaZ5u35Yh^=tX=_8)6y(doqq9_q9TG3NkZha_$!;^TM8y^j zyEtHxcWAmot9!0T^!a=FWkDS5!in;g*dh%jx*J^2r@Ux`(o`HBvfTCi`Q1VENQvg$ zBe$ZXWU<=>*X7M#=ZT+D9pcTd8t(%FPR~={X74i975%xcU*Kojk{-u0bhfO lKZ#9*9}02Qycw6yKWMCMHGUYcB8t4`le6?}lBI7={|2EJrX>IX literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..898c408f5b58d97fea18df5f1781dd3b08488ba6 GIT binary patch literal 5700 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..394a74d52d889ef7dfd1ce01a76b05608ae7b0e6 GIT binary patch literal 908 zcmZuvOK;Oa5Z<+&#CaA~h!(`bS4-5E+EXQjC{aoyAgz)BtuL;d-6RX^hjuqf*Pp?by}nL2BLM)>IMoL zq(ex9=qL`jKOgfP>N)yQl6_hv;@Wg?7Q#Pm07dZ%&iB&)J!uU8-rC?0CDrgo|ut(dc6|q0-M- z=7%g%R3s7iXNqy@>&Ep_rI%e6YfOgAi9#K?4}D1+0Gao&jV&x1VE5csQ3*qmj>53m zgrwfzq~0Q_7c)7!-NB>(g`plxCIWtHRFs#*(q!%ZL8tTjZc#<+MX-HG2SxKZSf#C? zd-M+P2MMguntYoQjl3>evH{WeN}0El4u A8vp5LqVm?NIR+%DYG8+oNa@*&>I++WaW zE%P!T`XF1&0_fMX^{fMZCnH1D>;4I+pdQw@k^{+$MlqU~H5Y0CzRe%^U+&ZXcU%1* z=-%tWV0-YQN3_3NtDIL!p`BMvU9i;baJ6BW^x>88dq|;kR0j&5BRCD8J>Fxg5tR%N zi~JxBPneLfS16UptHTE&7vX?cEX>DY#Z}ly@Ge3lIQf3Nh%Oh=#Uh&WY79et@7-V3 zv}W=*Bz(9`YyO_c6JD~I6-CaKI^vT`@+y`hjRmW@jFVF)A>fNFQDE|tRpyTIA*+}G zR~((N>LiBy$MsZAc=afH9LpSH>m)r+4w;PWypCyJDJB4>xKVi_tfB&Gq+||3;b8#CPi@o+4BF8PupCMgekCrb`qK9c`wlJ!mro2+sa+Q zXZN4)>_Dzn4LxLvnrd6oDK=rf_EVZp5@2kq)Muk0d-JPZpKocv7RkH zGE3gC1y7ljv`R`QA={a_XZ-6|D)J^f9t3;_ue=Wi*#vjs@!bFu9N>=STRwJ4fCC~- zs2AbF)v1w8{vu0>)`b9$j`U;X+@i1dhdSwnmq9*LR)C55Y zZKXmzpTfA;)d8jB z2IQ1cDhyD}Wdhvg#1w>Zj4=w+7EH@Td&ZS3weo4| gP5Vzuo;3w~YL-fqOC2aRpLB?g-?Mzz-}E2;1M4Ex`Tzg` literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34a4da8f8e4774c676e92beeacb93ab51d62ec14 GIT binary patch literal 5286 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/logging.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/logging.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..434cffd8eec32ed56b8363b513c7b83fb4b0e340 GIT binary patch literal 9259 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/models.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/models.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7826399fb6665d5fc0bb2a2f58b5b8eb48bb8c1 GIT binary patch literal 2019 zcmb_c&2JM&6rb5$I~&J#0t8S+OIJup_|WWuQze8D98iUbkRmR=Oegy$_BiXEWoD9+ z$mJ6L5IE+@zq40P+&T5cd%Jc>DORJVvzqtjtn`fGfz?;3`~0-i1xLj=Tpq5arEk^O-t&ES-WUW?D+Cp6l1TIDYWLnnMi; zJ*$tkGewfgQtmEH@?+@}?UG%3o8YZX_SI1*!BKTZ^GXRks@BEAbdlxKxhzD>7K7Gg z@)MkH1Idifm|(L2DVn~+PWkpAuq0+F0E4iKoXYpAkW}~ouKASNRh0SbO*%GHm8v|~ z#`}pG7YILfHcPE4jZ5Vp%Avq7AUzU2RfW?iFj9rGc$97(s^T!s^=?`o`LQYPZ~dA& zjk2Z8_T@;qwA5uPbm5gPWS$;ipk3O;b*nt8Vu5$s3$c!99KmM1&5wWjo~ySOvKc42 z`JnZgTPQ6(o3RN$;XBN>a61U9Xe`~hcFcg=HlEeCH-ugg3K9|G8txovW6Lo#l36W9 zk~nBh*z3^raWP}>Fg%`5g7=u=4UQ0hGY@tZo09xzY}FPbNApjE8d%jbeyr>__$)>H z2F?YvTT9$Sn*IYYOOP!^poXJ_uvh4WGUTh5EIH=~od1df6MG7dH{X-3y=~1^?)1)UN8Xxs3}f zUF>OCyn);BSUA+%CgF@v!jrQyimHxwx^P|=nW`II)!#P$w`rLxY)@W6Q|Vz-=~q#0 z)t)MBPVj9)Q`+Cd>8K|#-sMrStnLr~+ER6dz)p6M)4D6fs{@(OZ&ri= zli~5I5H2^~VF1_gAGSw?%DJv4OUZ00mn?`nK^%s3^H zBT>R5KY&N)k-xxC8S%yw?>zAW-^|*UlS-_$vomLA&zw2u`@VJ1Xw)oRgX6!0KNc

AUfTWXW417F*)Kz~4fAFfsHNbQ$l{@7 zew5@HmmSz@4;Txd2V5|YQ6qod_c;^UkoTBq+NvgU){FKc#)YaLppCK=>y|rN%APVA zgntQ7FI5_n4Kn^fodHVACOaJbp`*$DvJKuCV+ntB7R-ZBMKkdcyY`G0k&pQJwt-{n@F(R2wyv<-3LJ|Sa-HvfJs5O z(}N(6!WUD-Y|`yL+MT!*er}T6rGo$&O_2_>n(k#Bc`kPA>?+b~R(ToaRrQ&p7fkYs zHkFZN!BlBKi&EtzL9QI2rCCx-=XO!``Q)gp=cfHx_0)wTEPt~8H;Z4vPXD}Z53+={ zSsX{1l>6Br64Ky8w-!O!VgCW_N~74R8vzpxr)`^D8D$6;$t3pi8+= z@9%Ei+uGeaa-TnbxUt=N@a*VvC!mb==I8)rQ*FH5=BH123yX%AAY%Dp%f445wI zOsK{*I6n;%rrhaJE$Y>fTCLm$vqf`NyQ63}aEtfRSd|i~6Zc=+u9F%;-(Ddl+XZwg zPK}tgXTYOl(YFE5Ep#++P5_`08I#aJ1%qJT$BJ7;CM({xPy%0bHcDq@8}hg^Kfv)18-XBnH1f#zPn-)W}jMo z4T;0kwg{N;{hIkEI~}#K-FdOQ_2kL@9ex8&5cvmqsFiv2_;Hjnp~{*Pc@xCdD@xjU z{xl8!n!#!uGyW3migVaCa)G$G`KNl5_f^gJ_l8h$=KEZqL{&9F0ZdhANf5=Y38eH1 z)gn}?1#L{jj2i-Ym*y;3s>Mu$TB}W=(O1lZsj#)!4?SkS^1>ipotrkg*GeMMD|m73 z?Ayh(Jk0eT3p%1k5oA*QiQrlZRb{dOf8y|e0F8I`OqBEgX?R1wv4CtnDR}AnhFQqQ zhx&D`r3O=`?j~t-sn*{Ht|_M6FOw`B#_TJtyMm&rgHv^I>>_UbAkL=m)Esx+z3wjm E2P0wkZ~y=R literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/parallel.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/parallel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc2486747af07127f3043416a0259c1c87fb6312 GIT binary patch literal 3237 zcmds3O>f-B86I*eX|>X>R&p%avMi53fIvmO>o~nM2#ltx+zPQ|A(CT=mj$&mtEElO zurpjKD=0t!`QH45qV=Zo(=&-*^Zs9vuz zT>WqU5k09h_IG-jysCKlEgpN%V@$A+2~YUPe&~sc2ogW7gcXmWK9vONR5)GMXHc)Y z`gAgz*20>r&m?o{d^qpw)uf&_!iKBQCJSjZY_}jSxT>jSJDr{ z57MjQ)pR*rPFKPej9rn7FQ)KRd;WD6PRV64f8mAKP}WgiKbyx&jbt?po-?%^FnMG6 zSC7#x7Q(edrlub-(G1tbVt7+l#FDu3iecWmxFN2J!C5cSpvnY?X z;=0HC@o`@ou8n~04OEvpY^zo~=*O0)S_~4&Gow#pAuZ2OHSfzLn;iQQKaKM~k1~wP zOdREs_wbdYsQc1#t!jJ2ypL}^Bc7?VpmaC zI!*f#ajz$hR9Mh`1Pctg(CWjS9}fVS%BAFaUzQjFv-0cYyzbSw>y(L10Wo&mbMJ93 zO>~sV7JS5te4qeuGNd`>^!CVOo@t#}-tFt`t%*EVxyIrVSA+D3DC%L*K)tjdajP*j z8bNj<&5$P=>yAHZ`M}~kZf+8pW64jVWB^tG@MwkjO!97|00e-ct-a7kysOhJkzg+! zbo-zXEE%^s40H>+kwW$&FiaPP3Q`NyrzFFId7+uhyX z{R27!!f#`$sBR+Y2=Su2U1DF>a&3y4gJCAWicB%}Od-GvZ@=&kb`KuM-@aOBT?oqM zMRk&zE*|?kn6o?Q>?T&QPi|{H!8)HYb=5nI#$IjwwT5W$!6x@<7;MCQ2g`Tc3-Em zEt4eHdHzE8mDQ?kO}A}irfoYql@GXD(|$ zY5k^c5m)y!Br6EB?JUmP9fYPdDoWaeJWkM7%1SF67Bl1}HuP(PuL;8f->U{yujEk`G>hk&%Lq|h zW+8ItG8-Ue9G8=`vA%Ig8-=} zAuVYHRHvJh17FDDk&cYmCUDFk%iTP3=u(sSFLjebh19Gsa zx=m6f&t9ghqjzMkVQf+FP=bwhmcrCR>JhnS9ri6`18TE%hnfPy@{|DmIOaoZM$=oLM4r$Fd zq>aD`F{tFM;hB4Q+wjcle-`(OnNCOOZl^;PoK~pR%Hsf%YlwCnoD=^y&`~pmR&xsm zznpJ(wZtGzhvqI#y9r%xb)eoto0cJ2vxwJ7L>a`$x*dfJlVfcBwV83NzSG)D^@+4* zmR4PLePgw6Ikj))!;JhQjdnp@OqVVAX=kQEW`PWezgZ-+MCJ-ic;nqIy!qji#oTsE zKZ0AvXcN|-e2!y&e`}}nbZ=`H=lAx`*3)MPjx48fE;$_9h7J=$@;5=1Bh5)=^|R4m t>?0axKZOaFs{Xu(du;sxZ)<)N$5R!@74_Bppb}JkuU4B-4AzW z9I$aXkn(@D$NWosMMC1vi4*UQy}?T&nAN^FA8+2r@4YwC)>eza7@z$a{q7O+8!k2n z?2$+C>q8)%aGH>mhLqymNu1OTT|0LZFRg_&N<>XPgflOxr;V_Y`k|jT!zLw939s?` zTf*z2b?%03-grU!{vV)~^l8zaOObGv$V_NhwnV09N-%8{tahIt9Uig$XHWLOW#7LX z4iAP;`)=Vqma!@P10z&)oQT5vPHGdQzRlsl;t~A%84y82%1P*O8oJ!!?pqRi+~YOi z;2UoMuXCR_fj4-Iw}Jb-!?%Dp`8MAH-r`;G`$o}0>(7OWcx0l*{y{lCRQajoLiNlz zGCd_Cu6yZPtal<4p?fDPPkT|1g94dnk(v)$Js2^%S`M7!zYo903@z!BFaZ4pxuC-f zS~OXyweJ+37RgEBmpd0kZNrtnehtQXDgu!tGB;+Dk29TTfmU&##5C7I^n=hK@HvD4 zM5X{bI24RT29O#N3{FLM8YJ>Kn9j{O&mIiE473EJ2BpORV=y77fPrd)DuuXQII07z@Ukcs zHtZGI!OhM%(w8{hfSuC%Ud8&RRK)`quAmW{1#Eyt*N`Qd&?Vg?=kyhL;t}J_zoF#J zp=5D)>3C$~a{A6&()aWWNFj57A+N|0WbVxQ*~wZfexKa8x$HZ`MY|`n-cM(?IQlh( zHdPx)vHLQUan8kKf%J(|xhm>VQIN!`Sr@^b>_Fr?qE`LsqSu=zEd$>mHThAqsv-ERIUxXd#Nvh z_X#ZD+pzrc^_JI?G1fvka9$0$VtZW)MO(*8P7T9$D4Iw$bnBJMXsKDoR-&JQ;xY*z zR{Z%#X4r3I8>2eLiWXyO&SweEJB+=VMalZ4!5GhD##9%Sst=IZdf3C+Z6tS)VBR;% z!(xXGt9&5Xa2oIX)N_0fzNV#~JstKt;T}9Y0|t*1&()yv+}IKfcQ((p{L%JQaog^e zkJZ3FRs%Di%50>tgo^rlQG7sJrY8JBzx<^j*z;>`$Df?YMfm_UVn!Zuplz z{NU2Z{^!?scCPMRaT}%iNhI^qzLw=tngnra@A9wbJPG;Y_h^=-B6sAW+;k+*=UJYn zG1_^0izm^7Z_(5s5R-#1Uj5S9cD{M_f;if8e19Cp-1oPu{&;)B^B~W~#&X@Jvz}%= zS>JT1ayOO>+^sNWe0w|)JYX9xsw@sdzOjB&+$8CBlqWN5#sp=UB9H-2su+AsRV zP$Rl{qcDqV))4PQqOp_(%4U%2n$~uZu5dthjFtoaW?l(9eQ=dePaNa)(;Di)w0+9a4M5mzxew zub#x|D2V-3U9!CByvJBn-M3Rs;U=grA6S*7{#gZ` z);JZjAa|Q(PuuV^hmN<*i|M!^<%;s956*|+I@nb{zN`t|FCXLE-ippP1ctvw(@2(*_SR#5T%FYPP z$^F|?&SP90yQ{0y+@_$osRYZOQh!O+a+PtJM~R}8&mtlEBuPM5#TnYydDzfX=O}w$ zgOnsutz+ow``c>vVX+`2LW5@NL^1j}LOhSo1J)Xa!C&+eOPa`h0^#6)=RQgYo2J_)x|Ry30pK?CmZ##zVxmXmgp9y=zgSq zt5>=g4W{F!T1AUNd!;+t>YiGVd(nCjeC}Z*kC%~`A7ELJ$~TrWkA0%<6zu zBv)X}E-H3)aNZB-Ra6=gBCU#N0c;V}?lV@jF#yjSoG%+=#er0p5x<&BZxjBhFLt z92LYMB7FT1vgj)AFMDS_uRhM3;)e#iS6AFUA-i}1JCv)HD(bf>2|#aC9p=znyIQJf zZ~+72MJkj_tYnAvQIF)te;i=xS455Pv5TarsP(%bdhG(bao@7~dfR{lkQ1m(jzGC0 zkBvW6ta2MWmoK}0L98jC#e+0Bevk(0K^o+T8DJF@T1%_$kS7UpA3+gIQ0P(*fQrH@ zv?-4hL{N3isX(tnzKZtt+q0C-WBv~QxHL((VH>34<15BLMn}`}-EW_>pRoJ(1$*sZ D|GWPS literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4f086558414dc2c4c020652e053162b6c92a023e GIT binary patch literal 6102 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 Q%3P@Qu>4Q&7sj>!0h5=n5&!@I literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a7fd2146d45e4591bd6ff3f5aebc0b8a34c8261 GIT binary patch literal 7247 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/urls.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/urls.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..135104a23b51b2f682313c17790ebb7467634d9a GIT binary patch literal 1563 zcmZux&2Jnv6t_JeJK0RqHVQ;VNVr_+R_ctDo*E&j6cs3xfZ7Hrqe!dC+R02hV^3}G zrU|>3mNS3DM&iQ1s%C$e|3nD=<%D+^ z0pS5`T>)W;;RY3p6Big{(vUVNLhN(_@KF(aK5TkzQY0AhL_G#u)GW3AqTenT%WYbu z;1jdnZ>U&d30s15mG#*&oYxqBiU#Q$_!`<7U>kL%(j1tc;xEQr8(`Od-1~WNxc%M3 z?H`6uc6W9j?R+~3Z1PiQYAMRbhR^s*W20RG;t0D)m&@@X>}}YZ0%3THCRn8mJw;PA z2bqy`!h)Mq5v!cdPY-g1|bj)5SO;1H{8z`a)u z*IH-y)wlzULC1JbJPoGk9G~MEGT}U8*u?Xm*N_>Wx(1Q6s!w5UOEKZf(2{ngsi={_ z9o7xsqPtHXXOupx_`-5hHw``Dv@IE@<$;#X*Z?CKt;z}av0jX&;cVd!T{k-O>Wjz+ z93+-VZA14Rn+T~|&-EadXHs}MRBq_;VtXJR%UamgOZ6psZ0ejv+44;=42W8TcdOJ9 zSFZ(G1Khi$h`3{-`s5zCD6zT@DWBcnlVdt61(l*XrDm+eWhOlYuYuXIfTw`y^Y+reQg{TPHJd-?2M(cu@9-$N07EnTzY;c1AVG( zauvk(e<_ACbzRiU0rr literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5ae2ce1b6f475bdb86f5bde652d4f5255018a5e GIT binary patch literal 3396 zcmaJ@&vV;07A8naq-7;`6DQ5?W>PerX{wGbd1u?1?oNMY93{;(aXqm+Z8YsLv;ax8 zDS`z+JJ#Bl_3m-of5AR>rvJwN6TI%J_nvy`z6VH_?08EJ2?7KJyzhPQdoR9nrRKmj zIQk_XU3HxQVrTa9pz|r*>L++Ghmq77k`5vG?xt?XHLch2OzU@i(^fha(^flG(*~UY zS}zTUbDcTj@HzPn^!>CpobSvJ>zz7`c_&x+)l<@0;FXg_R)M$ISd|6;bUN2q$mXEE z&T4EP+9g(JSD?MYuCfJaZ?Z-98nmyoYwS9-x0t)>G?spb6FUu3F2vhPq=n{DGR%e4 z>o9ih>GO@}(b{M2wa=qxU#_n|UVqeZOaDotbQyk;>qKO6I{F~Vx@p1qiaJo54_8#8 z`AQylcjG=+->7##g8Q9MHa^^o(}I7jWx)@7ajJNui(AiL73i$Nt(M@SogJcG4PfHi zvA65Naoth2HsIY|MUx(d{hHgc;!!SnFL_DhjG3`SOR+~z_Hcm8J95BYVN@) zT4}P~$`ABFWPfS?wRH~CR-WXoD9JRJ0Dr5{Nvc|73t(w8KPaz9vdFR|>qkY#xQy^G zZy>NPJe;bm!}AsNk;Ddlv_(6bFmj9(aYw`Rm`fg~6U+ft#r0(0u7ikP;TereL-+^h?_&_ee z`zyv17&OKsG}<|K@|q^c4wz3ykDhT|$c%0Qb&+@b{GQ}=j4(~We~i<3#*StB5D89& z9&ovzC~ggFxCVH0fJ^PTb-`bL9{bxu=*^KnV|>2hO+e9ue)G_=n__9Jz-s%p;N>x+fLppAuHtbtSd4 zzoV=Q-U{Ll@Z1D5eer)h_Ja0=L>UDsr{{DBm<~FRVr6|bkx`ZNZqiFYSoI**bbr9J z%h$&cHRwiFmZ+sjM@v5JO!x}LK!H>=RxQU z4j{)6d6OL0+$t+3>y{N`;=@MO(5|e4VSO&kU~F3XR`hs%?a7x9+R^6o&8_y+X!G$_ zJKDIv_WAus?ak;}`%(MrvSKo7S?Nnr50y~OQhr(wH zhm!!q!=$nQSmuKp?`C4fp6PtG($p{YUCLjAFez|{5q88Ka;l|=sUwC7Dgx-2=qFvo z9TVA11~w7IIOJ#WA9@f%0yDulDhxr-dlMsL5&~mBUy?p8$wq(rox?Xmc@4mk*WpnH zEP)DP$jbm~JF9%SZ5c*JzoJNDomEz?y`XS){2UDhi(qAWd+IndJ}K$U;)`y6E1J%> zHOH$-_*>XbnL;|aNvg#E&G%#z#?Cn!`jB+SDu^11Dk$qV8EY5bZ)pz`GqX;8I!PHZ z-4-I{akhMh_cTRQOh~rs$i$`UWWjyd@NJGp0@_54C!Dd?6naMNm!{>#)c9SPZEdVp zN!7($qW(AjP}TtU0tyKZz$2X{R%B&>p$H@~ek)zcWdpxqtyBIHD!t}erPnl-UQ-|B zINieu)o};YhQ#nF=O6(+vB3>)M(@LJZ{U{z%UwuY@=ctK>B!oL^@LFc6LiKQ=ERrU q9DWGwC{q40x=3MJQiq^D`?+=3CyQ>4*nke_!de)Fi{YK{>i+<=wYl{G literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4879ad5fbe31aa4ea219e6ba1f74501e7c4c7f30 GIT binary patch literal 6375 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 XsF{{oHK*sDx19sd38&`FIs5+u?2W5i literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/appdirs.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/appdirs.py new file mode 100644 index 0000000..3989ed3 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/appdirs.py @@ -0,0 +1,44 @@ +""" +This code wraps the vendored appdirs module to so the return values are +compatible for the current pip code base. + +The intention is to rewrite current usages gradually, keeping the tests pass, +and eventually drop this after all usages are changed. +""" + +from __future__ import absolute_import + +import os + +from pip._vendor import appdirs as _appdirs + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List + + +def user_cache_dir(appname): + # type: (str) -> str + return _appdirs.user_cache_dir(appname, appauthor=False) + + +def user_config_dir(appname, roaming=True): + # type: (str, bool) -> str + path = _appdirs.user_config_dir(appname, appauthor=False, roaming=roaming) + if _appdirs.system == "darwin" and not os.path.isdir(path): + path = os.path.expanduser('~/.config/') + if appname: + path = os.path.join(path, appname) + return path + + +# for the discussion regarding site_config_dir locations +# see +def site_config_dirs(appname): + # type: (str) -> List[str] + dirval = _appdirs.site_config_dir(appname, appauthor=False, multipath=True) + if _appdirs.system not in ["win32", "darwin"]: + # always look in /etc directly as well + return dirval.split(os.pathsep) + ['/etc'] + return [dirval] diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/compat.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/compat.py new file mode 100644 index 0000000..2196e6e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/compat.py @@ -0,0 +1,293 @@ +"""Stuff that differs in different Python versions and platform +distributions.""" + +# The following comment should be removed at some point in the future. +# mypy: disallow-untyped-defs=False + +from __future__ import absolute_import, division + +import codecs +import functools +import locale +import logging +import os +import shutil +import sys + +from pip._vendor.six import PY2, text_type + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Callable, Optional, Protocol, Text, Tuple, TypeVar, Union + + # Used in the @lru_cache polyfill. + F = TypeVar('F') + + class LruCache(Protocol): + def __call__(self, maxsize=None): + # type: (Optional[int]) -> Callable[[F], F] + raise NotImplementedError + +try: + import ipaddress +except ImportError: + try: + from pip._vendor import ipaddress # type: ignore + except ImportError: + import ipaddr as ipaddress # type: ignore + ipaddress.ip_address = ipaddress.IPAddress # type: ignore + ipaddress.ip_network = ipaddress.IPNetwork # type: ignore + + +__all__ = [ + "ipaddress", "uses_pycache", "console_to_str", + "get_path_uid", "stdlib_pkgs", "WINDOWS", "samefile", "get_terminal_size", +] + + +logger = logging.getLogger(__name__) + +if PY2: + import imp + + try: + cache_from_source = imp.cache_from_source # type: ignore + except AttributeError: + # does not use __pycache__ + cache_from_source = None + + uses_pycache = cache_from_source is not None +else: + uses_pycache = True + from importlib.util import cache_from_source + + +if PY2: + # In Python 2.7, backslashreplace exists + # but does not support use for decoding. + # We implement our own replace handler for this + # situation, so that we can consistently use + # backslash replacement for all versions. + def backslashreplace_decode_fn(err): + raw_bytes = (err.object[i] for i in range(err.start, err.end)) + # Python 2 gave us characters - convert to numeric bytes + raw_bytes = (ord(b) for b in raw_bytes) + return u"".join(map(u"\\x{:x}".format, raw_bytes)), err.end + codecs.register_error( + "backslashreplace_decode", + backslashreplace_decode_fn, + ) + backslashreplace_decode = "backslashreplace_decode" +else: + backslashreplace_decode = "backslashreplace" + + +def has_tls(): + # type: () -> bool + try: + import _ssl # noqa: F401 # ignore unused + return True + except ImportError: + pass + + from pip._vendor.urllib3.util import IS_PYOPENSSL + return IS_PYOPENSSL + + +def str_to_display(data, desc=None): + # type: (Union[bytes, Text], Optional[str]) -> Text + """ + For display or logging purposes, convert a bytes object (or text) to + text (e.g. unicode in Python 2) safe for output. + + :param desc: An optional phrase describing the input data, for use in + the log message if a warning is logged. Defaults to "Bytes object". + + This function should never error out and so can take a best effort + approach. It is okay to be lossy if needed since the return value is + just for display. + + We assume the data is in the locale preferred encoding. If it won't + decode properly, we warn the user but decode as best we can. + + We also ensure that the output can be safely written to standard output + without encoding errors. + """ + if isinstance(data, text_type): + return data + + # Otherwise, data is a bytes object (str in Python 2). + # First, get the encoding we assume. This is the preferred + # encoding for the locale, unless that is not found, or + # it is ASCII, in which case assume UTF-8 + encoding = locale.getpreferredencoding() + if (not encoding) or codecs.lookup(encoding).name == "ascii": + encoding = "utf-8" + + # Now try to decode the data - if we fail, warn the user and + # decode with replacement. + try: + decoded_data = data.decode(encoding) + except UnicodeDecodeError: + logger.warning( + '%s does not appear to be encoded as %s', + desc or 'Bytes object', + encoding, + ) + decoded_data = data.decode(encoding, errors=backslashreplace_decode) + + # Make sure we can print the output, by encoding it to the output + # encoding with replacement of unencodable characters, and then + # decoding again. + # We use stderr's encoding because it's less likely to be + # redirected and if we don't find an encoding we skip this + # step (on the assumption that output is wrapped by something + # that won't fail). + # The double getattr is to deal with the possibility that we're + # being called in a situation where sys.__stderr__ doesn't exist, + # or doesn't have an encoding attribute. Neither of these cases + # should occur in normal pip use, but there's no harm in checking + # in case people use pip in (unsupported) unusual situations. + output_encoding = getattr(getattr(sys, "__stderr__", None), + "encoding", None) + + if output_encoding: + output_encoded = decoded_data.encode( + output_encoding, + errors="backslashreplace" + ) + decoded_data = output_encoded.decode(output_encoding) + + return decoded_data + + +def console_to_str(data): + # type: (bytes) -> Text + """Return a string, safe for output, of subprocess output. + """ + return str_to_display(data, desc='Subprocess output') + + +def get_path_uid(path): + # type: (str) -> int + """ + Return path's uid. + + Does not follow symlinks: + https://github.com/pypa/pip/pull/935#discussion_r5307003 + + Placed this function in compat due to differences on AIX and + Jython, that should eventually go away. + + :raises OSError: When path is a symlink or can't be read. + """ + if hasattr(os, 'O_NOFOLLOW'): + fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) + file_uid = os.fstat(fd).st_uid + os.close(fd) + else: # AIX and Jython + # WARNING: time of check vulnerability, but best we can do w/o NOFOLLOW + if not os.path.islink(path): + # older versions of Jython don't have `os.fstat` + file_uid = os.stat(path).st_uid + else: + # raise OSError for parity with os.O_NOFOLLOW above + raise OSError( + "{} is a symlink; Will not return uid for symlinks".format( + path) + ) + return file_uid + + +def expanduser(path): + # type: (str) -> str + """ + Expand ~ and ~user constructions. + + Includes a workaround for https://bugs.python.org/issue14768 + """ + expanded = os.path.expanduser(path) + if path.startswith('~/') and expanded.startswith('//'): + expanded = expanded[1:] + return expanded + + +# packages in the stdlib that may have installation metadata, but should not be +# considered 'installed'. this theoretically could be determined based on +# dist.location (py27:`sysconfig.get_paths()['stdlib']`, +# py26:sysconfig.get_config_vars('LIBDEST')), but fear platform variation may +# make this ineffective, so hard-coding +stdlib_pkgs = {"python", "wsgiref", "argparse"} + + +# windows detection, covers cpython and ironpython +WINDOWS = (sys.platform.startswith("win") or + (sys.platform == 'cli' and os.name == 'nt')) + + +def samefile(file1, file2): + # type: (str, str) -> bool + """Provide an alternative for os.path.samefile on Windows/Python2""" + if hasattr(os.path, 'samefile'): + return os.path.samefile(file1, file2) + else: + path1 = os.path.normcase(os.path.abspath(file1)) + path2 = os.path.normcase(os.path.abspath(file2)) + return path1 == path2 + + +if hasattr(shutil, 'get_terminal_size'): + def get_terminal_size(): + # type: () -> Tuple[int, int] + """ + Returns a tuple (x, y) representing the width(x) and the height(y) + in characters of the terminal window. + """ + return tuple(shutil.get_terminal_size()) # type: ignore +else: + def get_terminal_size(): + # type: () -> Tuple[int, int] + """ + Returns a tuple (x, y) representing the width(x) and the height(y) + in characters of the terminal window. + """ + def ioctl_GWINSZ(fd): + try: + import fcntl + import struct + import termios + cr = struct.unpack_from( + 'hh', + fcntl.ioctl(fd, termios.TIOCGWINSZ, '12345678') + ) + except Exception: + return None + if cr == (0, 0): + return None + return cr + cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) + if not cr: + if sys.platform != "win32": + try: + fd = os.open(os.ctermid(), os.O_RDONLY) + cr = ioctl_GWINSZ(fd) + os.close(fd) + except Exception: + pass + if not cr: + cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80)) + return int(cr[1]), int(cr[0]) + + +# Fallback to noop_lru_cache in Python 2 +# TODO: this can be removed when python 2 support is dropped! +def noop_lru_cache(maxsize=None): + # type: (Optional[int]) -> Callable[[F], F] + def _wrapper(f): + # type: (F) -> F + return f + return _wrapper + + +lru_cache = getattr(functools, "lru_cache", noop_lru_cache) # type: LruCache diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/compatibility_tags.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/compatibility_tags.py new file mode 100644 index 0000000..6780f9d --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/compatibility_tags.py @@ -0,0 +1,178 @@ +"""Generate and work with PEP 425 Compatibility Tags. +""" + +from __future__ import absolute_import + +import re + +from pip._vendor.packaging.tags import ( + Tag, + compatible_tags, + cpython_tags, + generic_tags, + interpreter_name, + interpreter_version, + mac_platforms, +) + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional, Tuple + + from pip._vendor.packaging.tags import PythonVersion + +_osx_arch_pat = re.compile(r'(.+)_(\d+)_(\d+)_(.+)') + + +def version_info_to_nodot(version_info): + # type: (Tuple[int, ...]) -> str + # Only use up to the first two numbers. + return ''.join(map(str, version_info[:2])) + + +def _mac_platforms(arch): + # type: (str) -> List[str] + match = _osx_arch_pat.match(arch) + if match: + name, major, minor, actual_arch = match.groups() + mac_version = (int(major), int(minor)) + arches = [ + # Since we have always only checked that the platform starts + # with "macosx", for backwards-compatibility we extract the + # actual prefix provided by the user in case they provided + # something like "macosxcustom_". It may be good to remove + # this as undocumented or deprecate it in the future. + '{}_{}'.format(name, arch[len('macosx_'):]) + for arch in mac_platforms(mac_version, actual_arch) + ] + else: + # arch pattern didn't match (?!) + arches = [arch] + return arches + + +def _custom_manylinux_platforms(arch): + # type: (str) -> List[str] + arches = [arch] + arch_prefix, arch_sep, arch_suffix = arch.partition('_') + if arch_prefix == 'manylinux2014': + # manylinux1/manylinux2010 wheels run on most manylinux2014 systems + # with the exception of wheels depending on ncurses. PEP 599 states + # manylinux1/manylinux2010 wheels should be considered + # manylinux2014 wheels: + # https://www.python.org/dev/peps/pep-0599/#backwards-compatibility-with-manylinux2010-wheels + if arch_suffix in {'i686', 'x86_64'}: + arches.append('manylinux2010' + arch_sep + arch_suffix) + arches.append('manylinux1' + arch_sep + arch_suffix) + elif arch_prefix == 'manylinux2010': + # manylinux1 wheels run on most manylinux2010 systems with the + # exception of wheels depending on ncurses. PEP 571 states + # manylinux1 wheels should be considered manylinux2010 wheels: + # https://www.python.org/dev/peps/pep-0571/#backwards-compatibility-with-manylinux1-wheels + arches.append('manylinux1' + arch_sep + arch_suffix) + return arches + + +def _get_custom_platforms(arch): + # type: (str) -> List[str] + arch_prefix, arch_sep, arch_suffix = arch.partition('_') + if arch.startswith('macosx'): + arches = _mac_platforms(arch) + elif arch_prefix in ['manylinux2014', 'manylinux2010']: + arches = _custom_manylinux_platforms(arch) + else: + arches = [arch] + return arches + + +def _expand_allowed_platforms(platforms): + # type: (Optional[List[str]]) -> Optional[List[str]] + if not platforms: + return None + + seen = set() + result = [] + + for p in platforms: + if p in seen: + continue + additions = [c for c in _get_custom_platforms(p) if c not in seen] + seen.update(additions) + result.extend(additions) + + return result + + +def _get_python_version(version): + # type: (str) -> PythonVersion + if len(version) > 1: + return int(version[0]), int(version[1:]) + else: + return (int(version[0]),) + + +def _get_custom_interpreter(implementation=None, version=None): + # type: (Optional[str], Optional[str]) -> str + if implementation is None: + implementation = interpreter_name() + if version is None: + version = interpreter_version() + return "{}{}".format(implementation, version) + + +def get_supported( + version=None, # type: Optional[str] + platforms=None, # type: Optional[List[str]] + impl=None, # type: Optional[str] + abis=None # type: Optional[List[str]] +): + # type: (...) -> List[Tag] + """Return a list of supported tags for each version specified in + `versions`. + + :param version: a string version, of the form "33" or "32", + or None. The version will be assumed to support our ABI. + :param platform: specify a list of platforms you want valid + tags for, or None. If None, use the local system platform. + :param impl: specify the exact implementation you want valid + tags for, or None. If None, use the local interpreter impl. + :param abis: specify a list of abis you want valid + tags for, or None. If None, use the local interpreter abi. + """ + supported = [] # type: List[Tag] + + python_version = None # type: Optional[PythonVersion] + if version is not None: + python_version = _get_python_version(version) + + interpreter = _get_custom_interpreter(impl, version) + + platforms = _expand_allowed_platforms(platforms) + + is_cpython = (impl or interpreter_name()) == "cp" + if is_cpython: + supported.extend( + cpython_tags( + python_version=python_version, + abis=abis, + platforms=platforms, + ) + ) + else: + supported.extend( + generic_tags( + interpreter=interpreter, + abis=abis, + platforms=platforms, + ) + ) + supported.extend( + compatible_tags( + python_version=python_version, + interpreter=interpreter, + platforms=platforms, + ) + ) + + return supported diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/datetime.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/datetime.py new file mode 100644 index 0000000..4d0503c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/datetime.py @@ -0,0 +1,14 @@ +"""For when pip wants to check the date or time. +""" + +from __future__ import absolute_import + +import datetime + + +def today_is_later_than(year, month, day): + # type: (int, int, int) -> bool + today = datetime.date.today() + given = datetime.date(year, month, day) + + return today > given diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/deprecation.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/deprecation.py new file mode 100644 index 0000000..2f20cfd --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/deprecation.py @@ -0,0 +1,104 @@ +""" +A module that implements tooling to enable easy warnings about deprecations. +""" + +# The following comment should be removed at some point in the future. +# mypy: disallow-untyped-defs=False + +from __future__ import absolute_import + +import logging +import warnings + +from pip._vendor.packaging.version import parse + +from pip import __version__ as current_version +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Optional + + +DEPRECATION_MSG_PREFIX = "DEPRECATION: " + + +class PipDeprecationWarning(Warning): + pass + + +_original_showwarning = None # type: Any + + +# Warnings <-> Logging Integration +def _showwarning(message, category, filename, lineno, file=None, line=None): + if file is not None: + if _original_showwarning is not None: + _original_showwarning( + message, category, filename, lineno, file, line, + ) + elif issubclass(category, PipDeprecationWarning): + # We use a specially named logger which will handle all of the + # deprecation messages for pip. + logger = logging.getLogger("pip._internal.deprecations") + logger.warning(message) + else: + _original_showwarning( + message, category, filename, lineno, file, line, + ) + + +def install_warning_logger(): + # type: () -> None + # Enable our Deprecation Warnings + warnings.simplefilter("default", PipDeprecationWarning, append=True) + + global _original_showwarning + + if _original_showwarning is None: + _original_showwarning = warnings.showwarning + warnings.showwarning = _showwarning + + +def deprecated(reason, replacement, gone_in, issue=None): + # type: (str, Optional[str], Optional[str], Optional[int]) -> None + """Helper to deprecate existing functionality. + + reason: + Textual reason shown to the user about why this functionality has + been deprecated. + replacement: + Textual suggestion shown to the user about what alternative + functionality they can use. + gone_in: + The version of pip does this functionality should get removed in. + Raises errors if pip's current version is greater than or equal to + this. + issue: + Issue number on the tracker that would serve as a useful place for + users to find related discussion and provide feedback. + + Always pass replacement, gone_in and issue as keyword arguments for clarity + at the call site. + """ + + # Construct a nice message. + # This is eagerly formatted as we want it to get logged as if someone + # typed this entire message out. + sentences = [ + (reason, DEPRECATION_MSG_PREFIX + "{}"), + (gone_in, "pip {} will remove support for this functionality."), + (replacement, "A possible replacement is {}."), + (issue, ( + "You can find discussion regarding this at " + "https://github.com/pypa/pip/issues/{}." + )), + ] + message = " ".join( + template.format(val) for val, template in sentences if val is not None + ) + + # Raise as an error if it has to be removed. + if gone_in is not None and parse(current_version) >= parse(gone_in): + raise PipDeprecationWarning(message) + + warnings.warn(message, category=PipDeprecationWarning, stacklevel=2) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/direct_url_helpers.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/direct_url_helpers.py new file mode 100644 index 0000000..87bd61f --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/direct_url_helpers.py @@ -0,0 +1,126 @@ +import logging + +from pip._internal.models.direct_url import ( + DIRECT_URL_METADATA_NAME, + ArchiveInfo, + DirectUrl, + DirectUrlValidationError, + DirInfo, + VcsInfo, +) +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.vcs import vcs + +try: + from json import JSONDecodeError +except ImportError: + # PY2 + JSONDecodeError = ValueError # type: ignore + +if MYPY_CHECK_RUNNING: + from typing import Optional + + from pip._vendor.pkg_resources import Distribution + + from pip._internal.models.link import Link + +logger = logging.getLogger(__name__) + + +def direct_url_as_pep440_direct_reference(direct_url, name): + # type: (DirectUrl, str) -> str + """Convert a DirectUrl to a pip requirement string.""" + direct_url.validate() # if invalid, this is a pip bug + requirement = name + " @ " + fragments = [] + if isinstance(direct_url.info, VcsInfo): + requirement += "{}+{}@{}".format( + direct_url.info.vcs, direct_url.url, direct_url.info.commit_id + ) + elif isinstance(direct_url.info, ArchiveInfo): + requirement += direct_url.url + if direct_url.info.hash: + fragments.append(direct_url.info.hash) + else: + assert isinstance(direct_url.info, DirInfo) + requirement += direct_url.url + if direct_url.subdirectory: + fragments.append("subdirectory=" + direct_url.subdirectory) + if fragments: + requirement += "#" + "&".join(fragments) + return requirement + + +def direct_url_from_link(link, source_dir=None, link_is_in_wheel_cache=False): + # type: (Link, Optional[str], bool) -> DirectUrl + if link.is_vcs: + vcs_backend = vcs.get_backend_for_scheme(link.scheme) + assert vcs_backend + url, requested_revision, _ = ( + vcs_backend.get_url_rev_and_auth(link.url_without_fragment) + ) + # For VCS links, we need to find out and add commit_id. + if link_is_in_wheel_cache: + # If the requested VCS link corresponds to a cached + # wheel, it means the requested revision was an + # immutable commit hash, otherwise it would not have + # been cached. In that case we don't have a source_dir + # with the VCS checkout. + assert requested_revision + commit_id = requested_revision + else: + # If the wheel was not in cache, it means we have + # had to checkout from VCS to build and we have a source_dir + # which we can inspect to find out the commit id. + assert source_dir + commit_id = vcs_backend.get_revision(source_dir) + return DirectUrl( + url=url, + info=VcsInfo( + vcs=vcs_backend.name, + commit_id=commit_id, + requested_revision=requested_revision, + ), + subdirectory=link.subdirectory_fragment, + ) + elif link.is_existing_dir(): + return DirectUrl( + url=link.url_without_fragment, + info=DirInfo(), + subdirectory=link.subdirectory_fragment, + ) + else: + hash = None + hash_name = link.hash_name + if hash_name: + hash = "{}={}".format(hash_name, link.hash) + return DirectUrl( + url=link.url_without_fragment, + info=ArchiveInfo(hash=hash), + subdirectory=link.subdirectory_fragment, + ) + + +def dist_get_direct_url(dist): + # type: (Distribution) -> Optional[DirectUrl] + """Obtain a DirectUrl from a pkg_resource.Distribution. + + Returns None if the distribution has no `direct_url.json` metadata, + or if `direct_url.json` is invalid. + """ + if not dist.has_metadata(DIRECT_URL_METADATA_NAME): + return None + try: + return DirectUrl.from_json(dist.get_metadata(DIRECT_URL_METADATA_NAME)) + except ( + DirectUrlValidationError, + JSONDecodeError, + UnicodeDecodeError + ) as e: + logger.warning( + "Error parsing %s for %s: %s", + DIRECT_URL_METADATA_NAME, + dist.project_name, + e, + ) + return None diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/distutils_args.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/distutils_args.py new file mode 100644 index 0000000..e38e402 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/distutils_args.py @@ -0,0 +1,48 @@ +from distutils.errors import DistutilsArgError +from distutils.fancy_getopt import FancyGetopt + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Dict, List + + +_options = [ + ("exec-prefix=", None, ""), + ("home=", None, ""), + ("install-base=", None, ""), + ("install-data=", None, ""), + ("install-headers=", None, ""), + ("install-lib=", None, ""), + ("install-platlib=", None, ""), + ("install-purelib=", None, ""), + ("install-scripts=", None, ""), + ("prefix=", None, ""), + ("root=", None, ""), + ("user", None, ""), +] + + +# typeshed doesn't permit Tuple[str, None, str], see python/typeshed#3469. +_distutils_getopt = FancyGetopt(_options) # type: ignore + + +def parse_distutils_args(args): + # type: (List[str]) -> Dict[str, str] + """Parse provided arguments, returning an object that has the + matched arguments. + + Any unknown arguments are ignored. + """ + result = {} + for arg in args: + try: + _, match = _distutils_getopt.getopt(args=[arg]) + except DistutilsArgError: + # We don't care about any other options, which here may be + # considered unrecognized since our option list is not + # exhaustive. + pass + else: + result.update(match.__dict__) + return result diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/encoding.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/encoding.py new file mode 100644 index 0000000..42a5753 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/encoding.py @@ -0,0 +1,41 @@ +import codecs +import locale +import re +import sys + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Text, Tuple + +BOMS = [ + (codecs.BOM_UTF8, 'utf-8'), + (codecs.BOM_UTF16, 'utf-16'), + (codecs.BOM_UTF16_BE, 'utf-16-be'), + (codecs.BOM_UTF16_LE, 'utf-16-le'), + (codecs.BOM_UTF32, 'utf-32'), + (codecs.BOM_UTF32_BE, 'utf-32-be'), + (codecs.BOM_UTF32_LE, 'utf-32-le'), +] # type: List[Tuple[bytes, Text]] + +ENCODING_RE = re.compile(br'coding[:=]\s*([-\w.]+)') + + +def auto_decode(data): + # type: (bytes) -> Text + """Check a bytes string for a BOM to correctly detect the encoding + + Fallback to locale.getpreferredencoding(False) like open() on Python3""" + for bom, encoding in BOMS: + if data.startswith(bom): + return data[len(bom):].decode(encoding) + # Lets check the first two lines as in PEP263 + for line in data.split(b'\n')[:2]: + if line[0:1] == b'#' and ENCODING_RE.search(line): + result = ENCODING_RE.search(line) + assert result is not None + encoding = result.groups()[0].decode('ascii') + return data.decode(encoding) + return data.decode( + locale.getpreferredencoding(False) or sys.getdefaultencoding(), + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/entrypoints.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/entrypoints.py new file mode 100644 index 0000000..64d1cb2 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/entrypoints.py @@ -0,0 +1,31 @@ +import sys + +from pip._internal.cli.main import main +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional + + +def _wrapper(args=None): + # type: (Optional[List[str]]) -> int + """Central wrapper for all old entrypoints. + + Historically pip has had several entrypoints defined. Because of issues + arising from PATH, sys.path, multiple Pythons, their interactions, and most + of them having a pip installed, users suffer every time an entrypoint gets + moved. + + To alleviate this pain, and provide a mechanism for warning users and + directing them to an appropriate place for help, we now define all of + our old entrypoints as wrappers for the current one. + """ + sys.stderr.write( + "WARNING: pip is being invoked by an old script wrapper. This will " + "fail in a future version of pip.\n" + "Please see https://github.com/pypa/pip/issues/5599 for advice on " + "fixing the underlying issue.\n" + "To avoid this problem you can invoke Python with '-m pip' instead of " + "running pip directly.\n" + ) + return main(args) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/filesystem.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/filesystem.py new file mode 100644 index 0000000..303243f --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/filesystem.py @@ -0,0 +1,224 @@ +import errno +import fnmatch +import os +import os.path +import random +import shutil +import stat +import sys +from contextlib import contextmanager +from tempfile import NamedTemporaryFile + +# NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is +# why we ignore the type on this import. +from pip._vendor.retrying import retry # type: ignore +from pip._vendor.six import PY2 + +from pip._internal.utils.compat import get_path_uid +from pip._internal.utils.misc import format_size +from pip._internal.utils.typing import MYPY_CHECK_RUNNING, cast + +if MYPY_CHECK_RUNNING: + from typing import Any, BinaryIO, Iterator, List, Union + + class NamedTemporaryFileResult(BinaryIO): + @property + def file(self): + # type: () -> BinaryIO + pass + + +def check_path_owner(path): + # type: (str) -> bool + # If we don't have a way to check the effective uid of this process, then + # we'll just assume that we own the directory. + if sys.platform == "win32" or not hasattr(os, "geteuid"): + return True + + assert os.path.isabs(path) + + previous = None + while path != previous: + if os.path.lexists(path): + # Check if path is writable by current user. + if os.geteuid() == 0: + # Special handling for root user in order to handle properly + # cases where users use sudo without -H flag. + try: + path_uid = get_path_uid(path) + except OSError: + return False + return path_uid == 0 + else: + return os.access(path, os.W_OK) + else: + previous, path = path, os.path.dirname(path) + return False # assume we don't own the path + + +def copy2_fixed(src, dest): + # type: (str, str) -> None + """Wrap shutil.copy2() but map errors copying socket files to + SpecialFileError as expected. + + See also https://bugs.python.org/issue37700. + """ + try: + shutil.copy2(src, dest) + except (OSError, IOError): + for f in [src, dest]: + try: + is_socket_file = is_socket(f) + except OSError: + # An error has already occurred. Another error here is not + # a problem and we can ignore it. + pass + else: + if is_socket_file: + raise shutil.SpecialFileError( + "`{f}` is a socket".format(**locals())) + + raise + + +def is_socket(path): + # type: (str) -> bool + return stat.S_ISSOCK(os.lstat(path).st_mode) + + +@contextmanager +def adjacent_tmp_file(path, **kwargs): + # type: (str, **Any) -> Iterator[NamedTemporaryFileResult] + """Return a file-like object pointing to a tmp file next to path. + + The file is created securely and is ensured to be written to disk + after the context reaches its end. + + kwargs will be passed to tempfile.NamedTemporaryFile to control + the way the temporary file will be opened. + """ + with NamedTemporaryFile( + delete=False, + dir=os.path.dirname(path), + prefix=os.path.basename(path), + suffix='.tmp', + **kwargs + ) as f: + result = cast('NamedTemporaryFileResult', f) + try: + yield result + finally: + result.file.flush() + os.fsync(result.file.fileno()) + + +_replace_retry = retry(stop_max_delay=1000, wait_fixed=250) + +if PY2: + @_replace_retry + def replace(src, dest): + # type: (str, str) -> None + try: + os.rename(src, dest) + except OSError: + os.remove(dest) + os.rename(src, dest) + +else: + replace = _replace_retry(os.replace) + + +# test_writable_dir and _test_writable_dir_win are copied from Flit, +# with the author's agreement to also place them under pip's license. +def test_writable_dir(path): + # type: (str) -> bool + """Check if a directory is writable. + + Uses os.access() on POSIX, tries creating files on Windows. + """ + # If the directory doesn't exist, find the closest parent that does. + while not os.path.isdir(path): + parent = os.path.dirname(path) + if parent == path: + break # Should never get here, but infinite loops are bad + path = parent + + if os.name == 'posix': + return os.access(path, os.W_OK) + + return _test_writable_dir_win(path) + + +def _test_writable_dir_win(path): + # type: (str) -> bool + # os.access doesn't work on Windows: http://bugs.python.org/issue2528 + # and we can't use tempfile: http://bugs.python.org/issue22107 + basename = 'accesstest_deleteme_fishfingers_custard_' + alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789' + for _ in range(10): + name = basename + ''.join(random.choice(alphabet) for _ in range(6)) + file = os.path.join(path, name) + try: + fd = os.open(file, os.O_RDWR | os.O_CREAT | os.O_EXCL) + # Python 2 doesn't support FileExistsError and PermissionError. + except OSError as e: + # exception FileExistsError + if e.errno == errno.EEXIST: + continue + # exception PermissionError + if e.errno == errno.EPERM or e.errno == errno.EACCES: + # This could be because there's a directory with the same name. + # But it's highly unlikely there's a directory called that, + # so we'll assume it's because the parent dir is not writable. + # This could as well be because the parent dir is not readable, + # due to non-privileged user access. + return False + raise + else: + os.close(fd) + os.unlink(file) + return True + + # This should never be reached + raise EnvironmentError( + 'Unexpected condition testing for writable directory' + ) + + +def find_files(path, pattern): + # type: (str, str) -> List[str] + """Returns a list of absolute paths of files beneath path, recursively, + with filenames which match the UNIX-style shell glob pattern.""" + result = [] # type: List[str] + for root, _, files in os.walk(path): + matches = fnmatch.filter(files, pattern) + result.extend(os.path.join(root, f) for f in matches) + return result + + +def file_size(path): + # type: (str) -> Union[int, float] + # If it's a symlink, return 0. + if os.path.islink(path): + return 0 + return os.path.getsize(path) + + +def format_file_size(path): + # type: (str) -> str + return format_size(file_size(path)) + + +def directory_size(path): + # type: (str) -> Union[int, float] + size = 0.0 + for root, _dirs, files in os.walk(path): + for filename in files: + file_path = os.path.join(root, filename) + size += file_size(file_path) + return size + + +def format_directory_size(path): + # type: (str) -> str + return format_size(directory_size(path)) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/filetypes.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/filetypes.py new file mode 100644 index 0000000..201c6eb --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/filetypes.py @@ -0,0 +1,26 @@ +"""Filetype information. +""" +from pip._internal.utils.misc import splitext +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Tuple + +WHEEL_EXTENSION = '.whl' +BZ2_EXTENSIONS = ('.tar.bz2', '.tbz') # type: Tuple[str, ...] +XZ_EXTENSIONS = ('.tar.xz', '.txz', '.tlz', + '.tar.lz', '.tar.lzma') # type: Tuple[str, ...] +ZIP_EXTENSIONS = ('.zip', WHEEL_EXTENSION) # type: Tuple[str, ...] +TAR_EXTENSIONS = ('.tar.gz', '.tgz', '.tar') # type: Tuple[str, ...] +ARCHIVE_EXTENSIONS = ( + ZIP_EXTENSIONS + BZ2_EXTENSIONS + TAR_EXTENSIONS + XZ_EXTENSIONS +) + + +def is_archive_file(name): + # type: (str) -> bool + """Return True if `name` is a considered as an archive file.""" + ext = splitext(name)[1].lower() + if ext in ARCHIVE_EXTENSIONS: + return True + return False diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/glibc.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/glibc.py new file mode 100644 index 0000000..3610424 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/glibc.py @@ -0,0 +1,98 @@ +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +from __future__ import absolute_import + +import os +import sys + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Optional, Tuple + + +def glibc_version_string(): + # type: () -> Optional[str] + "Returns glibc version string, or None if not using glibc." + return glibc_version_string_confstr() or glibc_version_string_ctypes() + + +def glibc_version_string_confstr(): + # type: () -> Optional[str] + "Primary implementation of glibc_version_string using os.confstr." + # os.confstr is quite a bit faster than ctypes.DLL. It's also less likely + # to be broken or missing. This strategy is used in the standard library + # platform module: + # https://github.com/python/cpython/blob/fcf1d003bf4f0100c9d0921ff3d70e1127ca1b71/Lib/platform.py#L175-L183 + if sys.platform == "win32": + return None + try: + # os.confstr("CS_GNU_LIBC_VERSION") returns a string like "glibc 2.17": + _, version = os.confstr("CS_GNU_LIBC_VERSION").split() + except (AttributeError, OSError, ValueError): + # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)... + return None + return version + + +def glibc_version_string_ctypes(): + # type: () -> Optional[str] + "Fallback implementation of glibc_version_string using ctypes." + + try: + import ctypes + except ImportError: + return None + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + process_namespace = ctypes.CDLL(None) + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +# platform.libc_ver regularly returns completely nonsensical glibc +# versions. E.g. on my computer, platform says: +# +# ~$ python2.7 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.7') +# ~$ python3.5 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.9') +# +# But the truth is: +# +# ~$ ldd --version +# ldd (Debian GLIBC 2.22-11) 2.22 +# +# This is unfortunate, because it means that the linehaul data on libc +# versions that was generated by pip 8.1.2 and earlier is useless and +# misleading. Solution: instead of using platform, use our code that actually +# works. +def libc_ver(): + # type: () -> Tuple[str, str] + """Try to determine the glibc version + + Returns a tuple of strings (lib, version) which default to empty strings + in case the lookup fails. + """ + glibc_version = glibc_version_string() + if glibc_version is None: + return ("", "") + else: + return ("glibc", glibc_version) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/hashes.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/hashes.py new file mode 100644 index 0000000..4d90f5b --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/hashes.py @@ -0,0 +1,169 @@ +from __future__ import absolute_import + +import hashlib + +from pip._vendor.six import iteritems, iterkeys, itervalues + +from pip._internal.exceptions import HashMismatch, HashMissing, InstallationError +from pip._internal.utils.misc import read_chunks +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import BinaryIO, Dict, Iterator, List, NoReturn + + from pip._vendor.six import PY3 + if PY3: + from hashlib import _Hash + else: + from hashlib import _hash as _Hash + + +# The recommended hash algo of the moment. Change this whenever the state of +# the art changes; it won't hurt backward compatibility. +FAVORITE_HASH = 'sha256' + + +# Names of hashlib algorithms allowed by the --hash option and ``pip hash`` +# Currently, those are the ones at least as collision-resistant as sha256. +STRONG_HASHES = ['sha256', 'sha384', 'sha512'] + + +class Hashes(object): + """A wrapper that builds multiple hashes at once and checks them against + known-good values + + """ + def __init__(self, hashes=None): + # type: (Dict[str, List[str]]) -> None + """ + :param hashes: A dict of algorithm names pointing to lists of allowed + hex digests + """ + allowed = {} + if hashes is not None: + for alg, keys in hashes.items(): + # Make sure values are always sorted (to ease equality checks) + allowed[alg] = sorted(keys) + self._allowed = allowed + + def __and__(self, other): + # type: (Hashes) -> Hashes + if not isinstance(other, Hashes): + return NotImplemented + + # If either of the Hashes object is entirely empty (i.e. no hash + # specified at all), all hashes from the other object are allowed. + if not other: + return self + if not self: + return other + + # Otherwise only hashes that present in both objects are allowed. + new = {} + for alg, values in iteritems(other._allowed): + if alg not in self._allowed: + continue + new[alg] = [v for v in values if v in self._allowed[alg]] + return Hashes(new) + + @property + def digest_count(self): + # type: () -> int + return sum(len(digests) for digests in self._allowed.values()) + + def is_hash_allowed( + self, + hash_name, # type: str + hex_digest, # type: str + ): + # type: (...) -> bool + """Return whether the given hex digest is allowed.""" + return hex_digest in self._allowed.get(hash_name, []) + + def check_against_chunks(self, chunks): + # type: (Iterator[bytes]) -> None + """Check good hashes against ones built from iterable of chunks of + data. + + Raise HashMismatch if none match. + + """ + gots = {} + for hash_name in iterkeys(self._allowed): + try: + gots[hash_name] = hashlib.new(hash_name) + except (ValueError, TypeError): + raise InstallationError( + 'Unknown hash name: {}'.format(hash_name) + ) + + for chunk in chunks: + for hash in itervalues(gots): + hash.update(chunk) + + for hash_name, got in iteritems(gots): + if got.hexdigest() in self._allowed[hash_name]: + return + self._raise(gots) + + def _raise(self, gots): + # type: (Dict[str, _Hash]) -> NoReturn + raise HashMismatch(self._allowed, gots) + + def check_against_file(self, file): + # type: (BinaryIO) -> None + """Check good hashes against a file-like object + + Raise HashMismatch if none match. + + """ + return self.check_against_chunks(read_chunks(file)) + + def check_against_path(self, path): + # type: (str) -> None + with open(path, 'rb') as file: + return self.check_against_file(file) + + def __nonzero__(self): + # type: () -> bool + """Return whether I know any known-good hashes.""" + return bool(self._allowed) + + def __bool__(self): + # type: () -> bool + return self.__nonzero__() + + def __eq__(self, other): + # type: (object) -> bool + if not isinstance(other, Hashes): + return NotImplemented + return self._allowed == other._allowed + + def __hash__(self): + # type: () -> int + return hash( + ",".join(sorted( + ":".join((alg, digest)) + for alg, digest_list in self._allowed.items() + for digest in digest_list + )) + ) + + +class MissingHashes(Hashes): + """A workalike for Hashes used when we're missing a hash for a requirement + + It computes the actual hash of the requirement and raises a HashMissing + exception showing it to the user. + + """ + def __init__(self): + # type: () -> None + """Don't offer the ``hashes`` kwarg.""" + # Pass our favorite hash in to generate a "gotten hash". With the + # empty list, it will never match, so an error will always raise. + super(MissingHashes, self).__init__(hashes={FAVORITE_HASH: []}) + + def _raise(self, gots): + # type: (Dict[str, _Hash]) -> NoReturn + raise HashMissing(gots[FAVORITE_HASH].hexdigest()) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/inject_securetransport.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/inject_securetransport.py new file mode 100644 index 0000000..5b93b1d --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/inject_securetransport.py @@ -0,0 +1,36 @@ +"""A helper module that injects SecureTransport, on import. + +The import should be done as early as possible, to ensure all requests and +sessions (or whatever) are created after injecting SecureTransport. + +Note that we only do the injection on macOS, when the linked OpenSSL is too +old to handle TLSv1.2. +""" + +import sys + + +def inject_securetransport(): + # type: () -> None + # Only relevant on macOS + if sys.platform != "darwin": + return + + try: + import ssl + except ImportError: + return + + # Checks for OpenSSL 1.0.1 + if ssl.OPENSSL_VERSION_NUMBER >= 0x1000100f: + return + + try: + from pip._vendor.urllib3.contrib import securetransport + except (ImportError, OSError): + return + + securetransport.inject_into_urllib3() + + +inject_securetransport() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/logging.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/logging.py new file mode 100644 index 0000000..9a017cf --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/logging.py @@ -0,0 +1,399 @@ +# The following comment should be removed at some point in the future. +# mypy: disallow-untyped-defs=False + +from __future__ import absolute_import + +import contextlib +import errno +import logging +import logging.handlers +import os +import sys +from logging import Filter, getLogger + +from pip._vendor.six import PY2 + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.deprecation import DEPRECATION_MSG_PREFIX +from pip._internal.utils.misc import ensure_dir + +try: + import threading +except ImportError: + import dummy_threading as threading # type: ignore + + +try: + # Use "import as" and set colorama in the else clause to avoid mypy + # errors and get the following correct revealed type for colorama: + # `Union[_importlib_modulespec.ModuleType, None]` + # Otherwise, we get an error like the following in the except block: + # > Incompatible types in assignment (expression has type "None", + # variable has type Module) + # TODO: eliminate the need to use "import as" once mypy addresses some + # of its issues with conditional imports. Here is an umbrella issue: + # https://github.com/python/mypy/issues/1297 + from pip._vendor import colorama as _colorama +# Lots of different errors can come from this, including SystemError and +# ImportError. +except Exception: + colorama = None +else: + # Import Fore explicitly rather than accessing below as colorama.Fore + # to avoid the following error running mypy: + # > Module has no attribute "Fore" + # TODO: eliminate the need to import Fore once mypy addresses some of its + # issues with conditional imports. This particular case could be an + # instance of the following issue (but also see the umbrella issue above): + # https://github.com/python/mypy/issues/3500 + from pip._vendor.colorama import Fore + + colorama = _colorama + + +_log_state = threading.local() +subprocess_logger = getLogger('pip.subprocessor') + + +class BrokenStdoutLoggingError(Exception): + """ + Raised if BrokenPipeError occurs for the stdout stream while logging. + """ + pass + + +# BrokenPipeError does not exist in Python 2 and, in addition, manifests +# differently in Windows and non-Windows. +if WINDOWS: + # In Windows, a broken pipe can show up as EINVAL rather than EPIPE: + # https://bugs.python.org/issue19612 + # https://bugs.python.org/issue30418 + if PY2: + def _is_broken_pipe_error(exc_class, exc): + """See the docstring for non-Windows Python 3 below.""" + return (exc_class is IOError and + exc.errno in (errno.EINVAL, errno.EPIPE)) + else: + # In Windows, a broken pipe IOError became OSError in Python 3. + def _is_broken_pipe_error(exc_class, exc): + """See the docstring for non-Windows Python 3 below.""" + return ((exc_class is BrokenPipeError) or # noqa: F821 + (exc_class is OSError and + exc.errno in (errno.EINVAL, errno.EPIPE))) +elif PY2: + def _is_broken_pipe_error(exc_class, exc): + """See the docstring for non-Windows Python 3 below.""" + return (exc_class is IOError and exc.errno == errno.EPIPE) +else: + # Then we are in the non-Windows Python 3 case. + def _is_broken_pipe_error(exc_class, exc): + """ + Return whether an exception is a broken pipe error. + + Args: + exc_class: an exception class. + exc: an exception instance. + """ + return (exc_class is BrokenPipeError) # noqa: F821 + + +@contextlib.contextmanager +def indent_log(num=2): + """ + A context manager which will cause the log output to be indented for any + log messages emitted inside it. + """ + # For thread-safety + _log_state.indentation = get_indentation() + _log_state.indentation += num + try: + yield + finally: + _log_state.indentation -= num + + +def get_indentation(): + return getattr(_log_state, 'indentation', 0) + + +class IndentingFormatter(logging.Formatter): + + def __init__(self, *args, **kwargs): + """ + A logging.Formatter that obeys the indent_log() context manager. + + :param add_timestamp: A bool indicating output lines should be prefixed + with their record's timestamp. + """ + self.add_timestamp = kwargs.pop("add_timestamp", False) + super(IndentingFormatter, self).__init__(*args, **kwargs) + + def get_message_start(self, formatted, levelno): + """ + Return the start of the formatted log message (not counting the + prefix to add to each line). + """ + if levelno < logging.WARNING: + return '' + if formatted.startswith(DEPRECATION_MSG_PREFIX): + # Then the message already has a prefix. We don't want it to + # look like "WARNING: DEPRECATION: ...." + return '' + if levelno < logging.ERROR: + return 'WARNING: ' + + return 'ERROR: ' + + def format(self, record): + """ + Calls the standard formatter, but will indent all of the log message + lines by our current indentation level. + """ + formatted = super(IndentingFormatter, self).format(record) + message_start = self.get_message_start(formatted, record.levelno) + formatted = message_start + formatted + + prefix = '' + if self.add_timestamp: + # TODO: Use Formatter.default_time_format after dropping PY2. + t = self.formatTime(record, "%Y-%m-%dT%H:%M:%S") + prefix = '{t},{record.msecs:03.0f} '.format(**locals()) + prefix += " " * get_indentation() + formatted = "".join([ + prefix + line + for line in formatted.splitlines(True) + ]) + return formatted + + +def _color_wrap(*colors): + def wrapped(inp): + return "".join(list(colors) + [inp, colorama.Style.RESET_ALL]) + return wrapped + + +class ColorizedStreamHandler(logging.StreamHandler): + + # Don't build up a list of colors if we don't have colorama + if colorama: + COLORS = [ + # This needs to be in order from highest logging level to lowest. + (logging.ERROR, _color_wrap(Fore.RED)), + (logging.WARNING, _color_wrap(Fore.YELLOW)), + ] + else: + COLORS = [] + + def __init__(self, stream=None, no_color=None): + logging.StreamHandler.__init__(self, stream) + self._no_color = no_color + + if WINDOWS and colorama: + self.stream = colorama.AnsiToWin32(self.stream) + + def _using_stdout(self): + """ + Return whether the handler is using sys.stdout. + """ + if WINDOWS and colorama: + # Then self.stream is an AnsiToWin32 object. + return self.stream.wrapped is sys.stdout + + return self.stream is sys.stdout + + def should_color(self): + # Don't colorize things if we do not have colorama or if told not to + if not colorama or self._no_color: + return False + + real_stream = ( + self.stream if not isinstance(self.stream, colorama.AnsiToWin32) + else self.stream.wrapped + ) + + # If the stream is a tty we should color it + if hasattr(real_stream, "isatty") and real_stream.isatty(): + return True + + # If we have an ANSI term we should color it + if os.environ.get("TERM") == "ANSI": + return True + + # If anything else we should not color it + return False + + def format(self, record): + msg = logging.StreamHandler.format(self, record) + + if self.should_color(): + for level, color in self.COLORS: + if record.levelno >= level: + msg = color(msg) + break + + return msg + + # The logging module says handleError() can be customized. + def handleError(self, record): + exc_class, exc = sys.exc_info()[:2] + # If a broken pipe occurred while calling write() or flush() on the + # stdout stream in logging's Handler.emit(), then raise our special + # exception so we can handle it in main() instead of logging the + # broken pipe error and continuing. + if (exc_class and self._using_stdout() and + _is_broken_pipe_error(exc_class, exc)): + raise BrokenStdoutLoggingError() + + return super(ColorizedStreamHandler, self).handleError(record) + + +class BetterRotatingFileHandler(logging.handlers.RotatingFileHandler): + + def _open(self): + ensure_dir(os.path.dirname(self.baseFilename)) + return logging.handlers.RotatingFileHandler._open(self) + + +class MaxLevelFilter(Filter): + + def __init__(self, level): + self.level = level + + def filter(self, record): + return record.levelno < self.level + + +class ExcludeLoggerFilter(Filter): + + """ + A logging Filter that excludes records from a logger (or its children). + """ + + def filter(self, record): + # The base Filter class allows only records from a logger (or its + # children). + return not super(ExcludeLoggerFilter, self).filter(record) + + +def setup_logging(verbosity, no_color, user_log_file): + """Configures and sets up all of the logging + + Returns the requested logging level, as its integer value. + """ + + # Determine the level to be logging at. + if verbosity >= 1: + level = "DEBUG" + elif verbosity == -1: + level = "WARNING" + elif verbosity == -2: + level = "ERROR" + elif verbosity <= -3: + level = "CRITICAL" + else: + level = "INFO" + + level_number = getattr(logging, level) + + # The "root" logger should match the "console" level *unless* we also need + # to log to a user log file. + include_user_log = user_log_file is not None + if include_user_log: + additional_log_file = user_log_file + root_level = "DEBUG" + else: + additional_log_file = "/dev/null" + root_level = level + + # Disable any logging besides WARNING unless we have DEBUG level logging + # enabled for vendored libraries. + vendored_log_level = "WARNING" if level in ["INFO", "ERROR"] else "DEBUG" + + # Shorthands for clarity + log_streams = { + "stdout": "ext://sys.stdout", + "stderr": "ext://sys.stderr", + } + handler_classes = { + "stream": "pip._internal.utils.logging.ColorizedStreamHandler", + "file": "pip._internal.utils.logging.BetterRotatingFileHandler", + } + handlers = ["console", "console_errors", "console_subprocess"] + ( + ["user_log"] if include_user_log else [] + ) + + logging.config.dictConfig({ + "version": 1, + "disable_existing_loggers": False, + "filters": { + "exclude_warnings": { + "()": "pip._internal.utils.logging.MaxLevelFilter", + "level": logging.WARNING, + }, + "restrict_to_subprocess": { + "()": "logging.Filter", + "name": subprocess_logger.name, + }, + "exclude_subprocess": { + "()": "pip._internal.utils.logging.ExcludeLoggerFilter", + "name": subprocess_logger.name, + }, + }, + "formatters": { + "indent": { + "()": IndentingFormatter, + "format": "%(message)s", + }, + "indent_with_timestamp": { + "()": IndentingFormatter, + "format": "%(message)s", + "add_timestamp": True, + }, + }, + "handlers": { + "console": { + "level": level, + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stdout"], + "filters": ["exclude_subprocess", "exclude_warnings"], + "formatter": "indent", + }, + "console_errors": { + "level": "WARNING", + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stderr"], + "filters": ["exclude_subprocess"], + "formatter": "indent", + }, + # A handler responsible for logging to the console messages + # from the "subprocessor" logger. + "console_subprocess": { + "level": level, + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stderr"], + "filters": ["restrict_to_subprocess"], + "formatter": "indent", + }, + "user_log": { + "level": "DEBUG", + "class": handler_classes["file"], + "filename": additional_log_file, + "delay": True, + "formatter": "indent_with_timestamp", + }, + }, + "root": { + "level": root_level, + "handlers": handlers, + }, + "loggers": { + "pip._vendor": { + "level": vendored_log_level + } + }, + }) + + return level_number diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/misc.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/misc.py new file mode 100644 index 0000000..b8795cc --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/misc.py @@ -0,0 +1,977 @@ +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False +# mypy: disallow-untyped-defs=False + +from __future__ import absolute_import + +import contextlib +import errno +import getpass +import hashlib +import io +import logging +import os +import posixpath +import shutil +import stat +import sys +from collections import deque +from itertools import tee + +from pip._vendor import pkg_resources +from pip._vendor.packaging.utils import canonicalize_name + +# NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is +# why we ignore the type on this import. +from pip._vendor.retrying import retry # type: ignore +from pip._vendor.six import PY2, text_type +from pip._vendor.six.moves import filter, filterfalse, input, map, zip_longest +from pip._vendor.six.moves.urllib import parse as urllib_parse +from pip._vendor.six.moves.urllib.parse import unquote as urllib_unquote + +from pip import __version__ +from pip._internal.exceptions import CommandError +from pip._internal.locations import get_major_minor_version, site_packages, user_site +from pip._internal.utils.compat import WINDOWS, expanduser, stdlib_pkgs, str_to_display +from pip._internal.utils.typing import MYPY_CHECK_RUNNING, cast +from pip._internal.utils.virtualenv import ( + running_under_virtualenv, + virtualenv_no_global, +) + +if PY2: + from io import BytesIO as StringIO +else: + from io import StringIO + +if MYPY_CHECK_RUNNING: + from typing import ( + Any, + AnyStr, + Callable, + Container, + Iterable, + Iterator, + List, + Optional, + Text, + Tuple, + TypeVar, + Union, + ) + + from pip._vendor.pkg_resources import Distribution + + VersionInfo = Tuple[int, int, int] + T = TypeVar("T") + + +__all__ = ['rmtree', 'display_path', 'backup_dir', + 'ask', 'splitext', + 'format_size', 'is_installable_dir', + 'normalize_path', + 'renames', 'get_prog', + 'captured_stdout', 'ensure_dir', + 'get_installed_version', 'remove_auth_from_url'] + + +logger = logging.getLogger(__name__) + + +def get_pip_version(): + # type: () -> str + pip_pkg_dir = os.path.join(os.path.dirname(__file__), "..", "..") + pip_pkg_dir = os.path.abspath(pip_pkg_dir) + + return ( + 'pip {} from {} (python {})'.format( + __version__, pip_pkg_dir, get_major_minor_version(), + ) + ) + + +def normalize_version_info(py_version_info): + # type: (Tuple[int, ...]) -> Tuple[int, int, int] + """ + Convert a tuple of ints representing a Python version to one of length + three. + + :param py_version_info: a tuple of ints representing a Python version, + or None to specify no version. The tuple can have any length. + + :return: a tuple of length three if `py_version_info` is non-None. + Otherwise, return `py_version_info` unchanged (i.e. None). + """ + if len(py_version_info) < 3: + py_version_info += (3 - len(py_version_info)) * (0,) + elif len(py_version_info) > 3: + py_version_info = py_version_info[:3] + + return cast('VersionInfo', py_version_info) + + +def ensure_dir(path): + # type: (AnyStr) -> None + """os.path.makedirs without EEXIST.""" + try: + os.makedirs(path) + except OSError as e: + # Windows can raise spurious ENOTEMPTY errors. See #6426. + if e.errno != errno.EEXIST and e.errno != errno.ENOTEMPTY: + raise + + +def get_prog(): + # type: () -> str + try: + prog = os.path.basename(sys.argv[0]) + if prog in ('__main__.py', '-c'): + return "{} -m pip".format(sys.executable) + else: + return prog + except (AttributeError, TypeError, IndexError): + pass + return 'pip' + + +# Retry every half second for up to 3 seconds +@retry(stop_max_delay=3000, wait_fixed=500) +def rmtree(dir, ignore_errors=False): + # type: (AnyStr, bool) -> None + shutil.rmtree(dir, ignore_errors=ignore_errors, + onerror=rmtree_errorhandler) + + +def rmtree_errorhandler(func, path, exc_info): + """On Windows, the files in .svn are read-only, so when rmtree() tries to + remove them, an exception is thrown. We catch that here, remove the + read-only attribute, and hopefully continue without problems.""" + try: + has_attr_readonly = not (os.stat(path).st_mode & stat.S_IWRITE) + except (IOError, OSError): + # it's equivalent to os.path.exists + return + + if has_attr_readonly: + # convert to read/write + os.chmod(path, stat.S_IWRITE) + # use the original function to repeat the operation + func(path) + return + else: + raise + + +def path_to_display(path): + # type: (Optional[Union[str, Text]]) -> Optional[Text] + """ + Convert a bytes (or text) path to text (unicode in Python 2) for display + and logging purposes. + + This function should never error out. Also, this function is mainly needed + for Python 2 since in Python 3 str paths are already text. + """ + if path is None: + return None + if isinstance(path, text_type): + return path + # Otherwise, path is a bytes object (str in Python 2). + try: + display_path = path.decode(sys.getfilesystemencoding(), 'strict') + except UnicodeDecodeError: + # Include the full bytes to make troubleshooting easier, even though + # it may not be very human readable. + if PY2: + # Convert the bytes to a readable str representation using + # repr(), and then convert the str to unicode. + # Also, we add the prefix "b" to the repr() return value both + # to make the Python 2 output look like the Python 3 output, and + # to signal to the user that this is a bytes representation. + display_path = str_to_display('b{!r}'.format(path)) + else: + # Silence the "F821 undefined name 'ascii'" flake8 error since + # in Python 3 ascii() is a built-in. + display_path = ascii(path) # noqa: F821 + + return display_path + + +def display_path(path): + # type: (Union[str, Text]) -> str + """Gives the display value for a given path, making it relative to cwd + if possible.""" + path = os.path.normcase(os.path.abspath(path)) + if sys.version_info[0] == 2: + path = path.decode(sys.getfilesystemencoding(), 'replace') + path = path.encode(sys.getdefaultencoding(), 'replace') + if path.startswith(os.getcwd() + os.path.sep): + path = '.' + path[len(os.getcwd()):] + return path + + +def backup_dir(dir, ext='.bak'): + # type: (str, str) -> str + """Figure out the name of a directory to back up the given dir to + (adding .bak, .bak2, etc)""" + n = 1 + extension = ext + while os.path.exists(dir + extension): + n += 1 + extension = ext + str(n) + return dir + extension + + +def ask_path_exists(message, options): + # type: (str, Iterable[str]) -> str + for action in os.environ.get('PIP_EXISTS_ACTION', '').split(): + if action in options: + return action + return ask(message, options) + + +def _check_no_input(message): + # type: (str) -> None + """Raise an error if no input is allowed.""" + if os.environ.get('PIP_NO_INPUT'): + raise Exception( + 'No input was expected ($PIP_NO_INPUT set); question: {}'.format( + message) + ) + + +def ask(message, options): + # type: (str, Iterable[str]) -> str + """Ask the message interactively, with the given possible responses""" + while 1: + _check_no_input(message) + response = input(message) + response = response.strip().lower() + if response not in options: + print( + 'Your response ({!r}) was not one of the expected responses: ' + '{}'.format(response, ', '.join(options)) + ) + else: + return response + + +def ask_input(message): + # type: (str) -> str + """Ask for input interactively.""" + _check_no_input(message) + return input(message) + + +def ask_password(message): + # type: (str) -> str + """Ask for a password interactively.""" + _check_no_input(message) + return getpass.getpass(message) + + +def format_size(bytes): + # type: (float) -> str + if bytes > 1000 * 1000: + return '{:.1f} MB'.format(bytes / 1000.0 / 1000) + elif bytes > 10 * 1000: + return '{} kB'.format(int(bytes / 1000)) + elif bytes > 1000: + return '{:.1f} kB'.format(bytes / 1000.0) + else: + return '{} bytes'.format(int(bytes)) + + +def tabulate(rows): + # type: (Iterable[Iterable[Any]]) -> Tuple[List[str], List[int]] + """Return a list of formatted rows and a list of column sizes. + + For example:: + + >>> tabulate([['foobar', 2000], [0xdeadbeef]]) + (['foobar 2000', '3735928559'], [10, 4]) + """ + rows = [tuple(map(str, row)) for row in rows] + sizes = [max(map(len, col)) for col in zip_longest(*rows, fillvalue='')] + table = [" ".join(map(str.ljust, row, sizes)).rstrip() for row in rows] + return table, sizes + + +def is_installable_dir(path): + # type: (str) -> bool + """Is path is a directory containing setup.py or pyproject.toml? + """ + if not os.path.isdir(path): + return False + setup_py = os.path.join(path, 'setup.py') + if os.path.isfile(setup_py): + return True + pyproject_toml = os.path.join(path, 'pyproject.toml') + if os.path.isfile(pyproject_toml): + return True + return False + + +def read_chunks(file, size=io.DEFAULT_BUFFER_SIZE): + """Yield pieces of data from a file-like object until EOF.""" + while True: + chunk = file.read(size) + if not chunk: + break + yield chunk + + +def normalize_path(path, resolve_symlinks=True): + # type: (str, bool) -> str + """ + Convert a path to its canonical, case-normalized, absolute version. + + """ + path = expanduser(path) + if resolve_symlinks: + path = os.path.realpath(path) + else: + path = os.path.abspath(path) + return os.path.normcase(path) + + +def splitext(path): + # type: (str) -> Tuple[str, str] + """Like os.path.splitext, but take off .tar too""" + base, ext = posixpath.splitext(path) + if base.lower().endswith('.tar'): + ext = base[-4:] + ext + base = base[:-4] + return base, ext + + +def renames(old, new): + # type: (str, str) -> None + """Like os.renames(), but handles renaming across devices.""" + # Implementation borrowed from os.renames(). + head, tail = os.path.split(new) + if head and tail and not os.path.exists(head): + os.makedirs(head) + + shutil.move(old, new) + + head, tail = os.path.split(old) + if head and tail: + try: + os.removedirs(head) + except OSError: + pass + + +def is_local(path): + # type: (str) -> bool + """ + Return True if this is a path pip is allowed to modify. + + If we're in a virtualenv, sys.prefix points to the virtualenv's + prefix; only sys.prefix is considered local. + + If we're not in a virtualenv, in general we can modify anything. + However, if the OS vendor has configured distutils to install + somewhere other than sys.prefix (which could be a subdirectory of + sys.prefix, e.g. /usr/local), we consider sys.prefix itself nonlocal + and the domain of the OS vendor. (In other words, everything _other + than_ sys.prefix is considered local.) + + Caution: this function assumes the head of path has been normalized + with normalize_path. + """ + + path = normalize_path(path) + # Hard-coded becouse PyPy uses a different sys.prefix on Debian + prefix = '/usr' + + if running_under_virtualenv(): + return path.startswith(normalize_path(sys.prefix)) + else: + from pip._internal.locations import distutils_scheme + if path.startswith(prefix): + for local_path in distutils_scheme("").values(): + if path.startswith(normalize_path(local_path)): + return True + return False + else: + return True + + +def dist_is_local(dist): + # type: (Distribution) -> bool + """ + Return True if given Distribution object is installed somewhere pip + is allowed to modify. + + """ + return is_local(dist_location(dist)) + + +def dist_in_usersite(dist): + # type: (Distribution) -> bool + """ + Return True if given Distribution is installed in user site. + """ + return dist_location(dist).startswith(normalize_path(user_site)) + + +def dist_in_site_packages(dist): + # type: (Distribution) -> bool + """ + Return True if given Distribution is installed in + sysconfig.get_python_lib(). + """ + return dist_location(dist).startswith(normalize_path(site_packages)) + + +def dist_is_editable(dist): + # type: (Distribution) -> bool + """ + Return True if given Distribution is an editable install. + """ + return bool(egg_link_path(dist)) + + +def get_installed_distributions( + local_only=True, # type: bool + skip=stdlib_pkgs, # type: Container[str] + include_editables=True, # type: bool + editables_only=False, # type: bool + user_only=False, # type: bool + paths=None # type: Optional[List[str]] +): + # type: (...) -> List[Distribution] + """ + Return a list of installed Distribution objects. + + If ``local_only`` is True (default), only return installations + local to the current virtualenv, if in a virtualenv. + + ``skip`` argument is an iterable of lower-case project names to + ignore; defaults to stdlib_pkgs + + If ``include_editables`` is False, don't report editables. + + If ``editables_only`` is True , only report editables. + + If ``user_only`` is True , only report installations in the user + site directory. + + If ``paths`` is set, only report the distributions present at the + specified list of locations. + """ + if paths: + working_set = pkg_resources.WorkingSet(paths) + else: + working_set = pkg_resources.working_set + + if local_only: + local_test = dist_is_local + else: + def local_test(d): + return True + + if include_editables: + def editable_test(d): + return True + else: + def editable_test(d): + return not dist_is_editable(d) + + if editables_only: + def editables_only_test(d): + return dist_is_editable(d) + else: + def editables_only_test(d): + return True + + if user_only: + user_test = dist_in_usersite + else: + def user_test(d): + return True + + return [d for d in working_set + if local_test(d) and + d.key not in skip and + editable_test(d) and + editables_only_test(d) and + user_test(d) + ] + + +def _search_distribution(req_name): + # type: (str) -> Optional[Distribution] + """Find a distribution matching the ``req_name`` in the environment. + + This searches from *all* distributions available in the environment, to + match the behavior of ``pkg_resources.get_distribution()``. + """ + # Canonicalize the name before searching in the list of + # installed distributions and also while creating the package + # dictionary to get the Distribution object + req_name = canonicalize_name(req_name) + packages = get_installed_distributions( + local_only=False, + skip=(), + include_editables=True, + editables_only=False, + user_only=False, + paths=None, + ) + pkg_dict = {canonicalize_name(p.key): p for p in packages} + return pkg_dict.get(req_name) + + +def get_distribution(req_name): + # type: (str) -> Optional[Distribution] + """Given a requirement name, return the installed Distribution object. + + This searches from *all* distributions available in the environment, to + match the behavior of ``pkg_resources.get_distribution()``. + """ + + # Search the distribution by looking through the working set + dist = _search_distribution(req_name) + + # If distribution could not be found, call working_set.require + # to update the working set, and try to find the distribution + # again. + # This might happen for e.g. when you install a package + # twice, once using setup.py develop and again using setup.py install. + # Now when run pip uninstall twice, the package gets removed + # from the working set in the first uninstall, so we have to populate + # the working set again so that pip knows about it and the packages + # gets picked up and is successfully uninstalled the second time too. + if not dist: + try: + pkg_resources.working_set.require(req_name) + except pkg_resources.DistributionNotFound: + return None + return _search_distribution(req_name) + + +def egg_link_path(dist): + # type: (Distribution) -> Optional[str] + """ + Return the path for the .egg-link file if it exists, otherwise, None. + + There's 3 scenarios: + 1) not in a virtualenv + try to find in site.USER_SITE, then site_packages + 2) in a no-global virtualenv + try to find in site_packages + 3) in a yes-global virtualenv + try to find in site_packages, then site.USER_SITE + (don't look in global location) + + For #1 and #3, there could be odd cases, where there's an egg-link in 2 + locations. + + This method will just return the first one found. + """ + sites = [] + if running_under_virtualenv(): + sites.append(site_packages) + if not virtualenv_no_global() and user_site: + sites.append(user_site) + else: + if user_site: + sites.append(user_site) + sites.append(site_packages) + + for site in sites: + egglink = os.path.join(site, dist.project_name) + '.egg-link' + if os.path.isfile(egglink): + return egglink + return None + + +def dist_location(dist): + # type: (Distribution) -> str + """ + Get the site-packages location of this distribution. Generally + this is dist.location, except in the case of develop-installed + packages, where dist.location is the source code location, and we + want to know where the egg-link file is. + + The returned location is normalized (in particular, with symlinks removed). + """ + egg_link = egg_link_path(dist) + if egg_link: + return normalize_path(egg_link) + return normalize_path(dist.location) + + +def write_output(msg, *args): + # type: (Any, Any) -> None + logger.info(msg, *args) + + +class FakeFile(object): + """Wrap a list of lines in an object with readline() to make + ConfigParser happy.""" + def __init__(self, lines): + self._gen = iter(lines) + + def readline(self): + try: + return next(self._gen) + except StopIteration: + return '' + + def __iter__(self): + return self._gen + + +class StreamWrapper(StringIO): + + @classmethod + def from_stream(cls, orig_stream): + cls.orig_stream = orig_stream + return cls() + + # compileall.compile_dir() needs stdout.encoding to print to stdout + @property + def encoding(self): + return self.orig_stream.encoding + + +@contextlib.contextmanager +def captured_output(stream_name): + """Return a context manager used by captured_stdout/stdin/stderr + that temporarily replaces the sys stream *stream_name* with a StringIO. + + Taken from Lib/support/__init__.py in the CPython repo. + """ + orig_stdout = getattr(sys, stream_name) + setattr(sys, stream_name, StreamWrapper.from_stream(orig_stdout)) + try: + yield getattr(sys, stream_name) + finally: + setattr(sys, stream_name, orig_stdout) + + +def captured_stdout(): + """Capture the output of sys.stdout: + + with captured_stdout() as stdout: + print('hello') + self.assertEqual(stdout.getvalue(), 'hello\n') + + Taken from Lib/support/__init__.py in the CPython repo. + """ + return captured_output('stdout') + + +def captured_stderr(): + """ + See captured_stdout(). + """ + return captured_output('stderr') + + +def get_installed_version(dist_name, working_set=None): + """Get the installed version of dist_name avoiding pkg_resources cache""" + # Create a requirement that we'll look for inside of setuptools. + req = pkg_resources.Requirement.parse(dist_name) + + if working_set is None: + # We want to avoid having this cached, so we need to construct a new + # working set each time. + working_set = pkg_resources.WorkingSet() + + # Get the installed distribution from our working set + dist = working_set.find(req) + + # Check to see if we got an installed distribution or not, if we did + # we want to return it's version. + return dist.version if dist else None + + +def consume(iterator): + """Consume an iterable at C speed.""" + deque(iterator, maxlen=0) + + +# Simulates an enum +def enum(*sequential, **named): + enums = dict(zip(sequential, range(len(sequential))), **named) + reverse = {value: key for key, value in enums.items()} + enums['reverse_mapping'] = reverse + return type('Enum', (), enums) + + +def build_netloc(host, port): + # type: (str, Optional[int]) -> str + """ + Build a netloc from a host-port pair + """ + if port is None: + return host + if ':' in host: + # Only wrap host with square brackets when it is IPv6 + host = '[{}]'.format(host) + return '{}:{}'.format(host, port) + + +def build_url_from_netloc(netloc, scheme='https'): + # type: (str, str) -> str + """ + Build a full URL from a netloc. + """ + if netloc.count(':') >= 2 and '@' not in netloc and '[' not in netloc: + # It must be a bare IPv6 address, so wrap it with brackets. + netloc = '[{}]'.format(netloc) + return '{}://{}'.format(scheme, netloc) + + +def parse_netloc(netloc): + # type: (str) -> Tuple[str, Optional[int]] + """ + Return the host-port pair from a netloc. + """ + url = build_url_from_netloc(netloc) + parsed = urllib_parse.urlparse(url) + return parsed.hostname, parsed.port + + +def split_auth_from_netloc(netloc): + """ + Parse out and remove the auth information from a netloc. + + Returns: (netloc, (username, password)). + """ + if '@' not in netloc: + return netloc, (None, None) + + # Split from the right because that's how urllib.parse.urlsplit() + # behaves if more than one @ is present (which can be checked using + # the password attribute of urlsplit()'s return value). + auth, netloc = netloc.rsplit('@', 1) + if ':' in auth: + # Split from the left because that's how urllib.parse.urlsplit() + # behaves if more than one : is present (which again can be checked + # using the password attribute of the return value) + user_pass = auth.split(':', 1) + else: + user_pass = auth, None + + user_pass = tuple( + None if x is None else urllib_unquote(x) for x in user_pass + ) + + return netloc, user_pass + + +def redact_netloc(netloc): + # type: (str) -> str + """ + Replace the sensitive data in a netloc with "****", if it exists. + + For example: + - "user:pass@example.com" returns "user:****@example.com" + - "accesstoken@example.com" returns "****@example.com" + """ + netloc, (user, password) = split_auth_from_netloc(netloc) + if user is None: + return netloc + if password is None: + user = '****' + password = '' + else: + user = urllib_parse.quote(user) + password = ':****' + return '{user}{password}@{netloc}'.format(user=user, + password=password, + netloc=netloc) + + +def _transform_url(url, transform_netloc): + """Transform and replace netloc in a url. + + transform_netloc is a function taking the netloc and returning a + tuple. The first element of this tuple is the new netloc. The + entire tuple is returned. + + Returns a tuple containing the transformed url as item 0 and the + original tuple returned by transform_netloc as item 1. + """ + purl = urllib_parse.urlsplit(url) + netloc_tuple = transform_netloc(purl.netloc) + # stripped url + url_pieces = ( + purl.scheme, netloc_tuple[0], purl.path, purl.query, purl.fragment + ) + surl = urllib_parse.urlunsplit(url_pieces) + return surl, netloc_tuple + + +def _get_netloc(netloc): + return split_auth_from_netloc(netloc) + + +def _redact_netloc(netloc): + return (redact_netloc(netloc),) + + +def split_auth_netloc_from_url(url): + # type: (str) -> Tuple[str, str, Tuple[str, str]] + """ + Parse a url into separate netloc, auth, and url with no auth. + + Returns: (url_without_auth, netloc, (username, password)) + """ + url_without_auth, (netloc, auth) = _transform_url(url, _get_netloc) + return url_without_auth, netloc, auth + + +def remove_auth_from_url(url): + # type: (str) -> str + """Return a copy of url with 'username:password@' removed.""" + # username/pass params are passed to subversion through flags + # and are not recognized in the url. + return _transform_url(url, _get_netloc)[0] + + +def redact_auth_from_url(url): + # type: (str) -> str + """Replace the password in a given url with ****.""" + return _transform_url(url, _redact_netloc)[0] + + +class HiddenText(object): + def __init__( + self, + secret, # type: str + redacted, # type: str + ): + # type: (...) -> None + self.secret = secret + self.redacted = redacted + + def __repr__(self): + # type: (...) -> str + return ''.format(str(self)) + + def __str__(self): + # type: (...) -> str + return self.redacted + + # This is useful for testing. + def __eq__(self, other): + # type: (Any) -> bool + if type(self) != type(other): + return False + + # The string being used for redaction doesn't also have to match, + # just the raw, original string. + return (self.secret == other.secret) + + # We need to provide an explicit __ne__ implementation for Python 2. + # TODO: remove this when we drop PY2 support. + def __ne__(self, other): + # type: (Any) -> bool + return not self == other + + +def hide_value(value): + # type: (str) -> HiddenText + return HiddenText(value, redacted='****') + + +def hide_url(url): + # type: (str) -> HiddenText + redacted = redact_auth_from_url(url) + return HiddenText(url, redacted=redacted) + + +def protect_pip_from_modification_on_windows(modifying_pip): + # type: (bool) -> None + """Protection of pip.exe from modification on Windows + + On Windows, any operation modifying pip should be run as: + python -m pip ... + """ + pip_names = [ + "pip.exe", + "pip{}.exe".format(sys.version_info[0]), + "pip{}.{}.exe".format(*sys.version_info[:2]) + ] + + # See https://github.com/pypa/pip/issues/1299 for more discussion + should_show_use_python_msg = ( + modifying_pip and + WINDOWS and + os.path.basename(sys.argv[0]) in pip_names + ) + + if should_show_use_python_msg: + new_command = [ + sys.executable, "-m", "pip" + ] + sys.argv[1:] + raise CommandError( + 'To modify pip, please run the following command:\n{}' + .format(" ".join(new_command)) + ) + + +def is_console_interactive(): + # type: () -> bool + """Is this console interactive? + """ + return sys.stdin is not None and sys.stdin.isatty() + + +def hash_file(path, blocksize=1 << 20): + # type: (Text, int) -> Tuple[Any, int] + """Return (hash, length) for path using hashlib.sha256() + """ + + h = hashlib.sha256() + length = 0 + with open(path, 'rb') as f: + for block in read_chunks(f, size=blocksize): + length += len(block) + h.update(block) + return h, length + + +def is_wheel_installed(): + """ + Return whether the wheel package is installed. + """ + try: + import wheel # noqa: F401 + except ImportError: + return False + + return True + + +def pairwise(iterable): + # type: (Iterable[Any]) -> Iterator[Tuple[Any, Any]] + """ + Return paired elements. + + For example: + s -> (s0, s1), (s2, s3), (s4, s5), ... + """ + iterable = iter(iterable) + return zip_longest(iterable, iterable) + + +def partition( + pred, # type: Callable[[T], bool] + iterable, # type: Iterable[T] +): + # type: (...) -> Tuple[Iterable[T], Iterable[T]] + """ + Use a predicate to partition entries into false entries and true entries, + like + + partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9 + """ + t1, t2 = tee(iterable) + return filterfalse(pred, t1), filter(pred, t2) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/models.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/models.py new file mode 100644 index 0000000..d1c2f22 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/models.py @@ -0,0 +1,44 @@ +"""Utilities for defining models +""" +# The following comment should be removed at some point in the future. +# mypy: disallow-untyped-defs=False + +import operator + + +class KeyBasedCompareMixin(object): + """Provides comparison capabilities that is based on a key + """ + + __slots__ = ['_compare_key', '_defining_class'] + + def __init__(self, key, defining_class): + self._compare_key = key + self._defining_class = defining_class + + def __hash__(self): + return hash(self._compare_key) + + def __lt__(self, other): + return self._compare(other, operator.__lt__) + + def __le__(self, other): + return self._compare(other, operator.__le__) + + def __gt__(self, other): + return self._compare(other, operator.__gt__) + + def __ge__(self, other): + return self._compare(other, operator.__ge__) + + def __eq__(self, other): + return self._compare(other, operator.__eq__) + + def __ne__(self, other): + return self._compare(other, operator.__ne__) + + def _compare(self, other, method): + if not isinstance(other, self._defining_class): + return NotImplemented + + return method(self._compare_key, other._compare_key) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/packaging.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/packaging.py new file mode 100644 index 0000000..27fd204 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/packaging.py @@ -0,0 +1,95 @@ +from __future__ import absolute_import + +import logging +from email.parser import FeedParser + +from pip._vendor import pkg_resources +from pip._vendor.packaging import specifiers, version + +from pip._internal.exceptions import NoneMetadataError +from pip._internal.utils.misc import display_path +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from email.message import Message + from typing import Optional, Tuple + + from pip._vendor.pkg_resources import Distribution + + +logger = logging.getLogger(__name__) + + +def check_requires_python(requires_python, version_info): + # type: (Optional[str], Tuple[int, ...]) -> bool + """ + Check if the given Python version matches a "Requires-Python" specifier. + + :param version_info: A 3-tuple of ints representing a Python + major-minor-micro version to check (e.g. `sys.version_info[:3]`). + + :return: `True` if the given Python version satisfies the requirement. + Otherwise, return `False`. + + :raises InvalidSpecifier: If `requires_python` has an invalid format. + """ + if requires_python is None: + # The package provides no information + return True + requires_python_specifier = specifiers.SpecifierSet(requires_python) + + python_version = version.parse('.'.join(map(str, version_info))) + return python_version in requires_python_specifier + + +def get_metadata(dist): + # type: (Distribution) -> Message + """ + :raises NoneMetadataError: if the distribution reports `has_metadata()` + True but `get_metadata()` returns None. + """ + metadata_name = 'METADATA' + if (isinstance(dist, pkg_resources.DistInfoDistribution) and + dist.has_metadata(metadata_name)): + metadata = dist.get_metadata(metadata_name) + elif dist.has_metadata('PKG-INFO'): + metadata_name = 'PKG-INFO' + metadata = dist.get_metadata(metadata_name) + else: + logger.warning("No metadata found in %s", display_path(dist.location)) + metadata = '' + + if metadata is None: + raise NoneMetadataError(dist, metadata_name) + + feed_parser = FeedParser() + # The following line errors out if with a "NoneType" TypeError if + # passed metadata=None. + feed_parser.feed(metadata) + return feed_parser.close() + + +def get_requires_python(dist): + # type: (pkg_resources.Distribution) -> Optional[str] + """ + Return the "Requires-Python" metadata for a distribution, or None + if not present. + """ + pkg_info_dict = get_metadata(dist) + requires_python = pkg_info_dict.get('Requires-Python') + + if requires_python is not None: + # Convert to a str to satisfy the type checker, since requires_python + # can be a Header object. + requires_python = str(requires_python) + + return requires_python + + +def get_installer(dist): + # type: (Distribution) -> str + if dist.has_metadata('INSTALLER'): + for line in dist.get_metadata_lines('INSTALLER'): + if line.strip(): + return line.strip() + return '' diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/parallel.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/parallel.py new file mode 100644 index 0000000..d4113bd --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/parallel.py @@ -0,0 +1,107 @@ +"""Convenient parallelization of higher order functions. + +This module provides two helper functions, with appropriate fallbacks on +Python 2 and on systems lacking support for synchronization mechanisms: + +- map_multiprocess +- map_multithread + +These helpers work like Python 3's map, with two differences: + +- They don't guarantee the order of processing of + the elements of the iterable. +- The underlying process/thread pools chop the iterable into + a number of chunks, so that for very long iterables using + a large value for chunksize can make the job complete much faster + than using the default value of 1. +""" + +__all__ = ['map_multiprocess', 'map_multithread'] + +from contextlib import contextmanager +from multiprocessing import Pool as ProcessPool +from multiprocessing.dummy import Pool as ThreadPool + +from pip._vendor.requests.adapters import DEFAULT_POOLSIZE +from pip._vendor.six import PY2 +from pip._vendor.six.moves import map + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from multiprocessing import pool + from typing import Callable, Iterable, Iterator, TypeVar, Union + + Pool = Union[pool.Pool, pool.ThreadPool] + S = TypeVar('S') + T = TypeVar('T') + +# On platforms without sem_open, multiprocessing[.dummy] Pool +# cannot be created. +try: + import multiprocessing.synchronize # noqa +except ImportError: + LACK_SEM_OPEN = True +else: + LACK_SEM_OPEN = False + +# Incredibly large timeout to work around bpo-8296 on Python 2. +TIMEOUT = 2000000 + + +@contextmanager +def closing(pool): + # type: (Pool) -> Iterator[Pool] + """Return a context manager making sure the pool closes properly.""" + try: + yield pool + finally: + # For Pool.imap*, close and join are needed + # for the returned iterator to begin yielding. + pool.close() + pool.join() + pool.terminate() + + +def _map_fallback(func, iterable, chunksize=1): + # type: (Callable[[S], T], Iterable[S], int) -> Iterator[T] + """Make an iterator applying func to each element in iterable. + + This function is the sequential fallback either on Python 2 + where Pool.imap* doesn't react to KeyboardInterrupt + or when sem_open is unavailable. + """ + return map(func, iterable) + + +def _map_multiprocess(func, iterable, chunksize=1): + # type: (Callable[[S], T], Iterable[S], int) -> Iterator[T] + """Chop iterable into chunks and submit them to a process pool. + + For very long iterables using a large value for chunksize can make + the job complete much faster than using the default value of 1. + + Return an unordered iterator of the results. + """ + with closing(ProcessPool()) as pool: + return pool.imap_unordered(func, iterable, chunksize) + + +def _map_multithread(func, iterable, chunksize=1): + # type: (Callable[[S], T], Iterable[S], int) -> Iterator[T] + """Chop iterable into chunks and submit them to a thread pool. + + For very long iterables using a large value for chunksize can make + the job complete much faster than using the default value of 1. + + Return an unordered iterator of the results. + """ + with closing(ThreadPool(DEFAULT_POOLSIZE)) as pool: + return pool.imap_unordered(func, iterable, chunksize) + + +if LACK_SEM_OPEN or PY2: + map_multiprocess = map_multithread = _map_fallback +else: + map_multiprocess = _map_multiprocess + map_multithread = _map_multithread diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/pkg_resources.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/pkg_resources.py new file mode 100644 index 0000000..0bc129a --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/pkg_resources.py @@ -0,0 +1,44 @@ +from pip._vendor.pkg_resources import yield_lines +from pip._vendor.six import ensure_str + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Dict, Iterable, List + + +class DictMetadata(object): + """IMetadataProvider that reads metadata files from a dictionary. + """ + def __init__(self, metadata): + # type: (Dict[str, bytes]) -> None + self._metadata = metadata + + def has_metadata(self, name): + # type: (str) -> bool + return name in self._metadata + + def get_metadata(self, name): + # type: (str) -> str + try: + return ensure_str(self._metadata[name]) + except UnicodeDecodeError as e: + # Mirrors handling done in pkg_resources.NullProvider. + e.reason += " in {} file".format(name) + raise + + def get_metadata_lines(self, name): + # type: (str) -> Iterable[str] + return yield_lines(self.get_metadata(name)) + + def metadata_isdir(self, name): + # type: (str) -> bool + return False + + def metadata_listdir(self, name): + # type: (str) -> List[str] + return [] + + def run_script(self, script_name, namespace): + # type: (str, str) -> None + pass diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/setuptools_build.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/setuptools_build.py new file mode 100644 index 0000000..2a664b0 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/setuptools_build.py @@ -0,0 +1,181 @@ +import sys + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional, Sequence + +# Shim to wrap setup.py invocation with setuptools +# +# We set sys.argv[0] to the path to the underlying setup.py file so +# setuptools / distutils don't take the path to the setup.py to be "-c" when +# invoking via the shim. This avoids e.g. the following manifest_maker +# warning: "warning: manifest_maker: standard file '-c' not found". +_SETUPTOOLS_SHIM = ( + "import sys, setuptools, tokenize; sys.argv[0] = {0!r}; __file__={0!r};" + "f=getattr(tokenize, 'open', open)(__file__);" + "code=f.read().replace('\\r\\n', '\\n');" + "f.close();" + "exec(compile(code, __file__, 'exec'))" +) + + +def make_setuptools_shim_args( + setup_py_path, # type: str + global_options=None, # type: Sequence[str] + no_user_config=False, # type: bool + unbuffered_output=False # type: bool +): + # type: (...) -> List[str] + """ + Get setuptools command arguments with shim wrapped setup file invocation. + + :param setup_py_path: The path to setup.py to be wrapped. + :param global_options: Additional global options. + :param no_user_config: If True, disables personal user configuration. + :param unbuffered_output: If True, adds the unbuffered switch to the + argument list. + """ + args = [sys.executable] + if unbuffered_output: + args += ["-u"] + args += ["-c", _SETUPTOOLS_SHIM.format(setup_py_path)] + if global_options: + args += global_options + if no_user_config: + args += ["--no-user-cfg"] + return args + + +def make_setuptools_bdist_wheel_args( + setup_py_path, # type: str + global_options, # type: Sequence[str] + build_options, # type: Sequence[str] + destination_dir, # type: str +): + # type: (...) -> List[str] + # NOTE: Eventually, we'd want to also -S to the flags here, when we're + # isolating. Currently, it breaks Python in virtualenvs, because it + # relies on site.py to find parts of the standard library outside the + # virtualenv. + args = make_setuptools_shim_args( + setup_py_path, + global_options=global_options, + unbuffered_output=True + ) + args += ["bdist_wheel", "-d", destination_dir] + args += build_options + return args + + +def make_setuptools_clean_args( + setup_py_path, # type: str + global_options, # type: Sequence[str] +): + # type: (...) -> List[str] + args = make_setuptools_shim_args( + setup_py_path, + global_options=global_options, + unbuffered_output=True + ) + args += ["clean", "--all"] + return args + + +def make_setuptools_develop_args( + setup_py_path, # type: str + global_options, # type: Sequence[str] + install_options, # type: Sequence[str] + no_user_config, # type: bool + prefix, # type: Optional[str] + home, # type: Optional[str] + use_user_site, # type: bool +): + # type: (...) -> List[str] + assert not (use_user_site and prefix) + + args = make_setuptools_shim_args( + setup_py_path, + global_options=global_options, + no_user_config=no_user_config, + ) + + args += ["develop", "--no-deps"] + + args += install_options + + if prefix: + args += ["--prefix", prefix] + if home is not None: + args += ["--home", home] + + if use_user_site: + args += ["--user", "--prefix="] + + return args + + +def make_setuptools_egg_info_args( + setup_py_path, # type: str + egg_info_dir, # type: Optional[str] + no_user_config, # type: bool +): + # type: (...) -> List[str] + args = make_setuptools_shim_args( + setup_py_path, no_user_config=no_user_config + ) + + args += ["egg_info"] + + if egg_info_dir: + args += ["--egg-base", egg_info_dir] + + return args + + +def make_setuptools_install_args( + setup_py_path, # type: str + global_options, # type: Sequence[str] + install_options, # type: Sequence[str] + record_filename, # type: str + root, # type: Optional[str] + prefix, # type: Optional[str] + header_dir, # type: Optional[str] + home, # type: Optional[str] + use_user_site, # type: bool + no_user_config, # type: bool + pycompile # type: bool +): + # type: (...) -> List[str] + assert not (use_user_site and prefix) + assert not (use_user_site and root) + + args = make_setuptools_shim_args( + setup_py_path, + global_options=global_options, + no_user_config=no_user_config, + unbuffered_output=True + ) + args += ["install", "--record", record_filename] + args += ["--single-version-externally-managed"] + + if root is not None: + args += ["--root", root] + if prefix is not None: + args += ["--prefix", prefix] + if home is not None: + args += ["--home", home] + if use_user_site: + args += ["--user", "--prefix="] + + if pycompile: + args += ["--compile"] + else: + args += ["--no-compile"] + + if header_dir: + args += ["--install-headers", header_dir] + + args += install_options + + return args diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/subprocess.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/subprocess.py new file mode 100644 index 0000000..3cd8b01 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/subprocess.py @@ -0,0 +1,299 @@ +from __future__ import absolute_import + +import logging +import os +import subprocess + +from pip._vendor.six.moves import shlex_quote + +from pip._internal.cli.spinners import SpinnerInterface, open_spinner +from pip._internal.exceptions import InstallationSubprocessError +from pip._internal.utils.compat import console_to_str, str_to_display +from pip._internal.utils.logging import subprocess_logger +from pip._internal.utils.misc import HiddenText, path_to_display +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Callable, Iterable, List, Mapping, Optional, Text, Union + + CommandArgs = List[Union[str, HiddenText]] + + +LOG_DIVIDER = '----------------------------------------' + + +def make_command(*args): + # type: (Union[str, HiddenText, CommandArgs]) -> CommandArgs + """ + Create a CommandArgs object. + """ + command_args = [] # type: CommandArgs + for arg in args: + # Check for list instead of CommandArgs since CommandArgs is + # only known during type-checking. + if isinstance(arg, list): + command_args.extend(arg) + else: + # Otherwise, arg is str or HiddenText. + command_args.append(arg) + + return command_args + + +def format_command_args(args): + # type: (Union[List[str], CommandArgs]) -> str + """ + Format command arguments for display. + """ + # For HiddenText arguments, display the redacted form by calling str(). + # Also, we don't apply str() to arguments that aren't HiddenText since + # this can trigger a UnicodeDecodeError in Python 2 if the argument + # has type unicode and includes a non-ascii character. (The type + # checker doesn't ensure the annotations are correct in all cases.) + return ' '.join( + shlex_quote(str(arg)) if isinstance(arg, HiddenText) + else shlex_quote(arg) for arg in args + ) + + +def reveal_command_args(args): + # type: (Union[List[str], CommandArgs]) -> List[str] + """ + Return the arguments in their raw, unredacted form. + """ + return [ + arg.secret if isinstance(arg, HiddenText) else arg for arg in args + ] + + +def make_subprocess_output_error( + cmd_args, # type: Union[List[str], CommandArgs] + cwd, # type: Optional[str] + lines, # type: List[Text] + exit_status, # type: int +): + # type: (...) -> Text + """ + Create and return the error message to use to log a subprocess error + with command output. + + :param lines: A list of lines, each ending with a newline. + """ + command = format_command_args(cmd_args) + # Convert `command` and `cwd` to text (unicode in Python 2) so we can use + # them as arguments in the unicode format string below. This avoids + # "UnicodeDecodeError: 'ascii' codec can't decode byte ..." in Python 2 + # if either contains a non-ascii character. + command_display = str_to_display(command, desc='command bytes') + cwd_display = path_to_display(cwd) + + # We know the joined output value ends in a newline. + output = ''.join(lines) + msg = ( + # Use a unicode string to avoid "UnicodeEncodeError: 'ascii' + # codec can't encode character ..." in Python 2 when a format + # argument (e.g. `output`) has a non-ascii character. + u'Command errored out with exit status {exit_status}:\n' + ' command: {command_display}\n' + ' cwd: {cwd_display}\n' + 'Complete output ({line_count} lines):\n{output}{divider}' + ).format( + exit_status=exit_status, + command_display=command_display, + cwd_display=cwd_display, + line_count=len(lines), + output=output, + divider=LOG_DIVIDER, + ) + return msg + + +def call_subprocess( + cmd, # type: Union[List[str], CommandArgs] + show_stdout=False, # type: bool + cwd=None, # type: Optional[str] + on_returncode='raise', # type: str + extra_ok_returncodes=None, # type: Optional[Iterable[int]] + command_desc=None, # type: Optional[str] + extra_environ=None, # type: Optional[Mapping[str, Any]] + unset_environ=None, # type: Optional[Iterable[str]] + spinner=None, # type: Optional[SpinnerInterface] + log_failed_cmd=True, # type: Optional[bool] + stdout_only=False, # type: Optional[bool] +): + # type: (...) -> Text + """ + Args: + show_stdout: if true, use INFO to log the subprocess's stderr and + stdout streams. Otherwise, use DEBUG. Defaults to False. + extra_ok_returncodes: an iterable of integer return codes that are + acceptable, in addition to 0. Defaults to None, which means []. + unset_environ: an iterable of environment variable names to unset + prior to calling subprocess.Popen(). + log_failed_cmd: if false, failed commands are not logged, only raised. + stdout_only: if true, return only stdout, else return both. When true, + logging of both stdout and stderr occurs when the subprocess has + terminated, else logging occurs as subprocess output is produced. + """ + if extra_ok_returncodes is None: + extra_ok_returncodes = [] + if unset_environ is None: + unset_environ = [] + # Most places in pip use show_stdout=False. What this means is-- + # + # - We connect the child's output (combined stderr and stdout) to a + # single pipe, which we read. + # - We log this output to stderr at DEBUG level as it is received. + # - If DEBUG logging isn't enabled (e.g. if --verbose logging wasn't + # requested), then we show a spinner so the user can still see the + # subprocess is in progress. + # - If the subprocess exits with an error, we log the output to stderr + # at ERROR level if it hasn't already been displayed to the console + # (e.g. if --verbose logging wasn't enabled). This way we don't log + # the output to the console twice. + # + # If show_stdout=True, then the above is still done, but with DEBUG + # replaced by INFO. + if show_stdout: + # Then log the subprocess output at INFO level. + log_subprocess = subprocess_logger.info + used_level = logging.INFO + else: + # Then log the subprocess output using DEBUG. This also ensures + # it will be logged to the log file (aka user_log), if enabled. + log_subprocess = subprocess_logger.debug + used_level = logging.DEBUG + + # Whether the subprocess will be visible in the console. + showing_subprocess = subprocess_logger.getEffectiveLevel() <= used_level + + # Only use the spinner if we're not showing the subprocess output + # and we have a spinner. + use_spinner = not showing_subprocess and spinner is not None + + if command_desc is None: + command_desc = format_command_args(cmd) + + log_subprocess("Running command %s", command_desc) + env = os.environ.copy() + if extra_environ: + env.update(extra_environ) + for name in unset_environ: + env.pop(name, None) + try: + proc = subprocess.Popen( + # Convert HiddenText objects to the underlying str. + reveal_command_args(cmd), + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT if not stdout_only else subprocess.PIPE, + cwd=cwd, + env=env, + ) + except Exception as exc: + if log_failed_cmd: + subprocess_logger.critical( + "Error %s while executing command %s", exc, command_desc, + ) + raise + all_output = [] + if not stdout_only: + assert proc.stdout + assert proc.stdin + proc.stdin.close() + # In this mode, stdout and stderr are in the same pipe. + while True: + # The "line" value is a unicode string in Python 2. + line = console_to_str(proc.stdout.readline()) + if not line: + break + line = line.rstrip() + all_output.append(line + '\n') + + # Show the line immediately. + log_subprocess(line) + # Update the spinner. + if use_spinner: + assert spinner + spinner.spin() + try: + proc.wait() + finally: + if proc.stdout: + proc.stdout.close() + output = ''.join(all_output) + else: + # In this mode, stdout and stderr are in different pipes. + # We must use communicate() which is the only safe way to read both. + out_bytes, err_bytes = proc.communicate() + # log line by line to preserve pip log indenting + out = console_to_str(out_bytes) + for out_line in out.splitlines(): + log_subprocess(out_line) + all_output.append(out) + err = console_to_str(err_bytes) + for err_line in err.splitlines(): + log_subprocess(err_line) + all_output.append(err) + output = out + + proc_had_error = ( + proc.returncode and proc.returncode not in extra_ok_returncodes + ) + if use_spinner: + assert spinner + if proc_had_error: + spinner.finish("error") + else: + spinner.finish("done") + if proc_had_error: + if on_returncode == 'raise': + if not showing_subprocess and log_failed_cmd: + # Then the subprocess streams haven't been logged to the + # console yet. + msg = make_subprocess_output_error( + cmd_args=cmd, + cwd=cwd, + lines=all_output, + exit_status=proc.returncode, + ) + subprocess_logger.error(msg) + raise InstallationSubprocessError(proc.returncode, command_desc) + elif on_returncode == 'warn': + subprocess_logger.warning( + 'Command "%s" had error code %s in %s', + command_desc, + proc.returncode, + cwd, + ) + elif on_returncode == 'ignore': + pass + else: + raise ValueError('Invalid value: on_returncode={!r}'.format( + on_returncode)) + return output + + +def runner_with_spinner_message(message): + # type: (str) -> Callable[..., None] + """Provide a subprocess_runner that shows a spinner message. + + Intended for use with for pep517's Pep517HookCaller. Thus, the runner has + an API that matches what's expected by Pep517HookCaller.subprocess_runner. + """ + + def runner( + cmd, # type: List[str] + cwd=None, # type: Optional[str] + extra_environ=None # type: Optional[Mapping[str, Any]] + ): + # type: (...) -> None + with open_spinner(message) as spinner: + call_subprocess( + cmd, + cwd=cwd, + extra_environ=extra_environ, + spinner=spinner, + ) + + return runner diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/temp_dir.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/temp_dir.py new file mode 100644 index 0000000..371958c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/temp_dir.py @@ -0,0 +1,284 @@ +from __future__ import absolute_import + +import errno +import itertools +import logging +import os.path +import tempfile +from contextlib import contextmanager + +from pip._vendor.contextlib2 import ExitStack +from pip._vendor.six import ensure_text + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.misc import enum, rmtree +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Dict, Iterator, Optional, TypeVar, Union + + _T = TypeVar('_T', bound='TempDirectory') + + +logger = logging.getLogger(__name__) + + +# Kinds of temporary directories. Only needed for ones that are +# globally-managed. +tempdir_kinds = enum( + BUILD_ENV="build-env", + EPHEM_WHEEL_CACHE="ephem-wheel-cache", + REQ_BUILD="req-build", +) + + +_tempdir_manager = None # type: Optional[ExitStack] + + +@contextmanager +def global_tempdir_manager(): + # type: () -> Iterator[None] + global _tempdir_manager + with ExitStack() as stack: + old_tempdir_manager, _tempdir_manager = _tempdir_manager, stack + try: + yield + finally: + _tempdir_manager = old_tempdir_manager + + +class TempDirectoryTypeRegistry(object): + """Manages temp directory behavior + """ + + def __init__(self): + # type: () -> None + self._should_delete = {} # type: Dict[str, bool] + + def set_delete(self, kind, value): + # type: (str, bool) -> None + """Indicate whether a TempDirectory of the given kind should be + auto-deleted. + """ + self._should_delete[kind] = value + + def get_delete(self, kind): + # type: (str) -> bool + """Get configured auto-delete flag for a given TempDirectory type, + default True. + """ + return self._should_delete.get(kind, True) + + +_tempdir_registry = None # type: Optional[TempDirectoryTypeRegistry] + + +@contextmanager +def tempdir_registry(): + # type: () -> Iterator[TempDirectoryTypeRegistry] + """Provides a scoped global tempdir registry that can be used to dictate + whether directories should be deleted. + """ + global _tempdir_registry + old_tempdir_registry = _tempdir_registry + _tempdir_registry = TempDirectoryTypeRegistry() + try: + yield _tempdir_registry + finally: + _tempdir_registry = old_tempdir_registry + + +class _Default(object): + pass + + +_default = _Default() + + +class TempDirectory(object): + """Helper class that owns and cleans up a temporary directory. + + This class can be used as a context manager or as an OO representation of a + temporary directory. + + Attributes: + path + Location to the created temporary directory + delete + Whether the directory should be deleted when exiting + (when used as a contextmanager) + + Methods: + cleanup() + Deletes the temporary directory + + When used as a context manager, if the delete attribute is True, on + exiting the context the temporary directory is deleted. + """ + + def __init__( + self, + path=None, # type: Optional[str] + delete=_default, # type: Union[bool, None, _Default] + kind="temp", # type: str + globally_managed=False, # type: bool + ): + super(TempDirectory, self).__init__() + + if delete is _default: + if path is not None: + # If we were given an explicit directory, resolve delete option + # now. + delete = False + else: + # Otherwise, we wait until cleanup and see what + # tempdir_registry says. + delete = None + + # The only time we specify path is in for editables where it + # is the value of the --src option. + if path is None: + path = self._create(kind) + + self._path = path + self._deleted = False + self.delete = delete + self.kind = kind + + if globally_managed: + assert _tempdir_manager is not None + _tempdir_manager.enter_context(self) + + @property + def path(self): + # type: () -> str + assert not self._deleted, ( + "Attempted to access deleted path: {}".format(self._path) + ) + return self._path + + def __repr__(self): + # type: () -> str + return "<{} {!r}>".format(self.__class__.__name__, self.path) + + def __enter__(self): + # type: (_T) -> _T + return self + + def __exit__(self, exc, value, tb): + # type: (Any, Any, Any) -> None + if self.delete is not None: + delete = self.delete + elif _tempdir_registry: + delete = _tempdir_registry.get_delete(self.kind) + else: + delete = True + + if delete: + self.cleanup() + + def _create(self, kind): + # type: (str) -> str + """Create a temporary directory and store its path in self.path + """ + # We realpath here because some systems have their default tmpdir + # symlinked to another directory. This tends to confuse build + # scripts, so we canonicalize the path by traversing potential + # symlinks here. + path = os.path.realpath( + tempfile.mkdtemp(prefix="pip-{}-".format(kind)) + ) + logger.debug("Created temporary directory: %s", path) + return path + + def cleanup(self): + # type: () -> None + """Remove the temporary directory created and reset state + """ + self._deleted = True + if not os.path.exists(self._path): + return + # Make sure to pass unicode on Python 2 to make the contents also + # use unicode, ensuring non-ASCII names and can be represented. + # This is only done on Windows because POSIX platforms use bytes + # natively for paths, and the bytes-text conversion omission avoids + # errors caused by the environment configuring encodings incorrectly. + if WINDOWS: + rmtree(ensure_text(self._path)) + else: + rmtree(self._path) + + +class AdjacentTempDirectory(TempDirectory): + """Helper class that creates a temporary directory adjacent to a real one. + + Attributes: + original + The original directory to create a temp directory for. + path + After calling create() or entering, contains the full + path to the temporary directory. + delete + Whether the directory should be deleted when exiting + (when used as a contextmanager) + + """ + # The characters that may be used to name the temp directory + # We always prepend a ~ and then rotate through these until + # a usable name is found. + # pkg_resources raises a different error for .dist-info folder + # with leading '-' and invalid metadata + LEADING_CHARS = "-~.=%0123456789" + + def __init__(self, original, delete=None): + # type: (str, Optional[bool]) -> None + self.original = original.rstrip('/\\') + super(AdjacentTempDirectory, self).__init__(delete=delete) + + @classmethod + def _generate_names(cls, name): + # type: (str) -> Iterator[str] + """Generates a series of temporary names. + + The algorithm replaces the leading characters in the name + with ones that are valid filesystem characters, but are not + valid package names (for both Python and pip definitions of + package). + """ + for i in range(1, len(name)): + for candidate in itertools.combinations_with_replacement( + cls.LEADING_CHARS, i - 1): + new_name = '~' + ''.join(candidate) + name[i:] + if new_name != name: + yield new_name + + # If we make it this far, we will have to make a longer name + for i in range(len(cls.LEADING_CHARS)): + for candidate in itertools.combinations_with_replacement( + cls.LEADING_CHARS, i): + new_name = '~' + ''.join(candidate) + name + if new_name != name: + yield new_name + + def _create(self, kind): + # type: (str) -> str + root, name = os.path.split(self.original) + for candidate in self._generate_names(name): + path = os.path.join(root, candidate) + try: + os.mkdir(path) + except OSError as ex: + # Continue if the name exists already + if ex.errno != errno.EEXIST: + raise + else: + path = os.path.realpath(path) + break + else: + # Final fallback on the default behavior. + path = os.path.realpath( + tempfile.mkdtemp(prefix="pip-{}-".format(kind)) + ) + + logger.debug("Created temporary directory: %s", path) + return path diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/typing.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/typing.py new file mode 100644 index 0000000..8505a29 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/typing.py @@ -0,0 +1,38 @@ +"""For neatly implementing static typing in pip. + +`mypy` - the static type analysis tool we use - uses the `typing` module, which +provides core functionality fundamental to mypy's functioning. + +Generally, `typing` would be imported at runtime and used in that fashion - +it acts as a no-op at runtime and does not have any run-time overhead by +design. + +As it turns out, `typing` is not vendorable - it uses separate sources for +Python 2/Python 3. Thus, this codebase can not expect it to be present. +To work around this, mypy allows the typing import to be behind a False-y +optional to prevent it from running at runtime and type-comments can be used +to remove the need for the types to be accessible directly during runtime. + +This module provides the False-y guard in a nicely named fashion so that a +curious maintainer can reach here to read this. + +In pip, all static-typing related imports should be guarded as follows: + + from pip._internal.utils.typing import MYPY_CHECK_RUNNING + + if MYPY_CHECK_RUNNING: + from typing import ... + +Ref: https://github.com/python/mypy/issues/3216 +""" + +MYPY_CHECK_RUNNING = False + + +if MYPY_CHECK_RUNNING: + from typing import cast +else: + # typing's cast() is needed at runtime, but we don't want to import typing. + # Thus, we use a dummy no-op version, which we tell mypy to ignore. + def cast(type_, value): # type: ignore + return value diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/unpacking.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/unpacking.py new file mode 100644 index 0000000..620f31e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/unpacking.py @@ -0,0 +1,281 @@ +"""Utilities related archives. +""" + +from __future__ import absolute_import + +import logging +import os +import shutil +import stat +import tarfile +import zipfile + +from pip._internal.exceptions import InstallationError +from pip._internal.utils.filetypes import ( + BZ2_EXTENSIONS, + TAR_EXTENSIONS, + XZ_EXTENSIONS, + ZIP_EXTENSIONS, +) +from pip._internal.utils.misc import ensure_dir +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Iterable, List, Optional, Text, Union + from zipfile import ZipInfo + + +logger = logging.getLogger(__name__) + + +SUPPORTED_EXTENSIONS = ZIP_EXTENSIONS + TAR_EXTENSIONS + +try: + import bz2 # noqa + SUPPORTED_EXTENSIONS += BZ2_EXTENSIONS +except ImportError: + logger.debug('bz2 module is not available') + +try: + # Only for Python 3.3+ + import lzma # noqa + SUPPORTED_EXTENSIONS += XZ_EXTENSIONS +except ImportError: + logger.debug('lzma module is not available') + + +def current_umask(): + # type: () -> int + """Get the current umask which involves having to set it temporarily.""" + mask = os.umask(0) + os.umask(mask) + return mask + + +def split_leading_dir(path): + # type: (Union[str, Text]) -> List[Union[str, Text]] + path = path.lstrip('/').lstrip('\\') + if ( + '/' in path and ( + ('\\' in path and path.find('/') < path.find('\\')) or + '\\' not in path + ) + ): + return path.split('/', 1) + elif '\\' in path: + return path.split('\\', 1) + else: + return [path, ''] + + +def has_leading_dir(paths): + # type: (Iterable[Union[str, Text]]) -> bool + """Returns true if all the paths have the same leading path name + (i.e., everything is in one subdirectory in an archive)""" + common_prefix = None + for path in paths: + prefix, rest = split_leading_dir(path) + if not prefix: + return False + elif common_prefix is None: + common_prefix = prefix + elif prefix != common_prefix: + return False + return True + + +def is_within_directory(directory, target): + # type: ((Union[str, Text]), (Union[str, Text])) -> bool + """ + Return true if the absolute path of target is within the directory + """ + abs_directory = os.path.abspath(directory) + abs_target = os.path.abspath(target) + + prefix = os.path.commonprefix([abs_directory, abs_target]) + return prefix == abs_directory + + +def set_extracted_file_to_default_mode_plus_executable(path): + # type: (Union[str, Text]) -> None + """ + Make file present at path have execute for user/group/world + (chmod +x) is no-op on windows per python docs + """ + os.chmod(path, (0o777 & ~current_umask() | 0o111)) + + +def zip_item_is_executable(info): + # type: (ZipInfo) -> bool + mode = info.external_attr >> 16 + # if mode and regular file and any execute permissions for + # user/group/world? + return bool(mode and stat.S_ISREG(mode) and mode & 0o111) + + +def unzip_file(filename, location, flatten=True): + # type: (str, str, bool) -> None + """ + Unzip the file (with path `filename`) to the destination `location`. All + files are written based on system defaults and umask (i.e. permissions are + not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ + ensure_dir(location) + zipfp = open(filename, 'rb') + try: + zip = zipfile.ZipFile(zipfp, allowZip64=True) + leading = has_leading_dir(zip.namelist()) and flatten + for info in zip.infolist(): + name = info.filename + fn = name + if leading: + fn = split_leading_dir(name)[1] + fn = os.path.join(location, fn) + dir = os.path.dirname(fn) + if not is_within_directory(location, fn): + message = ( + 'The zip file ({}) has a file ({}) trying to install ' + 'outside target directory ({})' + ) + raise InstallationError(message.format(filename, fn, location)) + if fn.endswith('/') or fn.endswith('\\'): + # A directory + ensure_dir(fn) + else: + ensure_dir(dir) + # Don't use read() to avoid allocating an arbitrarily large + # chunk of memory for the file's content + fp = zip.open(name) + try: + with open(fn, 'wb') as destfp: + shutil.copyfileobj(fp, destfp) + finally: + fp.close() + if zip_item_is_executable(info): + set_extracted_file_to_default_mode_plus_executable(fn) + finally: + zipfp.close() + + +def untar_file(filename, location): + # type: (str, str) -> None + """ + Untar the file (with path `filename`) to the destination `location`. + All files are written based on system defaults and umask (i.e. permissions + are not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ + ensure_dir(location) + if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'): + mode = 'r:gz' + elif filename.lower().endswith(BZ2_EXTENSIONS): + mode = 'r:bz2' + elif filename.lower().endswith(XZ_EXTENSIONS): + mode = 'r:xz' + elif filename.lower().endswith('.tar'): + mode = 'r' + else: + logger.warning( + 'Cannot determine compression type for file %s', filename, + ) + mode = 'r:*' + tar = tarfile.open(filename, mode) + try: + leading = has_leading_dir([ + member.name for member in tar.getmembers() + ]) + for member in tar.getmembers(): + fn = member.name + if leading: + # https://github.com/python/mypy/issues/1174 + fn = split_leading_dir(fn)[1] # type: ignore + path = os.path.join(location, fn) + if not is_within_directory(location, path): + message = ( + 'The tar file ({}) has a file ({}) trying to install ' + 'outside target directory ({})' + ) + raise InstallationError( + message.format(filename, path, location) + ) + if member.isdir(): + ensure_dir(path) + elif member.issym(): + try: + # https://github.com/python/typeshed/issues/2673 + tar._extract_member(member, path) # type: ignore + except Exception as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + 'In the tar file %s the member %s is invalid: %s', + filename, member.name, exc, + ) + continue + else: + try: + fp = tar.extractfile(member) + except (KeyError, AttributeError) as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + 'In the tar file %s the member %s is invalid: %s', + filename, member.name, exc, + ) + continue + ensure_dir(os.path.dirname(path)) + assert fp is not None + with open(path, 'wb') as destfp: + shutil.copyfileobj(fp, destfp) + fp.close() + # Update the timestamp (useful for cython compiled files) + # https://github.com/python/typeshed/issues/2673 + tar.utime(member, path) # type: ignore + # member have any execute permissions for user/group/world? + if member.mode & 0o111: + set_extracted_file_to_default_mode_plus_executable(path) + finally: + tar.close() + + +def unpack_file( + filename, # type: str + location, # type: str + content_type=None, # type: Optional[str] +): + # type: (...) -> None + filename = os.path.realpath(filename) + if ( + content_type == 'application/zip' or + filename.lower().endswith(ZIP_EXTENSIONS) or + zipfile.is_zipfile(filename) + ): + unzip_file( + filename, + location, + flatten=not filename.endswith('.whl') + ) + elif ( + content_type == 'application/x-gzip' or + tarfile.is_tarfile(filename) or + filename.lower().endswith( + TAR_EXTENSIONS + BZ2_EXTENSIONS + XZ_EXTENSIONS + ) + ): + untar_file(filename, location) + else: + # FIXME: handle? + # FIXME: magic signatures? + logger.critical( + 'Cannot unpack file %s (downloaded from %s, content-type: %s); ' + 'cannot detect archive format', + filename, location, content_type, + ) + raise InstallationError( + 'Cannot determine archive format of {}'.format(location) + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/urls.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/urls.py new file mode 100644 index 0000000..f37bc8f --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/urls.py @@ -0,0 +1,55 @@ +import os +import sys + +from pip._vendor.six.moves.urllib import parse as urllib_parse +from pip._vendor.six.moves.urllib import request as urllib_request + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Optional, Text, Union + + +def get_url_scheme(url): + # type: (Union[str, Text]) -> Optional[Text] + if ':' not in url: + return None + return url.split(':', 1)[0].lower() + + +def path_to_url(path): + # type: (Union[str, Text]) -> str + """ + Convert a path to a file: URL. The path will be made absolute and have + quoted path parts. + """ + path = os.path.normpath(os.path.abspath(path)) + url = urllib_parse.urljoin('file:', urllib_request.pathname2url(path)) + return url + + +def url_to_path(url): + # type: (str) -> str + """ + Convert a file: URL to a path. + """ + assert url.startswith('file:'), ( + "You can only turn file: urls into filenames (not {url!r})" + .format(**locals())) + + _, netloc, path, _, _ = urllib_parse.urlsplit(url) + + if not netloc or netloc == 'localhost': + # According to RFC 8089, same as empty authority. + netloc = '' + elif sys.platform == 'win32': + # If we have a UNC path, prepend UNC share notation. + netloc = '\\\\' + netloc + else: + raise ValueError( + 'non-local file URIs are not supported on this platform: {url!r}' + .format(**locals()) + ) + + path = urllib_request.url2pathname(netloc + path) + return path diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/virtualenv.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/virtualenv.py new file mode 100644 index 0000000..4a78128 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/virtualenv.py @@ -0,0 +1,119 @@ +from __future__ import absolute_import + +import io +import logging +import os +import re +import site +import sys + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Optional + +logger = logging.getLogger(__name__) +_INCLUDE_SYSTEM_SITE_PACKAGES_REGEX = re.compile( + r"include-system-site-packages\s*=\s*(?Ptrue|false)" +) + + +def _running_under_venv(): + # type: () -> bool + """Checks if sys.base_prefix and sys.prefix match. + + This handles PEP 405 compliant virtual environments. + """ + return sys.prefix != getattr(sys, "base_prefix", sys.prefix) + + +def _running_under_regular_virtualenv(): + # type: () -> bool + """Checks if sys.real_prefix is set. + + This handles virtual environments created with pypa's virtualenv. + """ + # pypa/virtualenv case + return hasattr(sys, 'real_prefix') + + +def running_under_virtualenv(): + # type: () -> bool + """Return True if we're running inside a virtualenv, False otherwise. + """ + return _running_under_venv() or _running_under_regular_virtualenv() + + +def _get_pyvenv_cfg_lines(): + # type: () -> Optional[List[str]] + """Reads {sys.prefix}/pyvenv.cfg and returns its contents as list of lines + + Returns None, if it could not read/access the file. + """ + pyvenv_cfg_file = os.path.join(sys.prefix, 'pyvenv.cfg') + try: + # Although PEP 405 does not specify, the built-in venv module always + # writes with UTF-8. (pypa/pip#8717) + with io.open(pyvenv_cfg_file, encoding='utf-8') as f: + return f.read().splitlines() # avoids trailing newlines + except IOError: + return None + + +def _no_global_under_venv(): + # type: () -> bool + """Check `{sys.prefix}/pyvenv.cfg` for system site-packages inclusion + + PEP 405 specifies that when system site-packages are not supposed to be + visible from a virtual environment, `pyvenv.cfg` must contain the following + line: + + include-system-site-packages = false + + Additionally, log a warning if accessing the file fails. + """ + cfg_lines = _get_pyvenv_cfg_lines() + if cfg_lines is None: + # We're not in a "sane" venv, so assume there is no system + # site-packages access (since that's PEP 405's default state). + logger.warning( + "Could not access 'pyvenv.cfg' despite a virtual environment " + "being active. Assuming global site-packages is not accessible " + "in this environment." + ) + return True + + for line in cfg_lines: + match = _INCLUDE_SYSTEM_SITE_PACKAGES_REGEX.match(line) + if match is not None and match.group('value') == 'false': + return True + return False + + +def _no_global_under_regular_virtualenv(): + # type: () -> bool + """Check if "no-global-site-packages.txt" exists beside site.py + + This mirrors logic in pypa/virtualenv for determining whether system + site-packages are visible in the virtual environment. + """ + site_mod_dir = os.path.dirname(os.path.abspath(site.__file__)) + no_global_site_packages_file = os.path.join( + site_mod_dir, 'no-global-site-packages.txt', + ) + return os.path.exists(no_global_site_packages_file) + + +def virtualenv_no_global(): + # type: () -> bool + """Returns a boolean, whether running in venv with no system site-packages. + """ + # PEP 405 compliance needs to be checked first since virtualenv >=20 would + # return True for both checks, but is only able to use the PEP 405 config. + if _running_under_venv(): + return _no_global_under_venv() + + if _running_under_regular_virtualenv(): + return _no_global_under_regular_virtualenv() + + return False diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/wheel.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/wheel.py new file mode 100644 index 0000000..9ce371c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/utils/wheel.py @@ -0,0 +1,225 @@ +"""Support functions for working with wheel files. +""" + +from __future__ import absolute_import + +import logging +from email.parser import Parser +from zipfile import ZipFile + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.pkg_resources import DistInfoDistribution +from pip._vendor.six import PY2, ensure_str + +from pip._internal.exceptions import UnsupportedWheel +from pip._internal.utils.pkg_resources import DictMetadata +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from email.message import Message + from typing import Dict, Tuple + + from pip._vendor.pkg_resources import Distribution + +if PY2: + from zipfile import BadZipfile as BadZipFile +else: + from zipfile import BadZipFile + + +VERSION_COMPATIBLE = (1, 0) + + +logger = logging.getLogger(__name__) + + +class WheelMetadata(DictMetadata): + """Metadata provider that maps metadata decoding exceptions to our + internal exception type. + """ + def __init__(self, metadata, wheel_name): + # type: (Dict[str, bytes], str) -> None + super(WheelMetadata, self).__init__(metadata) + self._wheel_name = wheel_name + + def get_metadata(self, name): + # type: (str) -> str + try: + return super(WheelMetadata, self).get_metadata(name) + except UnicodeDecodeError as e: + # Augment the default error with the origin of the file. + raise UnsupportedWheel( + "Error decoding metadata for {}: {}".format( + self._wheel_name, e + ) + ) + + +def pkg_resources_distribution_for_wheel(wheel_zip, name, location): + # type: (ZipFile, str, str) -> Distribution + """Get a pkg_resources distribution given a wheel. + + :raises UnsupportedWheel: on any errors + """ + info_dir, _ = parse_wheel(wheel_zip, name) + + metadata_files = [ + p for p in wheel_zip.namelist() if p.startswith("{}/".format(info_dir)) + ] + + metadata_text = {} # type: Dict[str, bytes] + for path in metadata_files: + # If a flag is set, namelist entries may be unicode in Python 2. + # We coerce them to native str type to match the types used in the rest + # of the code. This cannot fail because unicode can always be encoded + # with UTF-8. + full_path = ensure_str(path) + _, metadata_name = full_path.split("/", 1) + + try: + metadata_text[metadata_name] = read_wheel_metadata_file( + wheel_zip, full_path + ) + except UnsupportedWheel as e: + raise UnsupportedWheel( + "{} has an invalid wheel, {}".format(name, str(e)) + ) + + metadata = WheelMetadata(metadata_text, location) + + return DistInfoDistribution( + location=location, metadata=metadata, project_name=name + ) + + +def parse_wheel(wheel_zip, name): + # type: (ZipFile, str) -> Tuple[str, Message] + """Extract information from the provided wheel, ensuring it meets basic + standards. + + Returns the name of the .dist-info directory and the parsed WHEEL metadata. + """ + try: + info_dir = wheel_dist_info_dir(wheel_zip, name) + metadata = wheel_metadata(wheel_zip, info_dir) + version = wheel_version(metadata) + except UnsupportedWheel as e: + raise UnsupportedWheel( + "{} has an invalid wheel, {}".format(name, str(e)) + ) + + check_compatibility(version, name) + + return info_dir, metadata + + +def wheel_dist_info_dir(source, name): + # type: (ZipFile, str) -> str + """Returns the name of the contained .dist-info directory. + + Raises AssertionError or UnsupportedWheel if not found, >1 found, or + it doesn't match the provided name. + """ + # Zip file path separators must be / + subdirs = set(p.split("/", 1)[0] for p in source.namelist()) + + info_dirs = [s for s in subdirs if s.endswith('.dist-info')] + + if not info_dirs: + raise UnsupportedWheel(".dist-info directory not found") + + if len(info_dirs) > 1: + raise UnsupportedWheel( + "multiple .dist-info directories found: {}".format( + ", ".join(info_dirs) + ) + ) + + info_dir = info_dirs[0] + + info_dir_name = canonicalize_name(info_dir) + canonical_name = canonicalize_name(name) + if not info_dir_name.startswith(canonical_name): + raise UnsupportedWheel( + ".dist-info directory {!r} does not start with {!r}".format( + info_dir, canonical_name + ) + ) + + # Zip file paths can be unicode or str depending on the zip entry flags, + # so normalize it. + return ensure_str(info_dir) + + +def read_wheel_metadata_file(source, path): + # type: (ZipFile, str) -> bytes + try: + return source.read(path) + # BadZipFile for general corruption, KeyError for missing entry, + # and RuntimeError for password-protected files + except (BadZipFile, KeyError, RuntimeError) as e: + raise UnsupportedWheel( + "could not read {!r} file: {!r}".format(path, e) + ) + + +def wheel_metadata(source, dist_info_dir): + # type: (ZipFile, str) -> Message + """Return the WHEEL metadata of an extracted wheel, if possible. + Otherwise, raise UnsupportedWheel. + """ + path = "{}/WHEEL".format(dist_info_dir) + # Zip file path separators must be / + wheel_contents = read_wheel_metadata_file(source, path) + + try: + wheel_text = ensure_str(wheel_contents) + except UnicodeDecodeError as e: + raise UnsupportedWheel("error decoding {!r}: {!r}".format(path, e)) + + # FeedParser (used by Parser) does not raise any exceptions. The returned + # message may have .defects populated, but for backwards-compatibility we + # currently ignore them. + return Parser().parsestr(wheel_text) + + +def wheel_version(wheel_data): + # type: (Message) -> Tuple[int, ...] + """Given WHEEL metadata, return the parsed Wheel-Version. + Otherwise, raise UnsupportedWheel. + """ + version_text = wheel_data["Wheel-Version"] + if version_text is None: + raise UnsupportedWheel("WHEEL is missing Wheel-Version") + + version = version_text.strip() + + try: + return tuple(map(int, version.split('.'))) + except ValueError: + raise UnsupportedWheel("invalid Wheel-Version: {!r}".format(version)) + + +def check_compatibility(version, name): + # type: (Tuple[int, ...], str) -> None + """Raises errors or warns if called with an incompatible Wheel-Version. + + pip should refuse to install a Wheel-Version that's a major series + ahead of what it's compatible with (e.g 2.0 > 1.1); and warn when + installing a version only minor version ahead (e.g 1.2 > 1.1). + + version: a 2-tuple representing a Wheel-Version (Major, Minor) + name: name of wheel or package to raise exception about + + :raises UnsupportedWheel: when an incompatible Wheel-Version is given + """ + if version[0] > VERSION_COMPATIBLE[0]: + raise UnsupportedWheel( + "{}'s Wheel-Version ({}) is not compatible with this version " + "of pip".format(name, '.'.join(map(str, version))) + ) + elif version > VERSION_COMPATIBLE: + logger.warning( + 'Installing from a newer Wheel-Version (%s)', + '.'.join(map(str, version)), + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__init__.py new file mode 100644 index 0000000..2a4eb13 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__init__.py @@ -0,0 +1,15 @@ +# Expose a limited set of classes and functions so callers outside of +# the vcs package don't need to import deeper than `pip._internal.vcs`. +# (The test directory and imports protected by MYPY_CHECK_RUNNING may +# still need to import from a vcs sub-package.) +# Import all vcs modules to register each VCS in the VcsSupport object. +import pip._internal.vcs.bazaar +import pip._internal.vcs.git +import pip._internal.vcs.mercurial +import pip._internal.vcs.subversion # noqa: F401 +from pip._internal.vcs.versioncontrol import ( # noqa: F401 + RemoteNotFoundError, + is_url, + make_vcs_requirement_url, + vcs, +) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d104d1c1beeb199e49bdfdc1d7bcb5f36249ae08 GIT binary patch literal 512 zcmZWlJx{|h5Ote2O)EMfq)ITbb|4;@kSfFiV+Yu>L~e3wP5lwhPEe8H|L~W*GO;r; zaVZr-iY>qAd+%(YPfVv1Mq~5(C1jtmk2d%}NMkp&+=8HFWlyoJx99$WqXQ52+*d;# zXR#h-Bb{W49%thooqAyN=#y?>%lRN2--EUume$|d+LX757DFsuUZV;#Ew+$1h0771 zYKfr1_`MU6IG==BC95=-#seCmQWDdZco70aL{2#A+H2{OMU7IZaMm?ly=nlR zv?iQ)-GfzFlL3n6JSAlEl*nOv9C2@oMKc)?B7n+)2usXbjomm&n<{B)cP5y$D8yZnumOVJ zT}l>*I>|G+H2n*DkY;-Et$#%SioN#adrz58-QQb~vZc7-?8DpLw-0aMH+ujMt&i>U}@^$ zyBTd-d#DM!lEnhIlRG}j~(6=t4CgRRjeJqBCej0%5kr{8Vudp0` zG}c&6GE=!b8E3@4{(j227~K_*G!eWr(Zdf$yM?KLBKAsZ)hF>^e8@!fsJ{RRCt}=z zSr|;>Mn3nV3iqSnb7z2#D(Ah)xkZ;?}8*?gvre}Mf2*OwCJ1Ggz>! z+juyP1JLjM^f@EQZ-Tyup_T!hpus|Snfa{6-2YCSa}$(e_ZO+f5(1p+{cTL3N$12l z^fj~(-MTZs)c%Q&NVEC{Mdbw12b)w5E3ip0tDHugzdgNpdno!3($Sy|owTp1Yl^gb zP02N||I)qj5W!c+Md!KL1X(c{2x*PFKHN;)M!qbCxJhV{=aAn-n9 zBht_jG{If#b@O}^sQnb*L`v}b`@G}YTi8p@4J*F~4$p6LPGtEb?0$%`2%&}jO15X@ zBJZMM<@yE?jmYH`4-E0(9r}1%Dui#1t6e@XuSDQq=!XTFQff4?~vK(X2%|<=>Ilu!!A09 z^Elu2Y)+pBC?q#~y{S)y18ThhPGvIRcrn&c&*KF3*3^|wq$UjxJ3j1^sZ#%6$2n6& zfsjb`O37D<4<$RjP!q4Ls%x}Sb-my3Hp@!?ge8PBe$+2Nqp|F!X8sT@u zT!$flGnjW)d5%B4{_rX%lUKLpck%T*cb|CjH6X}aHf6=dC_9ip!Ai%SZuBW|DQJt` zc3IDFwx=tofT)_M3s0$3pw3fdLaXB})mb_c3I$cmbS&SZ^@?3L8*!>)%3+lFQ1xuO zl~i63(?7>cQl&6HbcnP`Yz%v3e4;(?X3Jz%De?lH9mxNLbBf~7aeY>Q7NEd|NO^U( z3=6gJn_hUqM$gZku@1T6sdd_z{D154$|cfcux%Fe)g`^kZ7!;vSs zu$64DY*JO57o%_KcAg+H-Ldj4M5P!s{wT@Cc`?^uJ!*>48KpcH4<|`B0dbj@yy>O6 zm|vypY*0%@EYVWc<2Wz)BqO{L$Hb-Fksr~Qt2{*mlM7QLv)ev z`?)|L#3dy;TkYfz38P#oZxW*=+kDNbC~oDi32YOf>|~nr{;ZFtERJ8etd03L(NQ;e z1w*|KKt;m-Dvhek>Rz}KE{A?taoKW+`3gqhGJB@;DqVATq9+p9l$7sGmFgPGpuC1z zbQSGdH%3#(3)xlaqi$a83Dt!wqsNnEP)Y7=wk+MEt?N#7nyGG{s(x7+Z8!1i%V^YO zXDo}pKn^3HHkV&Uqz}d<5mo$`e~BW|2B>MDJ&*npEvfy((=Y$<$QlVve>6=n=etBJ z4FXL9)QU*z-c1b-|Di4O@^`fOCIM2mL5vL0C!rI!N%uKu+ugTH*Lj{#po{mfK)0ukN+}{69hr#7+PJ literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/git.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/git.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..258923afbd54f4651263661d3c0d41b98f7d788b GIT binary patch literal 10647 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 Kxj$Cu&-p)Rh^g)X literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b7b63441f2133fd15e2637158d5ed3db555baa9 GIT binary patch literal 5209 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 MPj=OAd~VeL2bX|Hga7~l literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34fe371ba184092e48fcaf50ebe5a7a8b8c8c645 GIT binary patch literal 8634 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/bazaar.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/bazaar.py new file mode 100644 index 0000000..4a63d6f --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/bazaar.py @@ -0,0 +1,123 @@ +# The following comment should be removed at some point in the future. +# mypy: disallow-untyped-defs=False + +from __future__ import absolute_import + +import logging +import os + +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.utils.misc import display_path, rmtree +from pip._internal.utils.subprocess import make_command +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.urls import path_to_url +from pip._internal.vcs.versioncontrol import VersionControl, vcs + +if MYPY_CHECK_RUNNING: + from typing import Optional, Tuple + + from pip._internal.utils.misc import HiddenText + from pip._internal.vcs.versioncontrol import AuthInfo, RevOptions + + +logger = logging.getLogger(__name__) + + +class Bazaar(VersionControl): + name = 'bzr' + dirname = '.bzr' + repo_name = 'branch' + schemes = ( + 'bzr', 'bzr+http', 'bzr+https', 'bzr+ssh', 'bzr+sftp', 'bzr+ftp', + 'bzr+lp', + ) + + def __init__(self, *args, **kwargs): + super(Bazaar, self).__init__(*args, **kwargs) + # This is only needed for python <2.7.5 + # Register lp but do not expose as a scheme to support bzr+lp. + if getattr(urllib_parse, 'uses_fragment', None): + urllib_parse.uses_fragment.extend(['lp']) + + @staticmethod + def get_base_rev_args(rev): + return ['-r', rev] + + def export(self, location, url): + # type: (str, HiddenText) -> None + """ + Export the Bazaar repository at the url to the destination location + """ + # Remove the location to make sure Bazaar can export it correctly + if os.path.exists(location): + rmtree(location) + + url, rev_options = self.get_url_rev_options(url) + self.run_command( + make_command('export', location, url, rev_options.to_args()), + show_stdout=False, + ) + + def fetch_new(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + rev_display = rev_options.to_display() + logger.info( + 'Checking out %s%s to %s', + url, + rev_display, + display_path(dest), + ) + cmd_args = ( + make_command('branch', '-q', rev_options.to_args(), url, dest) + ) + self.run_command(cmd_args) + + def switch(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + self.run_command(make_command('switch', url), cwd=dest) + + def update(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + cmd_args = make_command('pull', '-q', rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + @classmethod + def get_url_rev_and_auth(cls, url): + # type: (str) -> Tuple[str, Optional[str], AuthInfo] + # hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it + url, rev, user_pass = super(Bazaar, cls).get_url_rev_and_auth(url) + if url.startswith('ssh://'): + url = 'bzr+' + url + return url, rev, user_pass + + @classmethod + def get_remote_url(cls, location): + urls = cls.run_command( + ['info'], show_stdout=False, stdout_only=True, cwd=location + ) + for line in urls.splitlines(): + line = line.strip() + for x in ('checkout of branch: ', + 'parent branch: '): + if line.startswith(x): + repo = line.split(x)[1] + if cls._is_local_repository(repo): + return path_to_url(repo) + return repo + return None + + @classmethod + def get_revision(cls, location): + revision = cls.run_command( + ['revno'], show_stdout=False, stdout_only=True, cwd=location, + ) + return revision.splitlines()[-1] + + @classmethod + def is_commit_id_equal(cls, dest, name): + """Always assume the versions don't match""" + return False + + +vcs.register(Bazaar) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/git.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/git.py new file mode 100644 index 0000000..4423a91 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/git.py @@ -0,0 +1,460 @@ +# The following comment should be removed at some point in the future. +# mypy: disallow-untyped-defs=False + +from __future__ import absolute_import + +import logging +import os.path +import re + +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.six.moves.urllib import parse as urllib_parse +from pip._vendor.six.moves.urllib import request as urllib_request + +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.utils.misc import display_path, hide_url +from pip._internal.utils.subprocess import make_command +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.vcs.versioncontrol import ( + RemoteNotFoundError, + VersionControl, + find_path_to_setup_from_repo_root, + vcs, +) + +if MYPY_CHECK_RUNNING: + from typing import Optional, Tuple + + from pip._internal.utils.misc import HiddenText + from pip._internal.vcs.versioncontrol import AuthInfo, RevOptions + + +urlsplit = urllib_parse.urlsplit +urlunsplit = urllib_parse.urlunsplit + + +logger = logging.getLogger(__name__) + + +HASH_REGEX = re.compile('^[a-fA-F0-9]{40}$') + + +def looks_like_hash(sha): + return bool(HASH_REGEX.match(sha)) + + +class Git(VersionControl): + name = 'git' + dirname = '.git' + repo_name = 'clone' + schemes = ( + 'git', 'git+http', 'git+https', 'git+ssh', 'git+git', 'git+file', + ) + # Prevent the user's environment variables from interfering with pip: + # https://github.com/pypa/pip/issues/1130 + unset_environ = ('GIT_DIR', 'GIT_WORK_TREE') + default_arg_rev = 'HEAD' + + @staticmethod + def get_base_rev_args(rev): + return [rev] + + def is_immutable_rev_checkout(self, url, dest): + # type: (str, str) -> bool + _, rev_options = self.get_url_rev_options(hide_url(url)) + if not rev_options.rev: + return False + if not self.is_commit_id_equal(dest, rev_options.rev): + # the current commit is different from rev, + # which means rev was something else than a commit hash + return False + # return False in the rare case rev is both a commit hash + # and a tag or a branch; we don't want to cache in that case + # because that branch/tag could point to something else in the future + is_tag_or_branch = bool( + self.get_revision_sha(dest, rev_options.rev)[0] + ) + return not is_tag_or_branch + + def get_git_version(self): + VERSION_PFX = 'git version ' + version = self.run_command( + ['version'], show_stdout=False, stdout_only=True + ) + if version.startswith(VERSION_PFX): + version = version[len(VERSION_PFX):].split()[0] + else: + version = '' + # get first 3 positions of the git version because + # on windows it is x.y.z.windows.t, and this parses as + # LegacyVersion which always smaller than a Version. + version = '.'.join(version.split('.')[:3]) + return parse_version(version) + + @classmethod + def get_current_branch(cls, location): + """ + Return the current branch, or None if HEAD isn't at a branch + (e.g. detached HEAD). + """ + # git-symbolic-ref exits with empty stdout if "HEAD" is a detached + # HEAD rather than a symbolic ref. In addition, the -q causes the + # command to exit with status code 1 instead of 128 in this case + # and to suppress the message to stderr. + args = ['symbolic-ref', '-q', 'HEAD'] + output = cls.run_command( + args, + extra_ok_returncodes=(1, ), + show_stdout=False, + stdout_only=True, + cwd=location, + ) + ref = output.strip() + + if ref.startswith('refs/heads/'): + return ref[len('refs/heads/'):] + + return None + + def export(self, location, url): + # type: (str, HiddenText) -> None + """Export the Git repository at the url to the destination location""" + if not location.endswith('/'): + location = location + '/' + + with TempDirectory(kind="export") as temp_dir: + self.unpack(temp_dir.path, url=url) + self.run_command( + ['checkout-index', '-a', '-f', '--prefix', location], + show_stdout=False, cwd=temp_dir.path + ) + + @classmethod + def get_revision_sha(cls, dest, rev): + """ + Return (sha_or_none, is_branch), where sha_or_none is a commit hash + if the revision names a remote branch or tag, otherwise None. + + Args: + dest: the repository directory. + rev: the revision name. + """ + # Pass rev to pre-filter the list. + output = cls.run_command( + ['show-ref', rev], + cwd=dest, + show_stdout=False, + stdout_only=True, + on_returncode='ignore', + ) + refs = {} + # NOTE: We do not use splitlines here since that would split on other + # unicode separators, which can be maliciously used to install a + # different revision. + for line in output.strip().split("\n"): + line = line.rstrip("\r") + if not line: + continue + try: + sha, ref = line.split(" ", maxsplit=2) + except ValueError: + # Include the offending line to simplify troubleshooting if + # this error ever occurs. + raise ValueError('unexpected show-ref line: {!r}'.format(line)) + + refs[ref] = sha + + branch_ref = 'refs/remotes/origin/{}'.format(rev) + tag_ref = 'refs/tags/{}'.format(rev) + + sha = refs.get(branch_ref) + if sha is not None: + return (sha, True) + + sha = refs.get(tag_ref) + + return (sha, False) + + @classmethod + def _should_fetch(cls, dest, rev): + """ + Return true if rev is a ref or is a commit that we don't have locally. + + Branches and tags are not considered in this method because they are + assumed to be always available locally (which is a normal outcome of + ``git clone`` and ``git fetch --tags``). + """ + if rev.startswith("refs/"): + # Always fetch remote refs. + return True + + if not looks_like_hash(rev): + # Git fetch would fail with abbreviated commits. + return False + + if cls.has_commit(dest, rev): + # Don't fetch if we have the commit locally. + return False + + return True + + @classmethod + def resolve_revision(cls, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> RevOptions + """ + Resolve a revision to a new RevOptions object with the SHA1 of the + branch, tag, or ref if found. + + Args: + rev_options: a RevOptions object. + """ + rev = rev_options.arg_rev + # The arg_rev property's implementation for Git ensures that the + # rev return value is always non-None. + assert rev is not None + + sha, is_branch = cls.get_revision_sha(dest, rev) + + if sha is not None: + rev_options = rev_options.make_new(sha) + rev_options.branch_name = rev if is_branch else None + + return rev_options + + # Do not show a warning for the common case of something that has + # the form of a Git commit hash. + if not looks_like_hash(rev): + logger.warning( + "Did not find branch or tag '%s', assuming revision or ref.", + rev, + ) + + if not cls._should_fetch(dest, rev): + return rev_options + + # fetch the requested revision + cls.run_command( + make_command('fetch', '-q', url, rev_options.to_args()), + cwd=dest, + ) + # Change the revision to the SHA of the ref we fetched + sha = cls.get_revision(dest, rev='FETCH_HEAD') + rev_options = rev_options.make_new(sha) + + return rev_options + + @classmethod + def is_commit_id_equal(cls, dest, name): + """ + Return whether the current commit hash equals the given name. + + Args: + dest: the repository directory. + name: a string name. + """ + if not name: + # Then avoid an unnecessary subprocess call. + return False + + return cls.get_revision(dest) == name + + def fetch_new(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + rev_display = rev_options.to_display() + logger.info('Cloning %s%s to %s', url, rev_display, display_path(dest)) + self.run_command(make_command('clone', '-q', url, dest)) + + if rev_options.rev: + # Then a specific revision was requested. + rev_options = self.resolve_revision(dest, url, rev_options) + branch_name = getattr(rev_options, 'branch_name', None) + if branch_name is None: + # Only do a checkout if the current commit id doesn't match + # the requested revision. + if not self.is_commit_id_equal(dest, rev_options.rev): + cmd_args = make_command( + 'checkout', '-q', rev_options.to_args(), + ) + self.run_command(cmd_args, cwd=dest) + elif self.get_current_branch(dest) != branch_name: + # Then a specific branch was requested, and that branch + # is not yet checked out. + track_branch = 'origin/{}'.format(branch_name) + cmd_args = [ + 'checkout', '-b', branch_name, '--track', track_branch, + ] + self.run_command(cmd_args, cwd=dest) + + #: repo may contain submodules + self.update_submodules(dest) + + def switch(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + self.run_command( + make_command('config', 'remote.origin.url', url), + cwd=dest, + ) + cmd_args = make_command('checkout', '-q', rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + self.update_submodules(dest) + + def update(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + # First fetch changes from the default remote + if self.get_git_version() >= parse_version('1.9.0'): + # fetch tags in addition to everything else + self.run_command(['fetch', '-q', '--tags'], cwd=dest) + else: + self.run_command(['fetch', '-q'], cwd=dest) + # Then reset to wanted revision (maybe even origin/master) + rev_options = self.resolve_revision(dest, url, rev_options) + cmd_args = make_command('reset', '--hard', '-q', rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + #: update submodules + self.update_submodules(dest) + + @classmethod + def get_remote_url(cls, location): + """ + Return URL of the first remote encountered. + + Raises RemoteNotFoundError if the repository does not have a remote + url configured. + """ + # We need to pass 1 for extra_ok_returncodes since the command + # exits with return code 1 if there are no matching lines. + stdout = cls.run_command( + ['config', '--get-regexp', r'remote\..*\.url'], + extra_ok_returncodes=(1, ), + show_stdout=False, + stdout_only=True, + cwd=location, + ) + remotes = stdout.splitlines() + try: + found_remote = remotes[0] + except IndexError: + raise RemoteNotFoundError + + for remote in remotes: + if remote.startswith('remote.origin.url '): + found_remote = remote + break + url = found_remote.split(' ')[1] + return url.strip() + + @classmethod + def has_commit(cls, location, rev): + """ + Check if rev is a commit that is available in the local repository. + """ + try: + cls.run_command( + ['rev-parse', '-q', '--verify', "sha^" + rev], + cwd=location, + log_failed_cmd=False, + ) + except InstallationError: + return False + else: + return True + + @classmethod + def get_revision(cls, location, rev=None): + if rev is None: + rev = 'HEAD' + current_rev = cls.run_command( + ['rev-parse', rev], + show_stdout=False, + stdout_only=True, + cwd=location, + ) + return current_rev.strip() + + @classmethod + def get_subdirectory(cls, location): + """ + Return the path to setup.py, relative to the repo root. + Return None if setup.py is in the repo root. + """ + # find the repo root + git_dir = cls.run_command( + ['rev-parse', '--git-dir'], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + if not os.path.isabs(git_dir): + git_dir = os.path.join(location, git_dir) + repo_root = os.path.abspath(os.path.join(git_dir, '..')) + return find_path_to_setup_from_repo_root(location, repo_root) + + @classmethod + def get_url_rev_and_auth(cls, url): + # type: (str) -> Tuple[str, Optional[str], AuthInfo] + """ + Prefixes stub URLs like 'user@hostname:user/repo.git' with 'ssh://'. + That's required because although they use SSH they sometimes don't + work with a ssh:// scheme (e.g. GitHub). But we need a scheme for + parsing. Hence we remove it again afterwards and return it as a stub. + """ + # Works around an apparent Git bug + # (see https://article.gmane.org/gmane.comp.version-control.git/146500) + scheme, netloc, path, query, fragment = urlsplit(url) + if scheme.endswith('file'): + initial_slashes = path[:-len(path.lstrip('/'))] + newpath = ( + initial_slashes + + urllib_request.url2pathname(path) + .replace('\\', '/').lstrip('/') + ) + after_plus = scheme.find('+') + 1 + url = scheme[:after_plus] + urlunsplit( + (scheme[after_plus:], netloc, newpath, query, fragment), + ) + + if '://' not in url: + assert 'file:' not in url + url = url.replace('git+', 'git+ssh://') + url, rev, user_pass = super(Git, cls).get_url_rev_and_auth(url) + url = url.replace('ssh://', '') + else: + url, rev, user_pass = super(Git, cls).get_url_rev_and_auth(url) + + return url, rev, user_pass + + @classmethod + def update_submodules(cls, location): + if not os.path.exists(os.path.join(location, '.gitmodules')): + return + cls.run_command( + ['submodule', 'update', '--init', '--recursive', '-q'], + cwd=location, + ) + + @classmethod + def get_repository_root(cls, location): + loc = super(Git, cls).get_repository_root(location) + if loc: + return loc + try: + r = cls.run_command( + ['rev-parse', '--show-toplevel'], + cwd=location, + show_stdout=False, + stdout_only=True, + on_returncode='raise', + log_failed_cmd=False, + ) + except BadCommand: + logger.debug("could not determine if %s is under git control " + "because git is not available", location) + return None + except InstallationError: + return None + return os.path.normpath(r.rstrip('\r\n')) + + +vcs.register(Git) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/mercurial.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/mercurial.py new file mode 100644 index 0000000..d2d145f --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/mercurial.py @@ -0,0 +1,172 @@ +# The following comment should be removed at some point in the future. +# mypy: disallow-untyped-defs=False + +from __future__ import absolute_import + +import logging +import os + +from pip._vendor.six.moves import configparser + +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.utils.misc import display_path +from pip._internal.utils.subprocess import make_command +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.urls import path_to_url +from pip._internal.vcs.versioncontrol import ( + VersionControl, + find_path_to_setup_from_repo_root, + vcs, +) + +if MYPY_CHECK_RUNNING: + from pip._internal.utils.misc import HiddenText + from pip._internal.vcs.versioncontrol import RevOptions + + +logger = logging.getLogger(__name__) + + +class Mercurial(VersionControl): + name = 'hg' + dirname = '.hg' + repo_name = 'clone' + schemes = ( + 'hg', 'hg+file', 'hg+http', 'hg+https', 'hg+ssh', 'hg+static-http', + ) + + @staticmethod + def get_base_rev_args(rev): + return [rev] + + def export(self, location, url): + # type: (str, HiddenText) -> None + """Export the Hg repository at the url to the destination location""" + with TempDirectory(kind="export") as temp_dir: + self.unpack(temp_dir.path, url=url) + + self.run_command( + ['archive', location], show_stdout=False, cwd=temp_dir.path + ) + + def fetch_new(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + rev_display = rev_options.to_display() + logger.info( + 'Cloning hg %s%s to %s', + url, + rev_display, + display_path(dest), + ) + self.run_command(make_command('clone', '--noupdate', '-q', url, dest)) + self.run_command( + make_command('update', '-q', rev_options.to_args()), + cwd=dest, + ) + + def switch(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + repo_config = os.path.join(dest, self.dirname, 'hgrc') + config = configparser.RawConfigParser() + try: + config.read(repo_config) + config.set('paths', 'default', url.secret) + with open(repo_config, 'w') as config_file: + config.write(config_file) + except (OSError, configparser.NoSectionError) as exc: + logger.warning( + 'Could not switch Mercurial repository to %s: %s', url, exc, + ) + else: + cmd_args = make_command('update', '-q', rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + def update(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + self.run_command(['pull', '-q'], cwd=dest) + cmd_args = make_command('update', '-q', rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + @classmethod + def get_remote_url(cls, location): + url = cls.run_command( + ['showconfig', 'paths.default'], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + if cls._is_local_repository(url): + url = path_to_url(url) + return url.strip() + + @classmethod + def get_revision(cls, location): + """ + Return the repository-local changeset revision number, as an integer. + """ + current_revision = cls.run_command( + ['parents', '--template={rev}'], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + return current_revision + + @classmethod + def get_requirement_revision(cls, location): + """ + Return the changeset identification hash, as a 40-character + hexadecimal string + """ + current_rev_hash = cls.run_command( + ['parents', '--template={node}'], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + return current_rev_hash + + @classmethod + def is_commit_id_equal(cls, dest, name): + """Always assume the versions don't match""" + return False + + @classmethod + def get_subdirectory(cls, location): + """ + Return the path to setup.py, relative to the repo root. + Return None if setup.py is in the repo root. + """ + # find the repo root + repo_root = cls.run_command( + ['root'], show_stdout=False, stdout_only=True, cwd=location + ).strip() + if not os.path.isabs(repo_root): + repo_root = os.path.abspath(os.path.join(location, repo_root)) + return find_path_to_setup_from_repo_root(location, repo_root) + + @classmethod + def get_repository_root(cls, location): + loc = super(Mercurial, cls).get_repository_root(location) + if loc: + return loc + try: + r = cls.run_command( + ['root'], + cwd=location, + show_stdout=False, + stdout_only=True, + on_returncode='raise', + log_failed_cmd=False, + ) + except BadCommand: + logger.debug("could not determine if %s is under hg control " + "because hg is not available", location) + return None + except InstallationError: + return None + return os.path.normpath(r.rstrip('\r\n')) + + +vcs.register(Mercurial) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/subversion.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/subversion.py new file mode 100644 index 0000000..701f41d --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/subversion.py @@ -0,0 +1,340 @@ +# The following comment should be removed at some point in the future. +# mypy: disallow-untyped-defs=False + +from __future__ import absolute_import + +import logging +import os +import re + +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + display_path, + is_console_interactive, + rmtree, + split_auth_from_netloc, +) +from pip._internal.utils.subprocess import make_command +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.vcs.versioncontrol import VersionControl, vcs + +_svn_xml_url_re = re.compile('url="([^"]+)"') +_svn_rev_re = re.compile(r'committed-rev="(\d+)"') +_svn_info_xml_rev_re = re.compile(r'\s*revision="(\d+)"') +_svn_info_xml_url_re = re.compile(r'(.*)') + + +if MYPY_CHECK_RUNNING: + from typing import Optional, Tuple + + from pip._internal.utils.misc import HiddenText + from pip._internal.utils.subprocess import CommandArgs + from pip._internal.vcs.versioncontrol import AuthInfo, RevOptions + + +logger = logging.getLogger(__name__) + + +class Subversion(VersionControl): + name = 'svn' + dirname = '.svn' + repo_name = 'checkout' + schemes = ('svn', 'svn+ssh', 'svn+http', 'svn+https', 'svn+svn') + + @classmethod + def should_add_vcs_url_prefix(cls, remote_url): + return True + + @staticmethod + def get_base_rev_args(rev): + return ['-r', rev] + + @classmethod + def get_revision(cls, location): + """ + Return the maximum revision for all files under a given location + """ + # Note: taken from setuptools.command.egg_info + revision = 0 + + for base, dirs, _ in os.walk(location): + if cls.dirname not in dirs: + dirs[:] = [] + continue # no sense walking uncontrolled subdirs + dirs.remove(cls.dirname) + entries_fn = os.path.join(base, cls.dirname, 'entries') + if not os.path.exists(entries_fn): + # FIXME: should we warn? + continue + + dirurl, localrev = cls._get_svn_url_rev(base) + + if base == location: + base = dirurl + '/' # save the root url + elif not dirurl or not dirurl.startswith(base): + dirs[:] = [] + continue # not part of the same svn tree, skip it + revision = max(revision, localrev) + return revision + + @classmethod + def get_netloc_and_auth(cls, netloc, scheme): + """ + This override allows the auth information to be passed to svn via the + --username and --password options instead of via the URL. + """ + if scheme == 'ssh': + # The --username and --password options can't be used for + # svn+ssh URLs, so keep the auth information in the URL. + return super(Subversion, cls).get_netloc_and_auth(netloc, scheme) + + return split_auth_from_netloc(netloc) + + @classmethod + def get_url_rev_and_auth(cls, url): + # type: (str) -> Tuple[str, Optional[str], AuthInfo] + # hotfix the URL scheme after removing svn+ from svn+ssh:// readd it + url, rev, user_pass = super(Subversion, cls).get_url_rev_and_auth(url) + if url.startswith('ssh://'): + url = 'svn+' + url + return url, rev, user_pass + + @staticmethod + def make_rev_args(username, password): + # type: (Optional[str], Optional[HiddenText]) -> CommandArgs + extra_args = [] # type: CommandArgs + if username: + extra_args += ['--username', username] + if password: + extra_args += ['--password', password] + + return extra_args + + @classmethod + def get_remote_url(cls, location): + # In cases where the source is in a subdirectory, not alongside + # setup.py we have to look up in the location until we find a real + # setup.py + orig_location = location + while not os.path.exists(os.path.join(location, 'setup.py')): + last_location = location + location = os.path.dirname(location) + if location == last_location: + # We've traversed up to the root of the filesystem without + # finding setup.py + logger.warning( + "Could not find setup.py for directory %s (tried all " + "parent directories)", + orig_location, + ) + return None + + return cls._get_svn_url_rev(location)[0] + + @classmethod + def _get_svn_url_rev(cls, location): + from pip._internal.exceptions import InstallationError + + entries_path = os.path.join(location, cls.dirname, 'entries') + if os.path.exists(entries_path): + with open(entries_path) as f: + data = f.read() + else: # subversion >= 1.7 does not have the 'entries' file + data = '' + + if (data.startswith('8') or + data.startswith('9') or + data.startswith('10')): + data = list(map(str.splitlines, data.split('\n\x0c\n'))) + del data[0][0] # get rid of the '8' + url = data[0][3] + revs = [int(d[9]) for d in data if len(d) > 9 and d[9]] + [0] + elif data.startswith('= 1.7 + # Note that using get_remote_call_options is not necessary here + # because `svn info` is being run against a local directory. + # We don't need to worry about making sure interactive mode + # is being used to prompt for passwords, because passwords + # are only potentially needed for remote server requests. + xml = cls.run_command( + ['info', '--xml', location], + show_stdout=False, + stdout_only=True, + ) + url = _svn_info_xml_url_re.search(xml).group(1) + revs = [ + int(m.group(1)) for m in _svn_info_xml_rev_re.finditer(xml) + ] + except InstallationError: + url, revs = None, [] + + if revs: + rev = max(revs) + else: + rev = 0 + + return url, rev + + @classmethod + def is_commit_id_equal(cls, dest, name): + """Always assume the versions don't match""" + return False + + def __init__(self, use_interactive=None): + # type: (bool) -> None + if use_interactive is None: + use_interactive = is_console_interactive() + self.use_interactive = use_interactive + + # This member is used to cache the fetched version of the current + # ``svn`` client. + # Special value definitions: + # None: Not evaluated yet. + # Empty tuple: Could not parse version. + self._vcs_version = None # type: Optional[Tuple[int, ...]] + + super(Subversion, self).__init__() + + def call_vcs_version(self): + # type: () -> Tuple[int, ...] + """Query the version of the currently installed Subversion client. + + :return: A tuple containing the parts of the version information or + ``()`` if the version returned from ``svn`` could not be parsed. + :raises: BadCommand: If ``svn`` is not installed. + """ + # Example versions: + # svn, version 1.10.3 (r1842928) + # compiled Feb 25 2019, 14:20:39 on x86_64-apple-darwin17.0.0 + # svn, version 1.7.14 (r1542130) + # compiled Mar 28 2018, 08:49:13 on x86_64-pc-linux-gnu + # svn, version 1.12.0-SlikSvn (SlikSvn/1.12.0) + # compiled May 28 2019, 13:44:56 on x86_64-microsoft-windows6.2 + version_prefix = 'svn, version ' + version = self.run_command( + ['--version'], show_stdout=False, stdout_only=True + ) + if not version.startswith(version_prefix): + return () + + version = version[len(version_prefix):].split()[0] + version_list = version.partition('-')[0].split('.') + try: + parsed_version = tuple(map(int, version_list)) + except ValueError: + return () + + return parsed_version + + def get_vcs_version(self): + # type: () -> Tuple[int, ...] + """Return the version of the currently installed Subversion client. + + If the version of the Subversion client has already been queried, + a cached value will be used. + + :return: A tuple containing the parts of the version information or + ``()`` if the version returned from ``svn`` could not be parsed. + :raises: BadCommand: If ``svn`` is not installed. + """ + if self._vcs_version is not None: + # Use cached version, if available. + # If parsing the version failed previously (empty tuple), + # do not attempt to parse it again. + return self._vcs_version + + vcs_version = self.call_vcs_version() + self._vcs_version = vcs_version + return vcs_version + + def get_remote_call_options(self): + # type: () -> CommandArgs + """Return options to be used on calls to Subversion that contact the server. + + These options are applicable for the following ``svn`` subcommands used + in this class. + + - checkout + - export + - switch + - update + + :return: A list of command line arguments to pass to ``svn``. + """ + if not self.use_interactive: + # --non-interactive switch is available since Subversion 0.14.4. + # Subversion < 1.8 runs in interactive mode by default. + return ['--non-interactive'] + + svn_version = self.get_vcs_version() + # By default, Subversion >= 1.8 runs in non-interactive mode if + # stdin is not a TTY. Since that is how pip invokes SVN, in + # call_subprocess(), pip must pass --force-interactive to ensure + # the user can be prompted for a password, if required. + # SVN added the --force-interactive option in SVN 1.8. Since + # e.g. RHEL/CentOS 7, which is supported until 2024, ships with + # SVN 1.7, pip should continue to support SVN 1.7. Therefore, pip + # can't safely add the option if the SVN version is < 1.8 (or unknown). + if svn_version >= (1, 8): + return ['--force-interactive'] + + return [] + + def export(self, location, url): + # type: (str, HiddenText) -> None + """Export the svn repository at the url to the destination location""" + url, rev_options = self.get_url_rev_options(url) + + logger.info('Exporting svn repository %s to %s', url, location) + with indent_log(): + if os.path.exists(location): + # Subversion doesn't like to check out over an existing + # directory --force fixes this, but was only added in svn 1.5 + rmtree(location) + cmd_args = make_command( + 'export', self.get_remote_call_options(), + rev_options.to_args(), url, location, + ) + self.run_command(cmd_args, show_stdout=False) + + def fetch_new(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + rev_display = rev_options.to_display() + logger.info( + 'Checking out %s%s to %s', + url, + rev_display, + display_path(dest), + ) + cmd_args = make_command( + 'checkout', '-q', self.get_remote_call_options(), + rev_options.to_args(), url, dest, + ) + self.run_command(cmd_args) + + def switch(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + cmd_args = make_command( + 'switch', self.get_remote_call_options(), rev_options.to_args(), + url, dest, + ) + self.run_command(cmd_args) + + def update(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + cmd_args = make_command( + 'update', self.get_remote_call_options(), rev_options.to_args(), + dest, + ) + self.run_command(cmd_args) + + +vcs.register(Subversion) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/versioncontrol.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/versioncontrol.py new file mode 100644 index 0000000..0e807a2 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/vcs/versioncontrol.py @@ -0,0 +1,735 @@ +"""Handles all VCS (version control) support""" + +from __future__ import absolute_import + +import errno +import logging +import os +import shutil +import sys + +from pip._vendor import pkg_resources +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.utils.compat import samefile +from pip._internal.utils.misc import ( + ask_path_exists, + backup_dir, + display_path, + hide_url, + hide_value, + rmtree, +) +from pip._internal.utils.subprocess import call_subprocess, make_command +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.urls import get_url_scheme + +if MYPY_CHECK_RUNNING: + from typing import ( + Any, + Dict, + Iterable, + Iterator, + List, + Mapping, + Optional, + Text, + Tuple, + Type, + Union, + ) + + from pip._internal.cli.spinners import SpinnerInterface + from pip._internal.utils.misc import HiddenText + from pip._internal.utils.subprocess import CommandArgs + + AuthInfo = Tuple[Optional[str], Optional[str]] + + +__all__ = ['vcs'] + + +logger = logging.getLogger(__name__) + + +def is_url(name): + # type: (Union[str, Text]) -> bool + """ + Return true if the name looks like a URL. + """ + scheme = get_url_scheme(name) + if scheme is None: + return False + return scheme in ['http', 'https', 'file', 'ftp'] + vcs.all_schemes + + +def make_vcs_requirement_url(repo_url, rev, project_name, subdir=None): + # type: (str, str, str, Optional[str]) -> str + """ + Return the URL for a VCS requirement. + + Args: + repo_url: the remote VCS url, with any needed VCS prefix (e.g. "git+"). + project_name: the (unescaped) project name. + """ + egg_project_name = pkg_resources.to_filename(project_name) + req = '{}@{}#egg={}'.format(repo_url, rev, egg_project_name) + if subdir: + req += '&subdirectory={}'.format(subdir) + + return req + + +def find_path_to_setup_from_repo_root(location, repo_root): + # type: (str, str) -> Optional[str] + """ + Find the path to `setup.py` by searching up the filesystem from `location`. + Return the path to `setup.py` relative to `repo_root`. + Return None if `setup.py` is in `repo_root` or cannot be found. + """ + # find setup.py + orig_location = location + while not os.path.exists(os.path.join(location, 'setup.py')): + last_location = location + location = os.path.dirname(location) + if location == last_location: + # We've traversed up to the root of the filesystem without + # finding setup.py + logger.warning( + "Could not find setup.py for directory %s (tried all " + "parent directories)", + orig_location, + ) + return None + + if samefile(repo_root, location): + return None + + return os.path.relpath(location, repo_root) + + +class RemoteNotFoundError(Exception): + pass + + +class RevOptions(object): + + """ + Encapsulates a VCS-specific revision to install, along with any VCS + install options. + + Instances of this class should be treated as if immutable. + """ + + def __init__( + self, + vc_class, # type: Type[VersionControl] + rev=None, # type: Optional[str] + extra_args=None, # type: Optional[CommandArgs] + ): + # type: (...) -> None + """ + Args: + vc_class: a VersionControl subclass. + rev: the name of the revision to install. + extra_args: a list of extra options. + """ + if extra_args is None: + extra_args = [] + + self.extra_args = extra_args + self.rev = rev + self.vc_class = vc_class + self.branch_name = None # type: Optional[str] + + def __repr__(self): + # type: () -> str + return ''.format(self.vc_class.name, self.rev) + + @property + def arg_rev(self): + # type: () -> Optional[str] + if self.rev is None: + return self.vc_class.default_arg_rev + + return self.rev + + def to_args(self): + # type: () -> CommandArgs + """ + Return the VCS-specific command arguments. + """ + args = [] # type: CommandArgs + rev = self.arg_rev + if rev is not None: + args += self.vc_class.get_base_rev_args(rev) + args += self.extra_args + + return args + + def to_display(self): + # type: () -> str + if not self.rev: + return '' + + return ' (to revision {})'.format(self.rev) + + def make_new(self, rev): + # type: (str) -> RevOptions + """ + Make a copy of the current instance, but with a new rev. + + Args: + rev: the name of the revision for the new object. + """ + return self.vc_class.make_rev_options(rev, extra_args=self.extra_args) + + +class VcsSupport(object): + _registry = {} # type: Dict[str, VersionControl] + schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp', 'svn'] + + def __init__(self): + # type: () -> None + # Register more schemes with urlparse for various version control + # systems + urllib_parse.uses_netloc.extend(self.schemes) + # Python >= 2.7.4, 3.3 doesn't have uses_fragment + if getattr(urllib_parse, 'uses_fragment', None): + urllib_parse.uses_fragment.extend(self.schemes) + super(VcsSupport, self).__init__() + + def __iter__(self): + # type: () -> Iterator[str] + return self._registry.__iter__() + + @property + def backends(self): + # type: () -> List[VersionControl] + return list(self._registry.values()) + + @property + def dirnames(self): + # type: () -> List[str] + return [backend.dirname for backend in self.backends] + + @property + def all_schemes(self): + # type: () -> List[str] + schemes = [] # type: List[str] + for backend in self.backends: + schemes.extend(backend.schemes) + return schemes + + def register(self, cls): + # type: (Type[VersionControl]) -> None + if not hasattr(cls, 'name'): + logger.warning('Cannot register VCS %s', cls.__name__) + return + if cls.name not in self._registry: + self._registry[cls.name] = cls() + logger.debug('Registered VCS backend: %s', cls.name) + + def unregister(self, name): + # type: (str) -> None + if name in self._registry: + del self._registry[name] + + def get_backend_for_dir(self, location): + # type: (str) -> Optional[VersionControl] + """ + Return a VersionControl object if a repository of that type is found + at the given directory. + """ + vcs_backends = {} + for vcs_backend in self._registry.values(): + repo_path = vcs_backend.get_repository_root(location) + if not repo_path: + continue + logger.debug('Determine that %s uses VCS: %s', + location, vcs_backend.name) + vcs_backends[repo_path] = vcs_backend + + if not vcs_backends: + return None + + # Choose the VCS in the inner-most directory. Since all repository + # roots found here would be either `location` or one of its + # parents, the longest path should have the most path components, + # i.e. the backend representing the inner-most repository. + inner_most_repo_path = max(vcs_backends, key=len) + return vcs_backends[inner_most_repo_path] + + def get_backend_for_scheme(self, scheme): + # type: (str) -> Optional[VersionControl] + """ + Return a VersionControl object or None. + """ + for vcs_backend in self._registry.values(): + if scheme in vcs_backend.schemes: + return vcs_backend + return None + + def get_backend(self, name): + # type: (str) -> Optional[VersionControl] + """ + Return a VersionControl object or None. + """ + name = name.lower() + return self._registry.get(name) + + +vcs = VcsSupport() + + +class VersionControl(object): + name = '' + dirname = '' + repo_name = '' + # List of supported schemes for this Version Control + schemes = () # type: Tuple[str, ...] + # Iterable of environment variable names to pass to call_subprocess(). + unset_environ = () # type: Tuple[str, ...] + default_arg_rev = None # type: Optional[str] + + @classmethod + def should_add_vcs_url_prefix(cls, remote_url): + # type: (str) -> bool + """ + Return whether the vcs prefix (e.g. "git+") should be added to a + repository's remote url when used in a requirement. + """ + return not remote_url.lower().startswith('{}:'.format(cls.name)) + + @classmethod + def get_subdirectory(cls, location): + # type: (str) -> Optional[str] + """ + Return the path to setup.py, relative to the repo root. + Return None if setup.py is in the repo root. + """ + return None + + @classmethod + def get_requirement_revision(cls, repo_dir): + # type: (str) -> str + """ + Return the revision string that should be used in a requirement. + """ + return cls.get_revision(repo_dir) + + @classmethod + def get_src_requirement(cls, repo_dir, project_name): + # type: (str, str) -> Optional[str] + """ + Return the requirement string to use to redownload the files + currently at the given repository directory. + + Args: + project_name: the (unescaped) project name. + + The return value has a form similar to the following: + + {repository_url}@{revision}#egg={project_name} + """ + repo_url = cls.get_remote_url(repo_dir) + if repo_url is None: + return None + + if cls.should_add_vcs_url_prefix(repo_url): + repo_url = '{}+{}'.format(cls.name, repo_url) + + revision = cls.get_requirement_revision(repo_dir) + subdir = cls.get_subdirectory(repo_dir) + req = make_vcs_requirement_url(repo_url, revision, project_name, + subdir=subdir) + + return req + + @staticmethod + def get_base_rev_args(rev): + # type: (str) -> List[str] + """ + Return the base revision arguments for a vcs command. + + Args: + rev: the name of a revision to install. Cannot be None. + """ + raise NotImplementedError + + def is_immutable_rev_checkout(self, url, dest): + # type: (str, str) -> bool + """ + Return true if the commit hash checked out at dest matches + the revision in url. + + Always return False, if the VCS does not support immutable commit + hashes. + + This method does not check if there are local uncommitted changes + in dest after checkout, as pip currently has no use case for that. + """ + return False + + @classmethod + def make_rev_options(cls, rev=None, extra_args=None): + # type: (Optional[str], Optional[CommandArgs]) -> RevOptions + """ + Return a RevOptions object. + + Args: + rev: the name of a revision to install. + extra_args: a list of extra options. + """ + return RevOptions(cls, rev, extra_args=extra_args) + + @classmethod + def _is_local_repository(cls, repo): + # type: (str) -> bool + """ + posix absolute paths start with os.path.sep, + win32 ones start with drive (like c:\\folder) + """ + drive, tail = os.path.splitdrive(repo) + return repo.startswith(os.path.sep) or bool(drive) + + def export(self, location, url): + # type: (str, HiddenText) -> None + """ + Export the repository at the url to the destination location + i.e. only download the files, without vcs informations + + :param url: the repository URL starting with a vcs prefix. + """ + raise NotImplementedError + + @classmethod + def get_netloc_and_auth(cls, netloc, scheme): + # type: (str, str) -> Tuple[str, Tuple[Optional[str], Optional[str]]] + """ + Parse the repository URL's netloc, and return the new netloc to use + along with auth information. + + Args: + netloc: the original repository URL netloc. + scheme: the repository URL's scheme without the vcs prefix. + + This is mainly for the Subversion class to override, so that auth + information can be provided via the --username and --password options + instead of through the URL. For other subclasses like Git without + such an option, auth information must stay in the URL. + + Returns: (netloc, (username, password)). + """ + return netloc, (None, None) + + @classmethod + def get_url_rev_and_auth(cls, url): + # type: (str) -> Tuple[str, Optional[str], AuthInfo] + """ + Parse the repository URL to use, and return the URL, revision, + and auth info to use. + + Returns: (url, rev, (username, password)). + """ + scheme, netloc, path, query, frag = urllib_parse.urlsplit(url) + if '+' not in scheme: + raise ValueError( + "Sorry, {!r} is a malformed VCS url. " + "The format is +://, " + "e.g. svn+http://myrepo/svn/MyApp#egg=MyApp".format(url) + ) + # Remove the vcs prefix. + scheme = scheme.split('+', 1)[1] + netloc, user_pass = cls.get_netloc_and_auth(netloc, scheme) + rev = None + if '@' in path: + path, rev = path.rsplit('@', 1) + if not rev: + raise InstallationError( + "The URL {!r} has an empty revision (after @) " + "which is not supported. Include a revision after @ " + "or remove @ from the URL.".format(url) + ) + url = urllib_parse.urlunsplit((scheme, netloc, path, query, '')) + return url, rev, user_pass + + @staticmethod + def make_rev_args(username, password): + # type: (Optional[str], Optional[HiddenText]) -> CommandArgs + """ + Return the RevOptions "extra arguments" to use in obtain(). + """ + return [] + + def get_url_rev_options(self, url): + # type: (HiddenText) -> Tuple[HiddenText, RevOptions] + """ + Return the URL and RevOptions object to use in obtain() and in + some cases export(), as a tuple (url, rev_options). + """ + secret_url, rev, user_pass = self.get_url_rev_and_auth(url.secret) + username, secret_password = user_pass + password = None # type: Optional[HiddenText] + if secret_password is not None: + password = hide_value(secret_password) + extra_args = self.make_rev_args(username, password) + rev_options = self.make_rev_options(rev, extra_args=extra_args) + + return hide_url(secret_url), rev_options + + @staticmethod + def normalize_url(url): + # type: (str) -> str + """ + Normalize a URL for comparison by unquoting it and removing any + trailing slash. + """ + return urllib_parse.unquote(url).rstrip('/') + + @classmethod + def compare_urls(cls, url1, url2): + # type: (str, str) -> bool + """ + Compare two repo URLs for identity, ignoring incidental differences. + """ + return (cls.normalize_url(url1) == cls.normalize_url(url2)) + + def fetch_new(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + """ + Fetch a revision from a repository, in the case that this is the + first fetch from the repository. + + Args: + dest: the directory to fetch the repository to. + rev_options: a RevOptions object. + """ + raise NotImplementedError + + def switch(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + """ + Switch the repo at ``dest`` to point to ``URL``. + + Args: + rev_options: a RevOptions object. + """ + raise NotImplementedError + + def update(self, dest, url, rev_options): + # type: (str, HiddenText, RevOptions) -> None + """ + Update an already-existing repo to the given ``rev_options``. + + Args: + rev_options: a RevOptions object. + """ + raise NotImplementedError + + @classmethod + def is_commit_id_equal(cls, dest, name): + # type: (str, Optional[str]) -> bool + """ + Return whether the id of the current commit equals the given name. + + Args: + dest: the repository directory. + name: a string name. + """ + raise NotImplementedError + + def obtain(self, dest, url): + # type: (str, HiddenText) -> None + """ + Install or update in editable mode the package represented by this + VersionControl object. + + :param dest: the repository directory in which to install or update. + :param url: the repository URL starting with a vcs prefix. + """ + url, rev_options = self.get_url_rev_options(url) + + if not os.path.exists(dest): + self.fetch_new(dest, url, rev_options) + return + + rev_display = rev_options.to_display() + if self.is_repository_directory(dest): + existing_url = self.get_remote_url(dest) + if self.compare_urls(existing_url, url.secret): + logger.debug( + '%s in %s exists, and has correct URL (%s)', + self.repo_name.title(), + display_path(dest), + url, + ) + if not self.is_commit_id_equal(dest, rev_options.rev): + logger.info( + 'Updating %s %s%s', + display_path(dest), + self.repo_name, + rev_display, + ) + self.update(dest, url, rev_options) + else: + logger.info('Skipping because already up-to-date.') + return + + logger.warning( + '%s %s in %s exists with URL %s', + self.name, + self.repo_name, + display_path(dest), + existing_url, + ) + prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ', + ('s', 'i', 'w', 'b')) + else: + logger.warning( + 'Directory %s already exists, and is not a %s %s.', + dest, + self.name, + self.repo_name, + ) + # https://github.com/python/mypy/issues/1174 + prompt = ('(i)gnore, (w)ipe, (b)ackup ', # type: ignore + ('i', 'w', 'b')) + + logger.warning( + 'The plan is to install the %s repository %s', + self.name, + url, + ) + response = ask_path_exists('What to do? {}'.format( + prompt[0]), prompt[1]) + + if response == 'a': + sys.exit(-1) + + if response == 'w': + logger.warning('Deleting %s', display_path(dest)) + rmtree(dest) + self.fetch_new(dest, url, rev_options) + return + + if response == 'b': + dest_dir = backup_dir(dest) + logger.warning( + 'Backing up %s to %s', display_path(dest), dest_dir, + ) + shutil.move(dest, dest_dir) + self.fetch_new(dest, url, rev_options) + return + + # Do nothing if the response is "i". + if response == 's': + logger.info( + 'Switching %s %s to %s%s', + self.repo_name, + display_path(dest), + url, + rev_display, + ) + self.switch(dest, url, rev_options) + + def unpack(self, location, url): + # type: (str, HiddenText) -> None + """ + Clean up current location and download the url repository + (and vcs infos) into location + + :param url: the repository URL starting with a vcs prefix. + """ + if os.path.exists(location): + rmtree(location) + self.obtain(location, url=url) + + @classmethod + def get_remote_url(cls, location): + # type: (str) -> str + """ + Return the url used at location + + Raises RemoteNotFoundError if the repository does not have a remote + url configured. + """ + raise NotImplementedError + + @classmethod + def get_revision(cls, location): + # type: (str) -> str + """ + Return the current commit id of the files at the given location. + """ + raise NotImplementedError + + @classmethod + def run_command( + cls, + cmd, # type: Union[List[str], CommandArgs] + show_stdout=True, # type: bool + cwd=None, # type: Optional[str] + on_returncode='raise', # type: str + extra_ok_returncodes=None, # type: Optional[Iterable[int]] + command_desc=None, # type: Optional[str] + extra_environ=None, # type: Optional[Mapping[str, Any]] + spinner=None, # type: Optional[SpinnerInterface] + log_failed_cmd=True, # type: bool + stdout_only=False, # type: bool + ): + # type: (...) -> Text + """ + Run a VCS subcommand + This is simply a wrapper around call_subprocess that adds the VCS + command name, and checks that the VCS is available + """ + cmd = make_command(cls.name, *cmd) + try: + return call_subprocess(cmd, show_stdout, cwd, + on_returncode=on_returncode, + extra_ok_returncodes=extra_ok_returncodes, + command_desc=command_desc, + extra_environ=extra_environ, + unset_environ=cls.unset_environ, + spinner=spinner, + log_failed_cmd=log_failed_cmd, + stdout_only=stdout_only) + except OSError as e: + # errno.ENOENT = no such file or directory + # In other words, the VCS executable isn't available + if e.errno == errno.ENOENT: + raise BadCommand( + 'Cannot find command {cls.name!r} - do you have ' + '{cls.name!r} installed and in your ' + 'PATH?'.format(**locals())) + else: + raise # re-raise exception if a different error occurred + + @classmethod + def is_repository_directory(cls, path): + # type: (str) -> bool + """ + Return whether a directory path is a repository directory. + """ + logger.debug('Checking in %s for %s (%s)...', + path, cls.dirname, cls.name) + return os.path.exists(os.path.join(path, cls.dirname)) + + @classmethod + def get_repository_root(cls, location): + # type: (str) -> Optional[str] + """ + Return the "root" (top-level) directory controlled by the vcs, + or `None` if the directory is not in any. + + It is meant to be overridden to implement smarter detection + mechanisms for specific vcs. + + This can do more than is_repository_directory() alone. For + example, the Git override checks that Git is actually available. + """ + if cls.is_repository_directory(location): + return location + return None diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/wheel_builder.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/wheel_builder.py new file mode 100644 index 0000000..f7e15af --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_internal/wheel_builder.py @@ -0,0 +1,363 @@ +"""Orchestrator for building wheels from InstallRequirements. +""" + +import logging +import os.path +import re +import shutil +import zipfile + +from pip._vendor.packaging.utils import canonicalize_name, canonicalize_version +from pip._vendor.packaging.version import InvalidVersion, Version +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.pkg_resources import Distribution + +from pip._internal.exceptions import InvalidWheelFilename, UnsupportedWheel +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.operations.build.wheel import build_wheel_pep517 +from pip._internal.operations.build.wheel_legacy import build_wheel_legacy +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ensure_dir, hash_file, is_wheel_installed +from pip._internal.utils.setuptools_build import make_setuptools_clean_args +from pip._internal.utils.subprocess import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.urls import path_to_url +from pip._internal.utils.wheel import pkg_resources_distribution_for_wheel +from pip._internal.vcs import vcs + +if MYPY_CHECK_RUNNING: + from typing import Any, Callable, Iterable, List, Optional, Tuple + + from pip._internal.cache import WheelCache + from pip._internal.req.req_install import InstallRequirement + + BinaryAllowedPredicate = Callable[[InstallRequirement], bool] + BuildResult = Tuple[List[InstallRequirement], List[InstallRequirement]] + +logger = logging.getLogger(__name__) + +_egg_info_re = re.compile(r'([a-z0-9_.]+)-([a-z0-9_.!+-]+)', re.IGNORECASE) + + +def _contains_egg_info(s): + # type: (str) -> bool + """Determine whether the string looks like an egg_info. + + :param s: The string to parse. E.g. foo-2.1 + """ + return bool(_egg_info_re.search(s)) + + +def _should_build( + req, # type: InstallRequirement + need_wheel, # type: bool + check_binary_allowed, # type: BinaryAllowedPredicate +): + # type: (...) -> bool + """Return whether an InstallRequirement should be built into a wheel.""" + if req.constraint: + # never build requirements that are merely constraints + return False + if req.is_wheel: + if need_wheel: + logger.info( + 'Skipping %s, due to already being wheel.', req.name, + ) + return False + + if need_wheel: + # i.e. pip wheel, not pip install + return True + + # From this point, this concerns the pip install command only + # (need_wheel=False). + + if req.editable or not req.source_dir: + return False + + if not check_binary_allowed(req): + logger.info( + "Skipping wheel build for %s, due to binaries " + "being disabled for it.", req.name, + ) + return False + + if not req.use_pep517 and not is_wheel_installed(): + # we don't build legacy requirements if wheel is not installed + logger.info( + "Using legacy 'setup.py install' for %s, " + "since package 'wheel' is not installed.", req.name, + ) + return False + + return True + + +def should_build_for_wheel_command( + req, # type: InstallRequirement +): + # type: (...) -> bool + return _should_build( + req, need_wheel=True, check_binary_allowed=_always_true + ) + + +def should_build_for_install_command( + req, # type: InstallRequirement + check_binary_allowed, # type: BinaryAllowedPredicate +): + # type: (...) -> bool + return _should_build( + req, need_wheel=False, check_binary_allowed=check_binary_allowed + ) + + +def _should_cache( + req, # type: InstallRequirement +): + # type: (...) -> Optional[bool] + """ + Return whether a built InstallRequirement can be stored in the persistent + wheel cache, assuming the wheel cache is available, and _should_build() + has determined a wheel needs to be built. + """ + if req.editable or not req.source_dir: + # never cache editable requirements + return False + + if req.link and req.link.is_vcs: + # VCS checkout. Do not cache + # unless it points to an immutable commit hash. + assert not req.editable + assert req.source_dir + vcs_backend = vcs.get_backend_for_scheme(req.link.scheme) + assert vcs_backend + if vcs_backend.is_immutable_rev_checkout(req.link.url, req.source_dir): + return True + return False + + assert req.link + base, ext = req.link.splitext() + if _contains_egg_info(base): + return True + + # Otherwise, do not cache. + return False + + +def _get_cache_dir( + req, # type: InstallRequirement + wheel_cache, # type: WheelCache +): + # type: (...) -> str + """Return the persistent or temporary cache directory where the built + wheel need to be stored. + """ + cache_available = bool(wheel_cache.cache_dir) + assert req.link + if cache_available and _should_cache(req): + cache_dir = wheel_cache.get_path_for_link(req.link) + else: + cache_dir = wheel_cache.get_ephem_path_for_link(req.link) + return cache_dir + + +def _always_true(_): + # type: (Any) -> bool + return True + + +def _get_metadata_version(dist): + # type: (Distribution) -> Optional[Version] + for line in dist.get_metadata_lines(dist.PKG_INFO): + if line.lower().startswith("metadata-version:"): + value = line.split(":", 1)[-1].strip() + try: + return Version(value) + except InvalidVersion: + msg = "Invalid Metadata-Version: {}".format(value) + raise UnsupportedWheel(msg) + raise UnsupportedWheel("Missing Metadata-Version") + + +def _verify_one(req, wheel_path): + # type: (InstallRequirement, str) -> None + canonical_name = canonicalize_name(req.name) + w = Wheel(os.path.basename(wheel_path)) + if canonicalize_name(w.name) != canonical_name: + raise InvalidWheelFilename( + "Wheel has unexpected file name: expected {!r}, " + "got {!r}".format(canonical_name, w.name), + ) + with zipfile.ZipFile(wheel_path, allowZip64=True) as zf: + dist = pkg_resources_distribution_for_wheel( + zf, canonical_name, wheel_path, + ) + if canonicalize_version(dist.version) != canonicalize_version(w.version): + raise InvalidWheelFilename( + "Wheel has unexpected file name: expected {!r}, " + "got {!r}".format(dist.version, w.version), + ) + if (_get_metadata_version(dist) >= Version("1.2") + and not isinstance(parse_version(dist.version), Version)): + raise UnsupportedWheel( + "Metadata 1.2 mandates PEP 440 version, " + "but {!r} is not".format(dist.version) + ) + + +def _build_one( + req, # type: InstallRequirement + output_dir, # type: str + verify, # type: bool + build_options, # type: List[str] + global_options, # type: List[str] +): + # type: (...) -> Optional[str] + """Build one wheel. + + :return: The filename of the built wheel, or None if the build failed. + """ + try: + ensure_dir(output_dir) + except OSError as e: + logger.warning( + "Building wheel for %s failed: %s", + req.name, e, + ) + return None + + # Install build deps into temporary directory (PEP 518) + with req.build_env: + wheel_path = _build_one_inside_env( + req, output_dir, build_options, global_options + ) + if wheel_path and verify: + try: + _verify_one(req, wheel_path) + except (InvalidWheelFilename, UnsupportedWheel) as e: + logger.warning("Built wheel for %s is invalid: %s", req.name, e) + return None + return wheel_path + + +def _build_one_inside_env( + req, # type: InstallRequirement + output_dir, # type: str + build_options, # type: List[str] + global_options, # type: List[str] +): + # type: (...) -> Optional[str] + with TempDirectory(kind="wheel") as temp_dir: + assert req.name + if req.use_pep517: + assert req.metadata_directory + wheel_path = build_wheel_pep517( + name=req.name, + backend=req.pep517_backend, + metadata_directory=req.metadata_directory, + build_options=build_options, + tempd=temp_dir.path, + ) + else: + wheel_path = build_wheel_legacy( + name=req.name, + setup_py_path=req.setup_py_path, + source_dir=req.unpacked_source_directory, + global_options=global_options, + build_options=build_options, + tempd=temp_dir.path, + ) + + if wheel_path is not None: + wheel_name = os.path.basename(wheel_path) + dest_path = os.path.join(output_dir, wheel_name) + try: + wheel_hash, length = hash_file(wheel_path) + shutil.move(wheel_path, dest_path) + logger.info('Created wheel for %s: ' + 'filename=%s size=%d sha256=%s', + req.name, wheel_name, length, + wheel_hash.hexdigest()) + logger.info('Stored in directory: %s', output_dir) + return dest_path + except Exception as e: + logger.warning( + "Building wheel for %s failed: %s", + req.name, e, + ) + # Ignore return, we can't do anything else useful. + if not req.use_pep517: + _clean_one_legacy(req, global_options) + return None + + +def _clean_one_legacy(req, global_options): + # type: (InstallRequirement, List[str]) -> bool + clean_args = make_setuptools_clean_args( + req.setup_py_path, + global_options=global_options, + ) + + logger.info('Running setup.py clean for %s', req.name) + try: + call_subprocess(clean_args, cwd=req.source_dir) + return True + except Exception: + logger.error('Failed cleaning build dir for %s', req.name) + return False + + +def build( + requirements, # type: Iterable[InstallRequirement] + wheel_cache, # type: WheelCache + verify, # type: bool + build_options, # type: List[str] + global_options, # type: List[str] +): + # type: (...) -> BuildResult + """Build wheels. + + :return: The list of InstallRequirement that succeeded to build and + the list of InstallRequirement that failed to build. + """ + if not requirements: + return [], [] + + # Build the wheels. + logger.info( + 'Building wheels for collected packages: %s', + ', '.join(req.name for req in requirements), # type: ignore + ) + + with indent_log(): + build_successes, build_failures = [], [] + for req in requirements: + cache_dir = _get_cache_dir(req, wheel_cache) + wheel_file = _build_one( + req, cache_dir, verify, build_options, global_options + ) + if wheel_file: + # Update the link for this. + req.link = Link(path_to_url(wheel_file)) + req.local_file_path = req.link.file_path + assert req.link.is_wheel + build_successes.append(req) + else: + build_failures.append(req) + + # notify success/failure + if build_successes: + logger.info( + 'Successfully built %s', + ' '.join([req.name for req in build_successes]), # type: ignore + ) + if build_failures: + logger.info( + 'Failed to build %s', + ' '.join([req.name for req in build_failures]), # type: ignore + ) + # Return a list of requirements that failed to build + return build_successes, build_failures diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_vendor/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_vendor/__init__.py new file mode 100644 index 0000000..d4e20fe --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_vendor/__init__.py @@ -0,0 +1,123 @@ +""" +pip._vendor is for vendoring dependencies of pip to prevent needing pip to +depend on something external. + +Files inside of pip._vendor should be considered immutable and should only be +updated to versions from upstream. +""" +from __future__ import absolute_import + +import glob +import os.path +import sys + +# Downstream redistributors which have debundled our dependencies should also +# patch this value to be true. This will trigger the additional patching +# to cause things like "six" to be available as pip. +DEBUNDLED = True + +# By default, look in this directory for a bunch of .whl files which we will +# add to the beginning of sys.path before attempting to import anything. This +# is done to support downstream re-distributors like Debian and Fedora who +# wish to create their own Wheels for our dependencies to aid in debundling. +prefix = getattr(sys, "base_prefix", sys.prefix) +if prefix.startswith('/usr/lib/pypy'): + prefix = '/usr' +WHEEL_DIR = os.path.abspath(os.path.join(prefix, 'share', 'python-wheels')) + + +# Define a small helper function to alias our vendored modules to the real ones +# if the vendored ones do not exist. This idea of this was taken from +# https://github.com/kennethreitz/requests/pull/2567. +def vendored(modulename): + vendored_name = "{0}.{1}".format(__name__, modulename) + + try: + __import__(modulename, globals(), locals(), level=0) + except ImportError: + # We can just silently allow import failures to pass here. If we + # got to this point it means that ``import pip._vendor.whatever`` + # failed and so did ``import whatever``. Since we're importing this + # upfront in an attempt to alias imports, not erroring here will + # just mean we get a regular import error whenever pip *actually* + # tries to import one of these modules to use it, which actually + # gives us a better error message than we would have otherwise + # gotten. + pass + else: + sys.modules[vendored_name] = sys.modules[modulename] + base, head = vendored_name.rsplit(".", 1) + setattr(sys.modules[base], head, sys.modules[modulename]) + + +# If we're operating in a debundled setup, then we want to go ahead and trigger +# the aliasing of our vendored libraries as well as looking for wheels to add +# to our sys.path. This will cause all of this code to be a no-op typically +# however downstream redistributors can enable it in a consistent way across +# all platforms. +if DEBUNDLED: + # Actually look inside of WHEEL_DIR to find .whl files and add them to the + # front of our sys.path. + sys.path[:] = [fn for fn in glob.iglob(os.path.join(WHEEL_DIR, '*.whl')) + if not (os.path.basename(fn).startswith('wheel') or + os.path.basename(fn).startswith('pip'))] + sys.path + + # Actually alias all of our vendored dependencies. + vendored("appdirs") + vendored("cachecontrol") + vendored("certifi") + vendored("colorama") + vendored("contextlib2") + vendored("distlib") + vendored("distro") + vendored("html5lib") + vendored("six") + vendored("six.moves") + vendored("six.moves.urllib") + vendored("six.moves.urllib.parse") + vendored("packaging") + vendored("packaging.version") + vendored("packaging.specifiers") + vendored("pep517") + vendored("pkg_resources") + vendored("progress") + vendored("retrying") + vendored("requests") + vendored("requests.exceptions") + vendored("requests.packages") + vendored("requests.packages.urllib3") + vendored("requests.packages.urllib3._collections") + vendored("requests.packages.urllib3.connection") + vendored("requests.packages.urllib3.connectionpool") + vendored("requests.packages.urllib3.contrib") + vendored("requests.packages.urllib3.contrib.ntlmpool") + vendored("requests.packages.urllib3.contrib.pyopenssl") + vendored("requests.packages.urllib3.exceptions") + vendored("requests.packages.urllib3.fields") + vendored("requests.packages.urllib3.filepost") + vendored("requests.packages.urllib3.packages") + try: + vendored("requests.packages.urllib3.packages.ordered_dict") + vendored("requests.packages.urllib3.packages.six") + except ImportError: + # Debian already unbundles these from requests. + pass + vendored("requests.packages.urllib3.packages.ssl_match_hostname") + vendored("requests.packages.urllib3.packages.ssl_match_hostname." + "_implementation") + vendored("requests.packages.urllib3.poolmanager") + vendored("requests.packages.urllib3.request") + vendored("requests.packages.urllib3.response") + vendored("requests.packages.urllib3.util") + vendored("requests.packages.urllib3.util.connection") + vendored("requests.packages.urllib3.util.request") + vendored("requests.packages.urllib3.util.response") + vendored("requests.packages.urllib3.util.retry") + vendored("requests.packages.urllib3.util.ssl_") + vendored("requests.packages.urllib3.util.timeout") + vendored("requests.packages.urllib3.util.url") + vendored("resolvelib") + vendored("toml") + vendored("toml.encoder") + vendored("toml.decoder") + vendored("urllib3") diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_vendor/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_vendor/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bd73a63f5b3014a3acf5a01111c4f8cf633bcd1 GIT binary patch literal 3339 zcmbW3TXWnr6o4h$>%C+*P1E#Vz|aCsFW!{iXbGjX2?H~oK5!X^9l+yQO6=6OjHGS5 zZt|4!1~cU!WFPr2`~nScJoTL?9y%P^N(eC7GI+=Oq@%OP@;OIG4tu>0f-BzqJv=jq z&~JLM_iDl5Hr!&xLWrONBA8ey&a8ojb>B|yfnCuVG%C6SmpFqaZBdsrsJq_YvIlM2 z-tG{0jQPi;38TjP)ONROd$dhjq&>FBcrZ;mWa=pz9H7l-7XOxXN$)A5_V$d?oF>y_ zYmArB76!XhN0DxcP3-TjMMMvf16vqt&KMpvoHaaTIA?g+@QC42!()cW4Nn-JG(2Va zis7qsdO4*; ztJUI8t?jYg6D*@L)>HJcq&yE(ztj0BNx@2zi-b^PZ1>3`X2X zvVw7W|8q695(*l?d#omp%U*vdct1^6`o*Xim5v?`8X^ukEqldC#w@@1D5f+O5!NQn zYW*sCOqiegladQDlcfGlR zj@QJCXajGzh(j7<>uYP%+O%c6(y)%B4SPp-%Z3;th@pGGY(81o^q*YXVMc>MbpqoH=r`9=wi2d7xhab@r#`9Nw9Gl<$`&J`ni(TQ zh@Nt}DAGi#rl2yElFvJ;Q_pF`s#m8DCDn73qrI%0n1N zI*W6`^1k3vpVNYge)x#$qg=$LA!4`$we@8V57>Ay6b%!(6 zie;8w)e>94HfclSXY3&r<;-r^A94ugN_pg;62AyJ1ixL!1xi7AaJLIVtafZU_m@Z% zG=jy!gmMd7T)lK%^@;~;0f&4T@(6OTRdBWjL+EiT`3P+4-giSPq$m&V^nCg_qJ`82 zp**-N+)0n}_`gKv6)u-=?K|ZM;IfoPwbe8G>w!P>TCF_$U$hFw((?6*nv#Qi&%IQ| z&t(eR7R;T0xo$CHP}qe?%L(tY$B*9rCLv@g5#<|`G*Z2_QYIJ!lbi^9qkycZ<*WNYZ77qpoS!`J@5$l`dqSJ?cb4_`OHA&rZ9>8s zgRr&B(=RcnBQ+`Xl_?3w2OCbzyGjpAnCj>{lftnH)y|PDOUtfqefaiakZoo}pqRo) zHS4N(d45(kgMhH8K2leQa>(I$<@(%Ejy_jalL^RN8S@h$<2^mmURu8M#r>sw%S&+f z*5@eHyy{zozoNBHYON-GwN!_Mv(A!SwZHs$dHG(j^vS2yF{K)bHqX0SU!Sadn(C}* zE!OAqE&UB3et^blcC8kMU&C>yaR)p2nAZ(X;>iXTd+ac-nHch5AYR G+WHgc4g;_N literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_vendor/vendor.txt b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_vendor/vendor.txt new file mode 100644 index 0000000..712fb77 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pip/_vendor/vendor.txt @@ -0,0 +1,24 @@ +appdirs==1.4.4 +CacheControl==0.12.6 +colorama==0.4.4 +contextlib2==0.6.0.post1 +distlib==0.3.1 +distro==1.5.0 +html5lib==1.1 +ipaddress==1.0.23 # Only needed on 2.6 and 2.7 +msgpack==1.0.0 +packaging==20.8 +pep517==0.9.1 +progress==1.5 +pyparsing==2.4.7 +requests==2.25.0 + certifi==2020.11.08 + chardet==3.0.4 + idna==2.10 + urllib3==1.26.2 +resolvelib==0.5.4 +retrying==1.3.3 +setuptools==44.0.0 +six==1.15.0 +toml==0.10.2 +webencodings==0.5.1 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/AUTHORS.txt b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/AUTHORS.txt new file mode 100644 index 0000000..0360f98 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/AUTHORS.txt @@ -0,0 +1,590 @@ +@Switch01 +A_Rog +Aakanksha Agrawal +Abhinav Sagar +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Wentz +admin +Adrien Morison +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Aleks Bunin +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andre Aguiar +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrey Bulgakov +Andrés Delfino +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anudit Nagar +Anuj Godase +AQNOUCH Mohammed +AraHaan +Arindam Choudhury +Armin Ronacher +Artem +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avinash Karhana +Avner Cohen +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Darnell +Ben Hoyt +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernard +Bernard Tyers +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bhavam Vidyarthi +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Brandon L. Reiss +Brandt Bucher +Brett Randall +Brian Cristante +Brian Rosner +BrownTruck +Bruno Oliveira +Bruno Renié +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris McDonough +Chris Wolfe +Christian Clauss +Christian Heimes +Christian Oudard +Christoph Reiter +Christopher Hunt +Christopher Snyder +cjc7373 +Clark Boylan +Clay McClure +Cody +Cody Soyland +Colin Watson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Cristina +Cristina Muñoz +Curtis Doty +cytolentino +Damian Quiroga +Dan Black +Dan Savilonis +Dan Sully +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Katz +Daniel Shaulov +Daniele Esposti +Daniele Procida +Danny Hermes +Danny McClanahan +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Caro +David Evans +David Linke +David Poggi +David Pursehouse +David Tucker +David Wales +Davidovich +Deepak Sharma +derwolfe +Desetude +Devesh Kumar Singh +Diego Caraballo +DiegoCaraballo +Dmitry Gladkov +Domen Kožar +Donald Stufft +Dongweiming +Douglas Thor +DrFeathers +Dustin Ingram +Dwayne Bailey +Ed Morley +Eitan Adler +ekristina +elainechan +Eli Schwartz +Elisha Hollander +Ellen Marie Dash +Emil Burzo +Emil Styrke +Emmanuel Arias +Endoh Takanao +enoch +Erdinc Mutlu +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Ernest W Durbin III +Ernest W. Durbin III +Erwin Janssen +Eugene Vereshchagin +everdimension +Felix Yan +fiber-space +Filip Kokosiński +Filipe Laíns +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gdanielson +Geoffrey Sneddon +George Song +Georgi Valkov +ghost +Giftlin Rajaiah +gizmoguy1 +gkdoc +Gopinath M +GOTO Hayato +gpiks +Greg Ward +Guilherme Espada +gutsytechster +Guy Rozendorn +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +Herbert Pfennig +Hsiaoming Yang +Hugo +Hugo Lopes Tavares +Hugo van Kemenade +hugovk +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ilan Schnell +Ilya Baryshev +INADA Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Ivan Pozdeev +Jacob Kim +jakirkham +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Firth +James Polley +Jan Pokorný +Jannis Leidel +jarondl +Jason R. Coombs +Jay Graves +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jelmer Vernooij +jenix21 +Jeremy Stanley +Jeremy Zafran +Jiashuo Li +Jim Garrison +Jivan Amara +John Paton +John T. Wodder II +John-Scott Atlakson +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joost Molenaar +Jorge Niedbalski +Joseph Long +Josh Bronson +Josh Hansen +Josh Schneier +Juanjo Bazán +Julian Berman +Julian Gethmann +Julien Demoor +Jussi Kukkonen +jwg4 +Jyrki Pulliainen +Kai Chen +Kamal Bin Mustafa +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +KOLANICH +kpinc +Krishna Oza +Kumar McMillan +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurie O +Laurie Opperman +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark Williams +Markus Hametner +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Matt Good +Matt Maker +Matt Robenolt +matthew +Matthew Einhorn +Matthew Gilliard +Matthew Iversen +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna +mdebi +memoselyk +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Williamson +michaelpacer +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +Nate Coraor +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nguyễn Gia Phong +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nicole Harris +Nikhil Benesch +Nikolay Korolev +Nitesh Sharma +Noah +Noah Gorny +Nowell Strite +NtaleGrey +nvdv +Ofekmeister +ofrinevo +Oliver Jeeves +Oliver Mannion +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +onlinejudge95 +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavithra Eswaramoorthy +Pawel Jasinski +Pekka Klärck +Peter Lisák +Peter Waller +petr-tik +Phaneendra Chiruvella +Phil Elson +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Prashant Sharma +Pratik Mallya +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal +Qiangning Hong +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Razzi Abuissa +rdb +Reece Dunham +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Richard Jones +Ricky Ng-Adam +RobberPhex +Robert Collins +Robert McGibbon +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Roman Bogorodskiy +Romuald Brunet +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Ruairidh MacLeod +Ryan Wooden +ryneeverett +Sachi King +Salvatore Rinchiera +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Woodworth +shireenrao +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +sinscary +socketubs +Sorin Sbarnea +Srinivas Nyayapati +Stavros Korokithakis +Stefan Scherfke +Stefano Rivera +Stephan Erb +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +stonebig +Stéphane Bidoul +Stéphane Bidoul (ACSONE) +Stéphane Klein +Sumana Harihareswara +Surbhi Sharma +Sviatoslav Sydorenko +Swat009 +Takayuki SHIMIZUKAWA +tbeswick +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tom Forbes +Tom Freudenheim +Tom V +Tomas Hrnciar +Tomas Orsava +Tomer Chachamu +Tony Beswick +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +toxinu +Travis Swicegood +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Vikram - Google +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo +Vipul Kumar +Vitaly Babiy +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William ML Leslie +William T Olson +Wilson Mo +wim glenn +Wolfgang Maier +Xavier Fernandez +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Zearin +Zhiping Deng +Zvezdan Petkovic +Łukasz Langa +Семён Марьясин diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/INSTALLER b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/LICENSE.txt b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/LICENSE.txt new file mode 100644 index 0000000..75eb0fd --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2020 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/METADATA b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/METADATA new file mode 100644 index 0000000..cf6c930 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/METADATA @@ -0,0 +1,13 @@ +Metadata-Version: 2.1 +Name: pkg_resources +Version: 0.0.0 +Summary: UNKNOWN +Home-page: UNKNOWN +Author: UNKNOWN +Author-email: UNKNOWN +License: UNKNOWN +Platform: UNKNOWN + +UNKNOWN + + diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/RECORD b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/RECORD new file mode 100644 index 0000000..2cc7da9 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/RECORD @@ -0,0 +1,39 @@ +pkg_resources-0.0.0.dist-info/AUTHORS.txt,sha256=ilkpJ4nuW3rRgU3fX4EufclaM4Y7RsZu5uOu0oizmNM,8036 +pkg_resources-0.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pkg_resources-0.0.0.dist-info/LICENSE.txt,sha256=gdAS_gPyTUkBTvvgoNNlG9Mv1KFDTig6W1JdeMD2Efg,1090 +pkg_resources-0.0.0.dist-info/METADATA,sha256=V9_WPOtD1FnuKrTGv6Ique7kAOn2lasvT8W0_iMCCCk,177 +pkg_resources-0.0.0.dist-info/RECORD,, +pkg_resources-0.0.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pkg_resources-0.0.0.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +pkg_resources/__init__.py,sha256=0IssxXPnaDKpYZRra8Ime0JG4hwosQljItGD0bnIkGk,108349 +pkg_resources/__pycache__/__init__.cpython-39.pyc,, +pkg_resources/__pycache__/py31compat.cpython-39.pyc,, +pkg_resources/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pkg_resources/_vendor/__pycache__/__init__.cpython-39.pyc,, +pkg_resources/_vendor/__pycache__/appdirs.cpython-39.pyc,, +pkg_resources/_vendor/__pycache__/pyparsing.cpython-39.pyc,, +pkg_resources/_vendor/__pycache__/six.cpython-39.pyc,, +pkg_resources/_vendor/appdirs.py,sha256=MievUEuv3l_mQISH5SF0shDk_BNhHHzYiAPrT3ITN4I,24701 +pkg_resources/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 +pkg_resources/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 +pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/markers.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/utils.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/version.cpython-39.pyc,, +pkg_resources/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 +pkg_resources/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 +pkg_resources/_vendor/packaging/markers.py,sha256=uEcBBtGvzqltgnArqb9c4RrcInXezDLos14zbBHhWJo,8248 +pkg_resources/_vendor/packaging/requirements.py,sha256=SikL2UynbsT0qtY9ltqngndha_sfo0w6XGFhAhoSoaQ,4355 +pkg_resources/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 +pkg_resources/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 +pkg_resources/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 +pkg_resources/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 +pkg_resources/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 +pkg_resources/extern/__init__.py,sha256=cHiEfHuLmm6rs5Ve_ztBfMI7Lr31vss-D4wkqF5xzlI,2498 +pkg_resources/extern/__pycache__/__init__.cpython-39.pyc,, +pkg_resources/py31compat.py,sha256=-WQ0e4c3RG_acdhwC3gLiXhP_lg4G5q7XYkZkQg0gxU,558 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/REQUESTED b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/WHEEL b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/WHEEL new file mode 100644 index 0000000..ef99c6c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources-0.0.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/__init__.py new file mode 100644 index 0000000..2f5aa64 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/__init__.py @@ -0,0 +1,3296 @@ +# coding: utf-8 +""" +Package resource API +-------------------- + +A resource is a logical file contained within a package, or a logical +subdirectory thereof. The package resource API expects resource names +to have their path parts separated with ``/``, *not* whatever the local +path separator is. Do not use os.path operations to manipulate resource +names being passed into the API. + +The package resource API is designed to work with normal filesystem packages, +.egg files, and unpacked .egg files. It can also work in a limited way with +.zip files and with custom PEP 302 loaders that support the ``get_data()`` +method. +""" + +from __future__ import absolute_import + +import sys +import os +import io +import time +import re +import types +import zipfile +import zipimport +import warnings +import stat +import functools +import pkgutil +import operator +import platform +import collections +import plistlib +import email.parser +import errno +import tempfile +import textwrap +import itertools +import inspect +import ntpath +import posixpath +from pkgutil import get_importer + +try: + import _imp +except ImportError: + # Python 3.2 compatibility + import imp as _imp + +try: + FileExistsError +except NameError: + FileExistsError = OSError + +from pkg_resources.extern import six +from pkg_resources.extern.six.moves import urllib, map, filter + +# capture these to bypass sandboxing +from os import utime +try: + from os import mkdir, rename, unlink + WRITE_SUPPORT = True +except ImportError: + # no write support, probably under GAE + WRITE_SUPPORT = False + +from os import open as os_open +from os.path import isdir, split + +try: + import importlib.machinery as importlib_machinery + # access attribute to force import under delayed import mechanisms. + importlib_machinery.__name__ +except ImportError: + importlib_machinery = None + +from . import py31compat +from pkg_resources.extern import appdirs +from pkg_resources.extern import packaging +__import__('pkg_resources.extern.packaging.version') +__import__('pkg_resources.extern.packaging.specifiers') +__import__('pkg_resources.extern.packaging.requirements') +__import__('pkg_resources.extern.packaging.markers') + + +__metaclass__ = type + + +if (3, 0) < sys.version_info < (3, 5): + raise RuntimeError("Python 3.5 or later is required") + +if six.PY2: + # Those builtin exceptions are only defined in Python 3 + PermissionError = None + NotADirectoryError = None + +# declare some globals that will be defined later to +# satisfy the linters. +require = None +working_set = None +add_activation_listener = None +resources_stream = None +cleanup_resources = None +resource_dir = None +resource_stream = None +set_extraction_path = None +resource_isdir = None +resource_string = None +iter_entry_points = None +resource_listdir = None +resource_filename = None +resource_exists = None +_distribution_finders = None +_namespace_handlers = None +_namespace_packages = None + + +class PEP440Warning(RuntimeWarning): + """ + Used when there is an issue with a version or specifier not complying with + PEP 440. + """ + + +def parse_version(v): + try: + return packaging.version.Version(v) + except packaging.version.InvalidVersion: + return packaging.version.LegacyVersion(v) + + +_state_vars = {} + + +def _declare_state(vartype, **kw): + globals().update(kw) + _state_vars.update(dict.fromkeys(kw, vartype)) + + +def __getstate__(): + state = {} + g = globals() + for k, v in _state_vars.items(): + state[k] = g['_sget_' + v](g[k]) + return state + + +def __setstate__(state): + g = globals() + for k, v in state.items(): + g['_sset_' + _state_vars[k]](k, g[k], v) + return state + + +def _sget_dict(val): + return val.copy() + + +def _sset_dict(key, ob, state): + ob.clear() + ob.update(state) + + +def _sget_object(val): + return val.__getstate__() + + +def _sset_object(key, ob, state): + ob.__setstate__(state) + + +_sget_none = _sset_none = lambda *args: None + + +def get_supported_platform(): + """Return this platform's maximum compatible version. + + distutils.util.get_platform() normally reports the minimum version + of Mac OS X that would be required to *use* extensions produced by + distutils. But what we want when checking compatibility is to know the + version of Mac OS X that we are *running*. To allow usage of packages that + explicitly require a newer version of Mac OS X, we must also know the + current version of the OS. + + If this condition occurs for any other platform with a version in its + platform strings, this function should be extended accordingly. + """ + plat = get_build_platform() + m = macosVersionString.match(plat) + if m is not None and sys.platform == "darwin": + try: + plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3)) + except ValueError: + # not Mac OS X + pass + return plat + + +__all__ = [ + # Basic resource access and distribution/entry point discovery + 'require', 'run_script', 'get_provider', 'get_distribution', + 'load_entry_point', 'get_entry_map', 'get_entry_info', + 'iter_entry_points', + 'resource_string', 'resource_stream', 'resource_filename', + 'resource_listdir', 'resource_exists', 'resource_isdir', + + # Environmental control + 'declare_namespace', 'working_set', 'add_activation_listener', + 'find_distributions', 'set_extraction_path', 'cleanup_resources', + 'get_default_cache', + + # Primary implementation classes + 'Environment', 'WorkingSet', 'ResourceManager', + 'Distribution', 'Requirement', 'EntryPoint', + + # Exceptions + 'ResolutionError', 'VersionConflict', 'DistributionNotFound', + 'UnknownExtra', 'ExtractionError', + + # Warnings + 'PEP440Warning', + + # Parsing functions and string utilities + 'parse_requirements', 'parse_version', 'safe_name', 'safe_version', + 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections', + 'safe_extra', 'to_filename', 'invalid_marker', 'evaluate_marker', + + # filesystem utilities + 'ensure_directory', 'normalize_path', + + # Distribution "precedence" constants + 'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST', + + # "Provider" interfaces, implementations, and registration/lookup APIs + 'IMetadataProvider', 'IResourceProvider', 'FileMetadata', + 'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider', + 'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider', + 'register_finder', 'register_namespace_handler', 'register_loader_type', + 'fixup_namespace_packages', 'get_importer', + + # Warnings + 'PkgResourcesDeprecationWarning', + + # Deprecated/backward compatibility only + 'run_main', 'AvailableDistributions', +] + + +class ResolutionError(Exception): + """Abstract base for dependency resolution errors""" + + def __repr__(self): + return self.__class__.__name__ + repr(self.args) + + +class VersionConflict(ResolutionError): + """ + An already-installed version conflicts with the requested version. + + Should be initialized with the installed Distribution and the requested + Requirement. + """ + + _template = "{self.dist} is installed but {self.req} is required" + + @property + def dist(self): + return self.args[0] + + @property + def req(self): + return self.args[1] + + def report(self): + return self._template.format(**locals()) + + def with_context(self, required_by): + """ + If required_by is non-empty, return a version of self that is a + ContextualVersionConflict. + """ + if not required_by: + return self + args = self.args + (required_by,) + return ContextualVersionConflict(*args) + + +class ContextualVersionConflict(VersionConflict): + """ + A VersionConflict that accepts a third parameter, the set of the + requirements that required the installed Distribution. + """ + + _template = VersionConflict._template + ' by {self.required_by}' + + @property + def required_by(self): + return self.args[2] + + +class DistributionNotFound(ResolutionError): + """A requested distribution was not found""" + + _template = ("The '{self.req}' distribution was not found " + "and is required by {self.requirers_str}") + + @property + def req(self): + return self.args[0] + + @property + def requirers(self): + return self.args[1] + + @property + def requirers_str(self): + if not self.requirers: + return 'the application' + return ', '.join(self.requirers) + + def report(self): + return self._template.format(**locals()) + + def __str__(self): + return self.report() + + +class UnknownExtra(ResolutionError): + """Distribution doesn't have an "extra feature" of the given name""" + + +_provider_factories = {} + +PY_MAJOR = '{}.{}'.format(*sys.version_info) +EGG_DIST = 3 +BINARY_DIST = 2 +SOURCE_DIST = 1 +CHECKOUT_DIST = 0 +DEVELOP_DIST = -1 + + +def register_loader_type(loader_type, provider_factory): + """Register `provider_factory` to make providers for `loader_type` + + `loader_type` is the type or class of a PEP 302 ``module.__loader__``, + and `provider_factory` is a function that, passed a *module* object, + returns an ``IResourceProvider`` for that module. + """ + _provider_factories[loader_type] = provider_factory + + +def get_provider(moduleOrReq): + """Return an IResourceProvider for the named module or requirement""" + if isinstance(moduleOrReq, Requirement): + return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] + try: + module = sys.modules[moduleOrReq] + except KeyError: + __import__(moduleOrReq) + module = sys.modules[moduleOrReq] + loader = getattr(module, '__loader__', None) + return _find_adapter(_provider_factories, loader)(module) + + +def _macosx_vers(_cache=[]): + if not _cache: + version = platform.mac_ver()[0] + # fallback for MacPorts + if version == '': + plist = '/System/Library/CoreServices/SystemVersion.plist' + if os.path.exists(plist): + if hasattr(plistlib, 'readPlist'): + plist_content = plistlib.readPlist(plist) + if 'ProductVersion' in plist_content: + version = plist_content['ProductVersion'] + + _cache.append(version.split('.')) + return _cache[0] + + +def _macosx_arch(machine): + return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine) + + +def get_build_platform(): + """Return this platform's string for platform-specific distributions + + XXX Currently this is the same as ``distutils.util.get_platform()``, but it + needs some hacks for Linux and Mac OS X. + """ + from sysconfig import get_platform + + plat = get_platform() + if sys.platform == "darwin" and not plat.startswith('macosx-'): + try: + version = _macosx_vers() + machine = os.uname()[4].replace(" ", "_") + return "macosx-%d.%d-%s" % ( + int(version[0]), int(version[1]), + _macosx_arch(machine), + ) + except ValueError: + # if someone is running a non-Mac darwin system, this will fall + # through to the default implementation + pass + return plat + + +macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)") +darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") +# XXX backward compat +get_platform = get_build_platform + + +def compatible_platforms(provided, required): + """Can code for the `provided` platform run on the `required` platform? + + Returns true if either platform is ``None``, or the platforms are equal. + + XXX Needs compatibility checks for Linux and other unixy OSes. + """ + if provided is None or required is None or provided == required: + # easy case + return True + + # Mac OS X special cases + reqMac = macosVersionString.match(required) + if reqMac: + provMac = macosVersionString.match(provided) + + # is this a Mac package? + if not provMac: + # this is backwards compatibility for packages built before + # setuptools 0.6. All packages built after this point will + # use the new macosx designation. + provDarwin = darwinVersionString.match(provided) + if provDarwin: + dversion = int(provDarwin.group(1)) + macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) + if dversion == 7 and macosversion >= "10.3" or \ + dversion == 8 and macosversion >= "10.4": + return True + # egg isn't macosx or legacy darwin + return False + + # are they the same major version and machine type? + if provMac.group(1) != reqMac.group(1) or \ + provMac.group(3) != reqMac.group(3): + return False + + # is the required OS major update >= the provided one? + if int(provMac.group(2)) > int(reqMac.group(2)): + return False + + return True + + # XXX Linux and other platforms' special cases should go here + return False + + +def run_script(dist_spec, script_name): + """Locate distribution `dist_spec` and run its `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + require(dist_spec)[0].run_script(script_name, ns) + + +# backward compatibility +run_main = run_script + + +def get_distribution(dist): + """Return a current distribution object for a Requirement or string""" + if isinstance(dist, six.string_types): + dist = Requirement.parse(dist) + if isinstance(dist, Requirement): + dist = get_provider(dist) + if not isinstance(dist, Distribution): + raise TypeError("Expected string, Requirement, or Distribution", dist) + return dist + + +def load_entry_point(dist, group, name): + """Return `name` entry point of `group` for `dist` or raise ImportError""" + return get_distribution(dist).load_entry_point(group, name) + + +def get_entry_map(dist, group=None): + """Return the entry point map for `group`, or the full entry map""" + return get_distribution(dist).get_entry_map(group) + + +def get_entry_info(dist, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return get_distribution(dist).get_entry_info(group, name) + + +class IMetadataProvider: + def has_metadata(name): + """Does the package's distribution contain the named metadata?""" + + def get_metadata(name): + """The named metadata resource as a string""" + + def get_metadata_lines(name): + """Yield named metadata resource as list of non-blank non-comment lines + + Leading and trailing whitespace is stripped from each line, and lines + with ``#`` as the first non-blank character are omitted.""" + + def metadata_isdir(name): + """Is the named metadata a directory? (like ``os.path.isdir()``)""" + + def metadata_listdir(name): + """List of metadata names in the directory (like ``os.listdir()``)""" + + def run_script(script_name, namespace): + """Execute the named script in the supplied namespace dictionary""" + + +class IResourceProvider(IMetadataProvider): + """An object that provides access to package resources""" + + def get_resource_filename(manager, resource_name): + """Return a true filesystem path for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_stream(manager, resource_name): + """Return a readable file-like object for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_string(manager, resource_name): + """Return a string containing the contents of `resource_name` + + `manager` must be an ``IResourceManager``""" + + def has_resource(resource_name): + """Does the package contain the named resource?""" + + def resource_isdir(resource_name): + """Is the named resource a directory? (like ``os.path.isdir()``)""" + + def resource_listdir(resource_name): + """List of resource names in the directory (like ``os.listdir()``)""" + + +class WorkingSet: + """A collection of active distributions on sys.path (or a similar list)""" + + def __init__(self, entries=None): + """Create working set from list of path entries (default=sys.path)""" + self.entries = [] + self.entry_keys = {} + self.by_key = {} + self.callbacks = [] + + if entries is None: + entries = sys.path + + for entry in entries: + self.add_entry(entry) + + @classmethod + def _build_master(cls): + """ + Prepare the master working set. + """ + ws = cls() + try: + from __main__ import __requires__ + except ImportError: + # The main program does not list any requirements + return ws + + # ensure the requirements are met + try: + ws.require(__requires__) + except VersionConflict: + return cls._build_from_requirements(__requires__) + + return ws + + @classmethod + def _build_from_requirements(cls, req_spec): + """ + Build a working set from a requirement spec. Rewrites sys.path. + """ + # try it without defaults already on sys.path + # by starting with an empty path + ws = cls([]) + reqs = parse_requirements(req_spec) + dists = ws.resolve(reqs, Environment()) + for dist in dists: + ws.add(dist) + + # add any missing entries from sys.path + for entry in sys.path: + if entry not in ws.entries: + ws.add_entry(entry) + + # then copy back to sys.path + sys.path[:] = ws.entries + return ws + + def add_entry(self, entry): + """Add a path item to ``.entries``, finding any distributions on it + + ``find_distributions(entry, True)`` is used to find distributions + corresponding to the path entry, and they are added. `entry` is + always appended to ``.entries``, even if it is already present. + (This is because ``sys.path`` can contain the same value more than + once, and the ``.entries`` of the ``sys.path`` WorkingSet should always + equal ``sys.path``.) + """ + self.entry_keys.setdefault(entry, []) + self.entries.append(entry) + for dist in find_distributions(entry, True): + self.add(dist, entry, False) + + def __contains__(self, dist): + """True if `dist` is the active distribution for its project""" + return self.by_key.get(dist.key) == dist + + def find(self, req): + """Find a distribution matching requirement `req` + + If there is an active distribution for the requested project, this + returns it as long as it meets the version requirement specified by + `req`. But, if there is an active distribution for the project and it + does *not* meet the `req` requirement, ``VersionConflict`` is raised. + If there is no active distribution for the requested project, ``None`` + is returned. + """ + dist = self.by_key.get(req.key) + if dist is not None and dist not in req: + # XXX add more info + raise VersionConflict(dist, req) + return dist + + def iter_entry_points(self, group, name=None): + """Yield entry point objects from `group` matching `name` + + If `name` is None, yields all entry points in `group` from all + distributions in the working set, otherwise only ones matching + both `group` and `name` are yielded (in distribution order). + """ + return ( + entry + for dist in self + for entry in dist.get_entry_map(group).values() + if name is None or name == entry.name + ) + + def run_script(self, requires, script_name): + """Locate distribution for `requires` and run `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + self.require(requires)[0].run_script(script_name, ns) + + def __iter__(self): + """Yield distributions for non-duplicate projects in the working set + + The yield order is the order in which the items' path entries were + added to the working set. + """ + seen = {} + for item in self.entries: + if item not in self.entry_keys: + # workaround a cache issue + continue + + for key in self.entry_keys[item]: + if key not in seen: + seen[key] = 1 + yield self.by_key[key] + + def add(self, dist, entry=None, insert=True, replace=False): + """Add `dist` to working set, associated with `entry` + + If `entry` is unspecified, it defaults to the ``.location`` of `dist`. + On exit from this routine, `entry` is added to the end of the working + set's ``.entries`` (if it wasn't already present). + + `dist` is only added to the working set if it's for a project that + doesn't already have a distribution in the set, unless `replace=True`. + If it's added, any callbacks registered with the ``subscribe()`` method + will be called. + """ + if insert: + dist.insert_on(self.entries, entry, replace=replace) + + if entry is None: + entry = dist.location + keys = self.entry_keys.setdefault(entry, []) + keys2 = self.entry_keys.setdefault(dist.location, []) + if not replace and dist.key in self.by_key: + # ignore hidden distros + return + + self.by_key[dist.key] = dist + if dist.key not in keys: + keys.append(dist.key) + if dist.key not in keys2: + keys2.append(dist.key) + self._added_new(dist) + + def resolve(self, requirements, env=None, installer=None, + replace_conflicting=False, extras=None): + """List all distributions needed to (recursively) meet `requirements` + + `requirements` must be a sequence of ``Requirement`` objects. `env`, + if supplied, should be an ``Environment`` instance. If + not supplied, it defaults to all distributions available within any + entry or distribution in the working set. `installer`, if supplied, + will be invoked with each requirement that cannot be met by an + already-installed distribution; it should return a ``Distribution`` or + ``None``. + + Unless `replace_conflicting=True`, raises a VersionConflict exception + if + any requirements are found on the path that have the correct name but + the wrong version. Otherwise, if an `installer` is supplied it will be + invoked to obtain the correct version of the requirement and activate + it. + + `extras` is a list of the extras to be used with these requirements. + This is important because extra requirements may look like `my_req; + extra = "my_extra"`, which would otherwise be interpreted as a purely + optional requirement. Instead, we want to be able to assert that these + requirements are truly required. + """ + + # set up the stack + requirements = list(requirements)[::-1] + # set of processed requirements + processed = {} + # key -> dist + best = {} + to_activate = [] + + req_extras = _ReqExtras() + + # Mapping of requirement to set of distributions that required it; + # useful for reporting info about conflicts. + required_by = collections.defaultdict(set) + + while requirements: + # process dependencies breadth-first + req = requirements.pop(0) + if req in processed: + # Ignore cyclic or redundant dependencies + continue + + if not req_extras.markers_pass(req, extras): + continue + + dist = best.get(req.key) + if dist is None: + # Find the best distribution and add it to the map + dist = self.by_key.get(req.key) + if dist is None or (dist not in req and replace_conflicting): + ws = self + if env is None: + if dist is None: + env = Environment(self.entries) + else: + # Use an empty environment and workingset to avoid + # any further conflicts with the conflicting + # distribution + env = Environment([]) + ws = WorkingSet([]) + dist = best[req.key] = env.best_match( + req, ws, installer, + replace_conflicting=replace_conflicting + ) + if dist is None: + requirers = required_by.get(req, None) + raise DistributionNotFound(req, requirers) + to_activate.append(dist) + if dist not in req: + # Oops, the "best" so far conflicts with a dependency + dependent_req = required_by[req] + raise VersionConflict(dist, req).with_context(dependent_req) + + # push the new requirements onto the stack + new_requirements = dist.requires(req.extras)[::-1] + requirements.extend(new_requirements) + + # Register the new requirements needed by req + for new_requirement in new_requirements: + required_by[new_requirement].add(req.project_name) + req_extras[new_requirement] = req.extras + + processed[req] = True + + # return list of distros to activate + return to_activate + + def find_plugins( + self, plugin_env, full_env=None, installer=None, fallback=True): + """Find all activatable distributions in `plugin_env` + + Example usage:: + + distributions, errors = working_set.find_plugins( + Environment(plugin_dirlist) + ) + # add plugins+libs to sys.path + map(working_set.add, distributions) + # display errors + print('Could not load', errors) + + The `plugin_env` should be an ``Environment`` instance that contains + only distributions that are in the project's "plugin directory" or + directories. The `full_env`, if supplied, should be an ``Environment`` + contains all currently-available distributions. If `full_env` is not + supplied, one is created automatically from the ``WorkingSet`` this + method is called on, which will typically mean that every directory on + ``sys.path`` will be scanned for distributions. + + `installer` is a standard installer callback as used by the + ``resolve()`` method. The `fallback` flag indicates whether we should + attempt to resolve older versions of a plugin if the newest version + cannot be resolved. + + This method returns a 2-tuple: (`distributions`, `error_info`), where + `distributions` is a list of the distributions found in `plugin_env` + that were loadable, along with any other distributions that are needed + to resolve their dependencies. `error_info` is a dictionary mapping + unloadable plugin distributions to an exception instance describing the + error that occurred. Usually this will be a ``DistributionNotFound`` or + ``VersionConflict`` instance. + """ + + plugin_projects = list(plugin_env) + # scan project names in alphabetic order + plugin_projects.sort() + + error_info = {} + distributions = {} + + if full_env is None: + env = Environment(self.entries) + env += plugin_env + else: + env = full_env + plugin_env + + shadow_set = self.__class__([]) + # put all our entries in shadow_set + list(map(shadow_set.add, self)) + + for project_name in plugin_projects: + + for dist in plugin_env[project_name]: + + req = [dist.as_requirement()] + + try: + resolvees = shadow_set.resolve(req, env, installer) + + except ResolutionError as v: + # save error info + error_info[dist] = v + if fallback: + # try the next older version of project + continue + else: + # give up on this project, keep going + break + + else: + list(map(shadow_set.add, resolvees)) + distributions.update(dict.fromkeys(resolvees)) + + # success, no need to try any more versions of this project + break + + distributions = list(distributions) + distributions.sort() + + return distributions, error_info + + def require(self, *requirements): + """Ensure that distributions matching `requirements` are activated + + `requirements` must be a string or a (possibly-nested) sequence + thereof, specifying the distributions and versions required. The + return value is a sequence of the distributions that needed to be + activated to fulfill the requirements; all relevant distributions are + included, even if they were already activated in this working set. + """ + needed = self.resolve(parse_requirements(requirements)) + + for dist in needed: + self.add(dist) + + return needed + + def subscribe(self, callback, existing=True): + """Invoke `callback` for all distributions + + If `existing=True` (default), + call on all existing ones, as well. + """ + if callback in self.callbacks: + return + self.callbacks.append(callback) + if not existing: + return + for dist in self: + callback(dist) + + def _added_new(self, dist): + for callback in self.callbacks: + callback(dist) + + def __getstate__(self): + return ( + self.entries[:], self.entry_keys.copy(), self.by_key.copy(), + self.callbacks[:] + ) + + def __setstate__(self, e_k_b_c): + entries, keys, by_key, callbacks = e_k_b_c + self.entries = entries[:] + self.entry_keys = keys.copy() + self.by_key = by_key.copy() + self.callbacks = callbacks[:] + + +class _ReqExtras(dict): + """ + Map each requirement to the extras that demanded it. + """ + + def markers_pass(self, req, extras=None): + """ + Evaluate markers for req against each extra that + demanded it. + + Return False if the req has a marker and fails + evaluation. Otherwise, return True. + """ + extra_evals = ( + req.marker.evaluate({'extra': extra}) + for extra in self.get(req, ()) + (extras or (None,)) + ) + return not req.marker or any(extra_evals) + + +class Environment: + """Searchable snapshot of distributions on a search path""" + + def __init__( + self, search_path=None, platform=get_supported_platform(), + python=PY_MAJOR): + """Snapshot distributions available on a search path + + Any distributions found on `search_path` are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. + + `platform` is an optional string specifying the name of the platform + that platform-specific distributions must be compatible with. If + unspecified, it defaults to the current platform. `python` is an + optional string naming the desired version of Python (e.g. ``'3.6'``); + it defaults to the current version. + + You may explicitly set `platform` (and/or `python`) to ``None`` if you + wish to map *all* distributions, not just those compatible with the + running platform or Python version. + """ + self._distmap = {} + self.platform = platform + self.python = python + self.scan(search_path) + + def can_add(self, dist): + """Is distribution `dist` acceptable for this environment? + + The distribution must match the platform and python version + requirements specified when this environment was created, or False + is returned. + """ + py_compat = ( + self.python is None + or dist.py_version is None + or dist.py_version == self.python + ) + return py_compat and compatible_platforms(dist.platform, self.platform) + + def remove(self, dist): + """Remove `dist` from the environment""" + self._distmap[dist.key].remove(dist) + + def scan(self, search_path=None): + """Scan `search_path` for distributions usable in this environment + + Any distributions found are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. Only distributions conforming to + the platform/python version defined at initialization are added. + """ + if search_path is None: + search_path = sys.path + + for item in search_path: + for dist in find_distributions(item): + self.add(dist) + + def __getitem__(self, project_name): + """Return a newest-to-oldest list of distributions for `project_name` + + Uses case-insensitive `project_name` comparison, assuming all the + project's distributions use their project's name converted to all + lowercase as their key. + + """ + distribution_key = project_name.lower() + return self._distmap.get(distribution_key, []) + + def add(self, dist): + """Add `dist` if we ``can_add()`` it and it has not already been added + """ + if self.can_add(dist) and dist.has_version(): + dists = self._distmap.setdefault(dist.key, []) + if dist not in dists: + dists.append(dist) + dists.sort(key=operator.attrgetter('hashcmp'), reverse=True) + + def best_match( + self, req, working_set, installer=None, replace_conflicting=False): + """Find distribution best matching `req` and usable on `working_set` + + This calls the ``find(req)`` method of the `working_set` to see if a + suitable distribution is already active. (This may raise + ``VersionConflict`` if an unsuitable version of the project is already + active in the specified `working_set`.) If a suitable distribution + isn't active, this method returns the newest distribution in the + environment that meets the ``Requirement`` in `req`. If no suitable + distribution is found, and `installer` is supplied, then the result of + calling the environment's ``obtain(req, installer)`` method will be + returned. + """ + try: + dist = working_set.find(req) + except VersionConflict: + if not replace_conflicting: + raise + dist = None + if dist is not None: + return dist + for dist in self[req.key]: + if dist in req: + return dist + # try to download/install + return self.obtain(req, installer) + + def obtain(self, requirement, installer=None): + """Obtain a distribution matching `requirement` (e.g. via download) + + Obtain a distro that matches requirement (e.g. via download). In the + base ``Environment`` class, this routine just returns + ``installer(requirement)``, unless `installer` is None, in which case + None is returned instead. This method is a hook that allows subclasses + to attempt other ways of obtaining a distribution before falling back + to the `installer` argument.""" + if installer is not None: + return installer(requirement) + + def __iter__(self): + """Yield the unique project names of the available distributions""" + for key in self._distmap.keys(): + if self[key]: + yield key + + def __iadd__(self, other): + """In-place addition of a distribution or environment""" + if isinstance(other, Distribution): + self.add(other) + elif isinstance(other, Environment): + for project in other: + for dist in other[project]: + self.add(dist) + else: + raise TypeError("Can't add %r to environment" % (other,)) + return self + + def __add__(self, other): + """Add an environment or distribution to an environment""" + new = self.__class__([], platform=None, python=None) + for env in self, other: + new += env + return new + + +# XXX backward compatibility +AvailableDistributions = Environment + + +class ExtractionError(RuntimeError): + """An error occurred extracting a resource + + The following attributes are available from instances of this exception: + + manager + The resource manager that raised this exception + + cache_path + The base directory for resource extraction + + original_error + The exception instance that caused extraction to fail + """ + + +class ResourceManager: + """Manage resource extraction and packages""" + extraction_path = None + + def __init__(self): + self.cached_files = {} + + def resource_exists(self, package_or_requirement, resource_name): + """Does the named resource exist?""" + return get_provider(package_or_requirement).has_resource(resource_name) + + def resource_isdir(self, package_or_requirement, resource_name): + """Is the named resource an existing directory?""" + return get_provider(package_or_requirement).resource_isdir( + resource_name + ) + + def resource_filename(self, package_or_requirement, resource_name): + """Return a true filesystem path for specified resource""" + return get_provider(package_or_requirement).get_resource_filename( + self, resource_name + ) + + def resource_stream(self, package_or_requirement, resource_name): + """Return a readable file-like object for specified resource""" + return get_provider(package_or_requirement).get_resource_stream( + self, resource_name + ) + + def resource_string(self, package_or_requirement, resource_name): + """Return specified resource as a string""" + return get_provider(package_or_requirement).get_resource_string( + self, resource_name + ) + + def resource_listdir(self, package_or_requirement, resource_name): + """List the contents of the named resource directory""" + return get_provider(package_or_requirement).resource_listdir( + resource_name + ) + + def extraction_error(self): + """Give an error message for problems extracting file(s)""" + + old_exc = sys.exc_info()[1] + cache_path = self.extraction_path or get_default_cache() + + tmpl = textwrap.dedent(""" + Can't extract file(s) to egg cache + + The following error occurred while trying to extract file(s) + to the Python egg cache: + + {old_exc} + + The Python egg cache directory is currently set to: + + {cache_path} + + Perhaps your account does not have write access to this directory? + You can change the cache directory by setting the PYTHON_EGG_CACHE + environment variable to point to an accessible directory. + """).lstrip() + err = ExtractionError(tmpl.format(**locals())) + err.manager = self + err.cache_path = cache_path + err.original_error = old_exc + raise err + + def get_cache_path(self, archive_name, names=()): + """Return absolute location in cache for `archive_name` and `names` + + The parent directory of the resulting path will be created if it does + not already exist. `archive_name` should be the base filename of the + enclosing egg (which may not be the name of the enclosing zipfile!), + including its ".egg" extension. `names`, if provided, should be a + sequence of path name parts "under" the egg's extraction location. + + This method should only be called by resource providers that need to + obtain an extraction location, and only for names they intend to + extract, as it tracks the generated names for possible cleanup later. + """ + extract_path = self.extraction_path or get_default_cache() + target_path = os.path.join(extract_path, archive_name + '-tmp', *names) + try: + _bypass_ensure_directory(target_path) + except Exception: + self.extraction_error() + + self._warn_unsafe_extraction_path(extract_path) + + self.cached_files[target_path] = 1 + return target_path + + @staticmethod + def _warn_unsafe_extraction_path(path): + """ + If the default extraction path is overridden and set to an insecure + location, such as /tmp, it opens up an opportunity for an attacker to + replace an extracted file with an unauthorized payload. Warn the user + if a known insecure location is used. + + See Distribute #375 for more details. + """ + if os.name == 'nt' and not path.startswith(os.environ['windir']): + # On Windows, permissions are generally restrictive by default + # and temp directories are not writable by other users, so + # bypass the warning. + return + mode = os.stat(path).st_mode + if mode & stat.S_IWOTH or mode & stat.S_IWGRP: + msg = ( + "%s is writable by group/others and vulnerable to attack " + "when " + "used with get_resource_filename. Consider a more secure " + "location (set with .set_extraction_path or the " + "PYTHON_EGG_CACHE environment variable)." % path + ) + warnings.warn(msg, UserWarning) + + def postprocess(self, tempname, filename): + """Perform any platform-specific postprocessing of `tempname` + + This is where Mac header rewrites should be done; other platforms don't + have anything special they should do. + + Resource providers should call this method ONLY after successfully + extracting a compressed resource. They must NOT call it on resources + that are already in the filesystem. + + `tempname` is the current (temporary) name of the file, and `filename` + is the name it will be renamed to by the caller after this routine + returns. + """ + + if os.name == 'posix': + # Make the resource executable + mode = ((os.stat(tempname).st_mode) | 0o555) & 0o7777 + os.chmod(tempname, mode) + + def set_extraction_path(self, path): + """Set the base path where resources will be extracted to, if needed. + + If you do not call this routine before any extractions take place, the + path defaults to the return value of ``get_default_cache()``. (Which + is based on the ``PYTHON_EGG_CACHE`` environment variable, with various + platform-specific fallbacks. See that routine's documentation for more + details.) + + Resources are extracted to subdirectories of this path based upon + information given by the ``IResourceProvider``. You may set this to a + temporary directory, but then you must call ``cleanup_resources()`` to + delete the extracted files when done. There is no guarantee that + ``cleanup_resources()`` will be able to remove all extracted files. + + (Note: you may not change the extraction path for a given resource + manager once resources have been extracted, unless you first call + ``cleanup_resources()``.) + """ + if self.cached_files: + raise ValueError( + "Can't change extraction path, files already extracted" + ) + + self.extraction_path = path + + def cleanup_resources(self, force=False): + """ + Delete all extracted resource files and directories, returning a list + of the file and directory names that could not be successfully removed. + This function does not have any concurrency protection, so it should + generally only be called when the extraction path is a temporary + directory exclusive to a single process. This method is not + automatically called; you must call it explicitly or register it as an + ``atexit`` function if you wish to ensure cleanup of a temporary + directory used for extractions. + """ + # XXX + + +def get_default_cache(): + """ + Return the ``PYTHON_EGG_CACHE`` environment variable + or a platform-relevant user cache dir for an app + named "Python-Eggs". + """ + return ( + os.environ.get('PYTHON_EGG_CACHE') + or appdirs.user_cache_dir(appname='Python-Eggs') + ) + + +def safe_name(name): + """Convert an arbitrary string to a standard distribution name + + Any runs of non-alphanumeric/. characters are replaced with a single '-'. + """ + return re.sub('[^A-Za-z0-9.]+', '-', name) + + +def safe_version(version): + """ + Convert an arbitrary string to a standard version string + """ + try: + # normalize the version + return str(packaging.version.Version(version)) + except packaging.version.InvalidVersion: + version = version.replace(' ', '.') + return re.sub('[^A-Za-z0-9.]+', '-', version) + + +def safe_extra(extra): + """Convert an arbitrary string to a standard 'extra' name + + Any runs of non-alphanumeric characters are replaced with a single '_', + and the result is always lowercased. + """ + return re.sub('[^A-Za-z0-9.-]+', '_', extra).lower() + + +def to_filename(name): + """Convert a project or version name to its filename-escaped form + + Any '-' characters are currently replaced with '_'. + """ + return name.replace('-', '_') + + +def invalid_marker(text): + """ + Validate text as a PEP 508 environment marker; return an exception + if invalid or False otherwise. + """ + try: + evaluate_marker(text) + except SyntaxError as e: + e.filename = None + e.lineno = None + return e + return False + + +def evaluate_marker(text, extra=None): + """ + Evaluate a PEP 508 environment marker. + Return a boolean indicating the marker result in this environment. + Raise SyntaxError if marker is invalid. + + This implementation uses the 'pyparsing' module. + """ + try: + marker = packaging.markers.Marker(text) + return marker.evaluate() + except packaging.markers.InvalidMarker as e: + raise SyntaxError(e) + + +class NullProvider: + """Try to implement resources and metadata for arbitrary PEP 302 loaders""" + + egg_name = None + egg_info = None + loader = None + + def __init__(self, module): + self.loader = getattr(module, '__loader__', None) + self.module_path = os.path.dirname(getattr(module, '__file__', '')) + + def get_resource_filename(self, manager, resource_name): + return self._fn(self.module_path, resource_name) + + def get_resource_stream(self, manager, resource_name): + return io.BytesIO(self.get_resource_string(manager, resource_name)) + + def get_resource_string(self, manager, resource_name): + return self._get(self._fn(self.module_path, resource_name)) + + def has_resource(self, resource_name): + return self._has(self._fn(self.module_path, resource_name)) + + def _get_metadata_path(self, name): + return self._fn(self.egg_info, name) + + def has_metadata(self, name): + if not self.egg_info: + return self.egg_info + + path = self._get_metadata_path(name) + return self._has(path) + + def get_metadata(self, name): + if not self.egg_info: + return "" + path = self._get_metadata_path(name) + value = self._get(path) + if six.PY2: + return value + try: + return value.decode('utf-8') + except UnicodeDecodeError as exc: + # Include the path in the error message to simplify + # troubleshooting, and without changing the exception type. + exc.reason += ' in {} file at path: {}'.format(name, path) + raise + + def get_metadata_lines(self, name): + return yield_lines(self.get_metadata(name)) + + def resource_isdir(self, resource_name): + return self._isdir(self._fn(self.module_path, resource_name)) + + def metadata_isdir(self, name): + return self.egg_info and self._isdir(self._fn(self.egg_info, name)) + + def resource_listdir(self, resource_name): + return self._listdir(self._fn(self.module_path, resource_name)) + + def metadata_listdir(self, name): + if self.egg_info: + return self._listdir(self._fn(self.egg_info, name)) + return [] + + def run_script(self, script_name, namespace): + script = 'scripts/' + script_name + if not self.has_metadata(script): + raise ResolutionError( + "Script {script!r} not found in metadata at {self.egg_info!r}" + .format(**locals()), + ) + script_text = self.get_metadata(script).replace('\r\n', '\n') + script_text = script_text.replace('\r', '\n') + script_filename = self._fn(self.egg_info, script) + namespace['__file__'] = script_filename + if os.path.exists(script_filename): + source = open(script_filename).read() + code = compile(source, script_filename, 'exec') + exec(code, namespace, namespace) + else: + from linecache import cache + cache[script_filename] = ( + len(script_text), 0, script_text.split('\n'), script_filename + ) + script_code = compile(script_text, script_filename, 'exec') + exec(script_code, namespace, namespace) + + def _has(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _isdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _listdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _fn(self, base, resource_name): + self._validate_resource_path(resource_name) + if resource_name: + return os.path.join(base, *resource_name.split('/')) + return base + + @staticmethod + def _validate_resource_path(path): + """ + Validate the resource paths according to the docs. + https://setuptools.readthedocs.io/en/latest/pkg_resources.html#basic-resource-access + + >>> warned = getfixture('recwarn') + >>> warnings.simplefilter('always') + >>> vrp = NullProvider._validate_resource_path + >>> vrp('foo/bar.txt') + >>> bool(warned) + False + >>> vrp('../foo/bar.txt') + >>> bool(warned) + True + >>> warned.clear() + >>> vrp('/foo/bar.txt') + >>> bool(warned) + True + >>> vrp('foo/../../bar.txt') + >>> bool(warned) + True + >>> warned.clear() + >>> vrp('foo/f../bar.txt') + >>> bool(warned) + False + + Windows path separators are straight-up disallowed. + >>> vrp(r'\\foo/bar.txt') + Traceback (most recent call last): + ... + ValueError: Use of .. or absolute path in a resource path \ +is not allowed. + + >>> vrp(r'C:\\foo/bar.txt') + Traceback (most recent call last): + ... + ValueError: Use of .. or absolute path in a resource path \ +is not allowed. + + Blank values are allowed + + >>> vrp('') + >>> bool(warned) + False + + Non-string values are not. + + >>> vrp(None) + Traceback (most recent call last): + ... + AttributeError: ... + """ + invalid = ( + os.path.pardir in path.split(posixpath.sep) or + posixpath.isabs(path) or + ntpath.isabs(path) + ) + if not invalid: + return + + msg = "Use of .. or absolute path in a resource path is not allowed." + + # Aggressively disallow Windows absolute paths + if ntpath.isabs(path) and not posixpath.isabs(path): + raise ValueError(msg) + + # for compatibility, warn; in future + # raise ValueError(msg) + warnings.warn( + msg[:-1] + " and will raise exceptions in a future release.", + DeprecationWarning, + stacklevel=4, + ) + + def _get(self, path): + if hasattr(self.loader, 'get_data'): + return self.loader.get_data(path) + raise NotImplementedError( + "Can't perform this operation for loaders without 'get_data()'" + ) + + +register_loader_type(object, NullProvider) + + +class EggProvider(NullProvider): + """Provider based on a virtual filesystem""" + + def __init__(self, module): + NullProvider.__init__(self, module) + self._setup_prefix() + + def _setup_prefix(self): + # we assume here that our metadata may be nested inside a "basket" + # of multiple eggs; that's why we use module_path instead of .archive + path = self.module_path + old = None + while path != old: + if _is_egg_path(path): + self.egg_name = os.path.basename(path) + self.egg_info = os.path.join(path, 'EGG-INFO') + self.egg_root = path + break + old = path + path, base = os.path.split(path) + + +class DefaultProvider(EggProvider): + """Provides access to package resources in the filesystem""" + + def _has(self, path): + return os.path.exists(path) + + def _isdir(self, path): + return os.path.isdir(path) + + def _listdir(self, path): + return os.listdir(path) + + def get_resource_stream(self, manager, resource_name): + return open(self._fn(self.module_path, resource_name), 'rb') + + def _get(self, path): + with open(path, 'rb') as stream: + return stream.read() + + @classmethod + def _register(cls): + loader_names = 'SourceFileLoader', 'SourcelessFileLoader', + for name in loader_names: + loader_cls = getattr(importlib_machinery, name, type(None)) + register_loader_type(loader_cls, cls) + + +DefaultProvider._register() + + +class EmptyProvider(NullProvider): + """Provider that returns nothing for all requests""" + + module_path = None + + _isdir = _has = lambda self, path: False + + def _get(self, path): + return '' + + def _listdir(self, path): + return [] + + def __init__(self): + pass + + +empty_provider = EmptyProvider() + + +class ZipManifests(dict): + """ + zip manifest builder + """ + + @classmethod + def build(cls, path): + """ + Build a dictionary similar to the zipimport directory + caches, except instead of tuples, store ZipInfo objects. + + Use a platform-specific path separator (os.sep) for the path keys + for compatibility with pypy on Windows. + """ + with zipfile.ZipFile(path) as zfile: + items = ( + ( + name.replace('/', os.sep), + zfile.getinfo(name), + ) + for name in zfile.namelist() + ) + return dict(items) + + load = build + + +class MemoizedZipManifests(ZipManifests): + """ + Memoized zipfile manifests. + """ + manifest_mod = collections.namedtuple('manifest_mod', 'manifest mtime') + + def load(self, path): + """ + Load a manifest at path or return a suitable manifest already loaded. + """ + path = os.path.normpath(path) + mtime = os.stat(path).st_mtime + + if path not in self or self[path].mtime != mtime: + manifest = self.build(path) + self[path] = self.manifest_mod(manifest, mtime) + + return self[path].manifest + + +class ZipProvider(EggProvider): + """Resource support for zips and eggs""" + + eagers = None + _zip_manifests = MemoizedZipManifests() + + def __init__(self, module): + EggProvider.__init__(self, module) + self.zip_pre = self.loader.archive + os.sep + + def _zipinfo_name(self, fspath): + # Convert a virtual filename (full path to file) into a zipfile subpath + # usable with the zipimport directory cache for our target archive + fspath = fspath.rstrip(os.sep) + if fspath == self.loader.archive: + return '' + if fspath.startswith(self.zip_pre): + return fspath[len(self.zip_pre):] + raise AssertionError( + "%s is not a subpath of %s" % (fspath, self.zip_pre) + ) + + def _parts(self, zip_path): + # Convert a zipfile subpath into an egg-relative path part list. + # pseudo-fs path + fspath = self.zip_pre + zip_path + if fspath.startswith(self.egg_root + os.sep): + return fspath[len(self.egg_root) + 1:].split(os.sep) + raise AssertionError( + "%s is not a subpath of %s" % (fspath, self.egg_root) + ) + + @property + def zipinfo(self): + return self._zip_manifests.load(self.loader.archive) + + def get_resource_filename(self, manager, resource_name): + if not self.egg_name: + raise NotImplementedError( + "resource_filename() only supported for .egg, not .zip" + ) + # no need to lock for extraction, since we use temp names + zip_path = self._resource_to_zip(resource_name) + eagers = self._get_eager_resources() + if '/'.join(self._parts(zip_path)) in eagers: + for name in eagers: + self._extract_resource(manager, self._eager_to_zip(name)) + return self._extract_resource(manager, zip_path) + + @staticmethod + def _get_date_and_size(zip_stat): + size = zip_stat.file_size + # ymdhms+wday, yday, dst + date_time = zip_stat.date_time + (0, 0, -1) + # 1980 offset already done + timestamp = time.mktime(date_time) + return timestamp, size + + def _extract_resource(self, manager, zip_path): + + if zip_path in self._index(): + for name in self._index()[zip_path]: + last = self._extract_resource( + manager, os.path.join(zip_path, name) + ) + # return the extracted directory name + return os.path.dirname(last) + + timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) + + if not WRITE_SUPPORT: + raise IOError('"os.rename" and "os.unlink" are not supported ' + 'on this platform') + try: + + real_path = manager.get_cache_path( + self.egg_name, self._parts(zip_path) + ) + + if self._is_current(real_path, zip_path): + return real_path + + outf, tmpnam = _mkstemp( + ".$extract", + dir=os.path.dirname(real_path), + ) + os.write(outf, self.loader.get_data(zip_path)) + os.close(outf) + utime(tmpnam, (timestamp, timestamp)) + manager.postprocess(tmpnam, real_path) + + try: + rename(tmpnam, real_path) + + except os.error: + if os.path.isfile(real_path): + if self._is_current(real_path, zip_path): + # the file became current since it was checked above, + # so proceed. + return real_path + # Windows, del old file and retry + elif os.name == 'nt': + unlink(real_path) + rename(tmpnam, real_path) + return real_path + raise + + except os.error: + # report a user-friendly error + manager.extraction_error() + + return real_path + + def _is_current(self, file_path, zip_path): + """ + Return True if the file_path is current for this zip_path + """ + timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) + if not os.path.isfile(file_path): + return False + stat = os.stat(file_path) + if stat.st_size != size or stat.st_mtime != timestamp: + return False + # check that the contents match + zip_contents = self.loader.get_data(zip_path) + with open(file_path, 'rb') as f: + file_contents = f.read() + return zip_contents == file_contents + + def _get_eager_resources(self): + if self.eagers is None: + eagers = [] + for name in ('native_libs.txt', 'eager_resources.txt'): + if self.has_metadata(name): + eagers.extend(self.get_metadata_lines(name)) + self.eagers = eagers + return self.eagers + + def _index(self): + try: + return self._dirindex + except AttributeError: + ind = {} + for path in self.zipinfo: + parts = path.split(os.sep) + while parts: + parent = os.sep.join(parts[:-1]) + if parent in ind: + ind[parent].append(parts[-1]) + break + else: + ind[parent] = [parts.pop()] + self._dirindex = ind + return ind + + def _has(self, fspath): + zip_path = self._zipinfo_name(fspath) + return zip_path in self.zipinfo or zip_path in self._index() + + def _isdir(self, fspath): + return self._zipinfo_name(fspath) in self._index() + + def _listdir(self, fspath): + return list(self._index().get(self._zipinfo_name(fspath), ())) + + def _eager_to_zip(self, resource_name): + return self._zipinfo_name(self._fn(self.egg_root, resource_name)) + + def _resource_to_zip(self, resource_name): + return self._zipinfo_name(self._fn(self.module_path, resource_name)) + + +register_loader_type(zipimport.zipimporter, ZipProvider) + + +class FileMetadata(EmptyProvider): + """Metadata handler for standalone PKG-INFO files + + Usage:: + + metadata = FileMetadata("/path/to/PKG-INFO") + + This provider rejects all data and metadata requests except for PKG-INFO, + which is treated as existing, and will be the contents of the file at + the provided location. + """ + + def __init__(self, path): + self.path = path + + def _get_metadata_path(self, name): + return self.path + + def has_metadata(self, name): + return name == 'PKG-INFO' and os.path.isfile(self.path) + + def get_metadata(self, name): + if name != 'PKG-INFO': + raise KeyError("No metadata except PKG-INFO is available") + + with io.open(self.path, encoding='utf-8', errors="replace") as f: + metadata = f.read() + self._warn_on_replacement(metadata) + return metadata + + def _warn_on_replacement(self, metadata): + # Python 2.7 compat for: replacement_char = '�' + replacement_char = b'\xef\xbf\xbd'.decode('utf-8') + if replacement_char in metadata: + tmpl = "{self.path} could not be properly decoded in UTF-8" + msg = tmpl.format(**locals()) + warnings.warn(msg) + + def get_metadata_lines(self, name): + return yield_lines(self.get_metadata(name)) + + +class PathMetadata(DefaultProvider): + """Metadata provider for egg directories + + Usage:: + + # Development eggs: + + egg_info = "/path/to/PackageName.egg-info" + base_dir = os.path.dirname(egg_info) + metadata = PathMetadata(base_dir, egg_info) + dist_name = os.path.splitext(os.path.basename(egg_info))[0] + dist = Distribution(basedir, project_name=dist_name, metadata=metadata) + + # Unpacked egg directories: + + egg_path = "/path/to/PackageName-ver-pyver-etc.egg" + metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO')) + dist = Distribution.from_filename(egg_path, metadata=metadata) + """ + + def __init__(self, path, egg_info): + self.module_path = path + self.egg_info = egg_info + + +class EggMetadata(ZipProvider): + """Metadata provider for .egg files""" + + def __init__(self, importer): + """Create a metadata provider from a zipimporter""" + + self.zip_pre = importer.archive + os.sep + self.loader = importer + if importer.prefix: + self.module_path = os.path.join(importer.archive, importer.prefix) + else: + self.module_path = importer.archive + self._setup_prefix() + + +_declare_state('dict', _distribution_finders={}) + + +def register_finder(importer_type, distribution_finder): + """Register `distribution_finder` to find distributions in sys.path items + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `distribution_finder` is a callable that, passed a path + item and the importer instance, yields ``Distribution`` instances found on + that path item. See ``pkg_resources.find_on_path`` for an example.""" + _distribution_finders[importer_type] = distribution_finder + + +def find_distributions(path_item, only=False): + """Yield distributions accessible via `path_item`""" + importer = get_importer(path_item) + finder = _find_adapter(_distribution_finders, importer) + return finder(importer, path_item, only) + + +def find_eggs_in_zip(importer, path_item, only=False): + """ + Find eggs in zip files; possibly multiple nested eggs. + """ + if importer.archive.endswith('.whl'): + # wheels are not supported with this finder + # they don't have PKG-INFO metadata, and won't ever contain eggs + return + metadata = EggMetadata(importer) + if metadata.has_metadata('PKG-INFO'): + yield Distribution.from_filename(path_item, metadata=metadata) + if only: + # don't yield nested distros + return + for subitem in metadata.resource_listdir(''): + if _is_egg_path(subitem): + subpath = os.path.join(path_item, subitem) + dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath) + for dist in dists: + yield dist + elif subitem.lower().endswith('.dist-info'): + subpath = os.path.join(path_item, subitem) + submeta = EggMetadata(zipimport.zipimporter(subpath)) + submeta.egg_info = subpath + yield Distribution.from_location(path_item, subitem, submeta) + + +register_finder(zipimport.zipimporter, find_eggs_in_zip) + + +def find_nothing(importer, path_item, only=False): + return () + + +register_finder(object, find_nothing) + + +def _by_version_descending(names): + """ + Given a list of filenames, return them in descending order + by version number. + + >>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg' + >>> _by_version_descending(names) + ['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar'] + >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg' + >>> _by_version_descending(names) + ['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg'] + >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.post1.egg' + >>> _by_version_descending(names) + ['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg'] + """ + def _by_version(name): + """ + Parse each component of the filename + """ + name, ext = os.path.splitext(name) + parts = itertools.chain(name.split('-'), [ext]) + return [packaging.version.parse(part) for part in parts] + + return sorted(names, key=_by_version, reverse=True) + + +def find_on_path(importer, path_item, only=False): + """Yield distributions accessible on a sys.path directory""" + path_item = _normalize_cached(path_item) + + if _is_unpacked_egg(path_item): + yield Distribution.from_filename( + path_item, metadata=PathMetadata( + path_item, os.path.join(path_item, 'EGG-INFO') + ) + ) + return + + entries = safe_listdir(path_item) + + # for performance, before sorting by version, + # screen entries for only those that will yield + # distributions + filtered = ( + entry + for entry in entries + if dist_factory(path_item, entry, only) + ) + + # scan for .egg and .egg-info in directory + path_item_entries = _by_version_descending(filtered) + for entry in path_item_entries: + fullpath = os.path.join(path_item, entry) + factory = dist_factory(path_item, entry, only) + for dist in factory(fullpath): + yield dist + + +def dist_factory(path_item, entry, only): + """ + Return a dist_factory for a path_item and entry + """ + lower = entry.lower() + is_meta = any(map(lower.endswith, ('.egg-info', '.dist-info'))) + return ( + distributions_from_metadata + if is_meta else + find_distributions + if not only and _is_egg_path(entry) else + resolve_egg_link + if not only and lower.endswith('.egg-link') else + NoDists() + ) + + +class NoDists: + """ + >>> bool(NoDists()) + False + + >>> list(NoDists()('anything')) + [] + """ + def __bool__(self): + return False + if six.PY2: + __nonzero__ = __bool__ + + def __call__(self, fullpath): + return iter(()) + + +def safe_listdir(path): + """ + Attempt to list contents of path, but suppress some exceptions. + """ + try: + return os.listdir(path) + except (PermissionError, NotADirectoryError): + pass + except OSError as e: + # Ignore the directory if does not exist, not a directory or + # permission denied + ignorable = ( + e.errno in (errno.ENOTDIR, errno.EACCES, errno.ENOENT) + # Python 2 on Windows needs to be handled this way :( + or getattr(e, "winerror", None) == 267 + ) + if not ignorable: + raise + return () + + +def distributions_from_metadata(path): + root = os.path.dirname(path) + if os.path.isdir(path): + if len(os.listdir(path)) == 0: + # empty metadata dir; skip + return + metadata = PathMetadata(root, path) + else: + metadata = FileMetadata(path) + entry = os.path.basename(path) + yield Distribution.from_location( + root, entry, metadata, precedence=DEVELOP_DIST, + ) + + +def non_empty_lines(path): + """ + Yield non-empty lines from file at path + """ + with open(path) as f: + for line in f: + line = line.strip() + if line: + yield line + + +def resolve_egg_link(path): + """ + Given a path to an .egg-link, resolve distributions + present in the referenced path. + """ + referenced_paths = non_empty_lines(path) + resolved_paths = ( + os.path.join(os.path.dirname(path), ref) + for ref in referenced_paths + ) + dist_groups = map(find_distributions, resolved_paths) + return next(dist_groups, ()) + + +register_finder(pkgutil.ImpImporter, find_on_path) + +if hasattr(importlib_machinery, 'FileFinder'): + register_finder(importlib_machinery.FileFinder, find_on_path) + +_declare_state('dict', _namespace_handlers={}) +_declare_state('dict', _namespace_packages={}) + + +def register_namespace_handler(importer_type, namespace_handler): + """Register `namespace_handler` to declare namespace packages + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `namespace_handler` is a callable like this:: + + def namespace_handler(importer, path_entry, moduleName, module): + # return a path_entry to use for child packages + + Namespace handlers are only called if the importer object has already + agreed that it can handle the relevant path item, and they should only + return a subpath if the module __path__ does not already contain an + equivalent subpath. For an example namespace handler, see + ``pkg_resources.file_ns_handler``. + """ + _namespace_handlers[importer_type] = namespace_handler + + +def _handle_ns(packageName, path_item): + """Ensure that named package includes a subpath of path_item (if needed)""" + + importer = get_importer(path_item) + if importer is None: + return None + + # capture warnings due to #1111 + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + loader = importer.find_module(packageName) + + if loader is None: + return None + module = sys.modules.get(packageName) + if module is None: + module = sys.modules[packageName] = types.ModuleType(packageName) + module.__path__ = [] + _set_parent_ns(packageName) + elif not hasattr(module, '__path__'): + raise TypeError("Not a package:", packageName) + handler = _find_adapter(_namespace_handlers, importer) + subpath = handler(importer, path_item, packageName, module) + if subpath is not None: + path = module.__path__ + path.append(subpath) + loader.load_module(packageName) + _rebuild_mod_path(path, packageName, module) + return subpath + + +def _rebuild_mod_path(orig_path, package_name, module): + """ + Rebuild module.__path__ ensuring that all entries are ordered + corresponding to their sys.path order + """ + sys_path = [_normalize_cached(p) for p in sys.path] + + def safe_sys_path_index(entry): + """ + Workaround for #520 and #513. + """ + try: + return sys_path.index(entry) + except ValueError: + return float('inf') + + def position_in_sys_path(path): + """ + Return the ordinal of the path based on its position in sys.path + """ + path_parts = path.split(os.sep) + module_parts = package_name.count('.') + 1 + parts = path_parts[:-module_parts] + return safe_sys_path_index(_normalize_cached(os.sep.join(parts))) + + new_path = sorted(orig_path, key=position_in_sys_path) + new_path = [_normalize_cached(p) for p in new_path] + + if isinstance(module.__path__, list): + module.__path__[:] = new_path + else: + module.__path__ = new_path + + +def declare_namespace(packageName): + """Declare that package 'packageName' is a namespace package""" + + _imp.acquire_lock() + try: + if packageName in _namespace_packages: + return + + path = sys.path + parent, _, _ = packageName.rpartition('.') + + if parent: + declare_namespace(parent) + if parent not in _namespace_packages: + __import__(parent) + try: + path = sys.modules[parent].__path__ + except AttributeError: + raise TypeError("Not a package:", parent) + + # Track what packages are namespaces, so when new path items are added, + # they can be updated + _namespace_packages.setdefault(parent or None, []).append(packageName) + _namespace_packages.setdefault(packageName, []) + + for path_item in path: + # Ensure all the parent's path items are reflected in the child, + # if they apply + _handle_ns(packageName, path_item) + + finally: + _imp.release_lock() + + +def fixup_namespace_packages(path_item, parent=None): + """Ensure that previously-declared namespace packages include path_item""" + _imp.acquire_lock() + try: + for package in _namespace_packages.get(parent, ()): + subpath = _handle_ns(package, path_item) + if subpath: + fixup_namespace_packages(subpath, package) + finally: + _imp.release_lock() + + +def file_ns_handler(importer, path_item, packageName, module): + """Compute an ns-package subpath for a filesystem or zipfile importer""" + + subpath = os.path.join(path_item, packageName.split('.')[-1]) + normalized = _normalize_cached(subpath) + for item in module.__path__: + if _normalize_cached(item) == normalized: + break + else: + # Only return the path if it's not already there + return subpath + + +register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) +register_namespace_handler(zipimport.zipimporter, file_ns_handler) + +if hasattr(importlib_machinery, 'FileFinder'): + register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler) + + +def null_ns_handler(importer, path_item, packageName, module): + return None + + +register_namespace_handler(object, null_ns_handler) + + +def normalize_path(filename): + """Normalize a file/dir name for comparison purposes""" + return os.path.normcase(os.path.realpath(os.path.normpath(_cygwin_patch(filename)))) + + +def _cygwin_patch(filename): # pragma: nocover + """ + Contrary to POSIX 2008, on Cygwin, getcwd (3) contains + symlink components. Using + os.path.abspath() works around this limitation. A fix in os.getcwd() + would probably better, in Cygwin even more so, except + that this seems to be by design... + """ + return os.path.abspath(filename) if sys.platform == 'cygwin' else filename + + +def _normalize_cached(filename, _cache={}): + try: + return _cache[filename] + except KeyError: + _cache[filename] = result = normalize_path(filename) + return result + + +def _is_egg_path(path): + """ + Determine if given path appears to be an egg. + """ + return path.lower().endswith('.egg') + + +def _is_unpacked_egg(path): + """ + Determine if given path appears to be an unpacked egg. + """ + return ( + _is_egg_path(path) and + os.path.isfile(os.path.join(path, 'EGG-INFO', 'PKG-INFO')) + ) + + +def _set_parent_ns(packageName): + parts = packageName.split('.') + name = parts.pop() + if parts: + parent = '.'.join(parts) + setattr(sys.modules[parent], name, sys.modules[packageName]) + + +def yield_lines(strs): + """Yield non-empty/non-comment lines of a string or sequence""" + if isinstance(strs, six.string_types): + for s in strs.splitlines(): + s = s.strip() + # skip blank lines/comments + if s and not s.startswith('#'): + yield s + else: + for ss in strs: + for s in yield_lines(ss): + yield s + + +MODULE = re.compile(r"\w+(\.\w+)*$").match +EGG_NAME = re.compile( + r""" + (?P[^-]+) ( + -(?P[^-]+) ( + -py(?P[^-]+) ( + -(?P.+) + )? + )? + )? + """, + re.VERBOSE | re.IGNORECASE, +).match + + +class EntryPoint: + """Object representing an advertised importable object""" + + def __init__(self, name, module_name, attrs=(), extras=(), dist=None): + if not MODULE(module_name): + raise ValueError("Invalid module name", module_name) + self.name = name + self.module_name = module_name + self.attrs = tuple(attrs) + self.extras = tuple(extras) + self.dist = dist + + def __str__(self): + s = "%s = %s" % (self.name, self.module_name) + if self.attrs: + s += ':' + '.'.join(self.attrs) + if self.extras: + s += ' [%s]' % ','.join(self.extras) + return s + + def __repr__(self): + return "EntryPoint.parse(%r)" % str(self) + + def load(self, require=True, *args, **kwargs): + """ + Require packages for this EntryPoint, then resolve it. + """ + if not require or args or kwargs: + warnings.warn( + "Parameters to load are deprecated. Call .resolve and " + ".require separately.", + PkgResourcesDeprecationWarning, + stacklevel=2, + ) + if require: + self.require(*args, **kwargs) + return self.resolve() + + def resolve(self): + """ + Resolve the entry point from its module and attrs. + """ + module = __import__(self.module_name, fromlist=['__name__'], level=0) + try: + return functools.reduce(getattr, self.attrs, module) + except AttributeError as exc: + raise ImportError(str(exc)) + + def require(self, env=None, installer=None): + if self.extras and not self.dist: + raise UnknownExtra("Can't require() without a distribution", self) + + # Get the requirements for this entry point with all its extras and + # then resolve them. We have to pass `extras` along when resolving so + # that the working set knows what extras we want. Otherwise, for + # dist-info distributions, the working set will assume that the + # requirements for that extra are purely optional and skip over them. + reqs = self.dist.requires(self.extras) + items = working_set.resolve(reqs, env, installer, extras=self.extras) + list(map(working_set.add, items)) + + pattern = re.compile( + r'\s*' + r'(?P.+?)\s*' + r'=\s*' + r'(?P[\w.]+)\s*' + r'(:\s*(?P[\w.]+))?\s*' + r'(?P\[.*\])?\s*$' + ) + + @classmethod + def parse(cls, src, dist=None): + """Parse a single entry point from string `src` + + Entry point syntax follows the form:: + + name = some.module:some.attr [extra1, extra2] + + The entry name and module name are required, but the ``:attrs`` and + ``[extras]`` parts are optional + """ + m = cls.pattern.match(src) + if not m: + msg = "EntryPoint must be in 'name=module:attrs [extras]' format" + raise ValueError(msg, src) + res = m.groupdict() + extras = cls._parse_extras(res['extras']) + attrs = res['attr'].split('.') if res['attr'] else () + return cls(res['name'], res['module'], attrs, extras, dist) + + @classmethod + def _parse_extras(cls, extras_spec): + if not extras_spec: + return () + req = Requirement.parse('x' + extras_spec) + if req.specs: + raise ValueError() + return req.extras + + @classmethod + def parse_group(cls, group, lines, dist=None): + """Parse an entry point group""" + if not MODULE(group): + raise ValueError("Invalid group name", group) + this = {} + for line in yield_lines(lines): + ep = cls.parse(line, dist) + if ep.name in this: + raise ValueError("Duplicate entry point", group, ep.name) + this[ep.name] = ep + return this + + @classmethod + def parse_map(cls, data, dist=None): + """Parse a map of entry point groups""" + if isinstance(data, dict): + data = data.items() + else: + data = split_sections(data) + maps = {} + for group, lines in data: + if group is None: + if not lines: + continue + raise ValueError("Entry points must be listed in groups") + group = group.strip() + if group in maps: + raise ValueError("Duplicate group name", group) + maps[group] = cls.parse_group(group, lines, dist) + return maps + + +def _remove_md5_fragment(location): + if not location: + return '' + parsed = urllib.parse.urlparse(location) + if parsed[-1].startswith('md5='): + return urllib.parse.urlunparse(parsed[:-1] + ('',)) + return location + + +def _version_from_file(lines): + """ + Given an iterable of lines from a Metadata file, return + the value of the Version field, if present, or None otherwise. + """ + def is_version_line(line): + return line.lower().startswith('version:') + version_lines = filter(is_version_line, lines) + line = next(iter(version_lines), '') + _, _, value = line.partition(':') + return safe_version(value.strip()) or None + + +class Distribution: + """Wrap an actual or potential sys.path entry w/metadata""" + PKG_INFO = 'PKG-INFO' + + def __init__( + self, location=None, metadata=None, project_name=None, + version=None, py_version=PY_MAJOR, platform=None, + precedence=EGG_DIST): + self.project_name = safe_name(project_name or 'Unknown') + if version is not None: + self._version = safe_version(version) + self.py_version = py_version + self.platform = platform + self.location = location + self.precedence = precedence + self._provider = metadata or empty_provider + + @classmethod + def from_location(cls, location, basename, metadata=None, **kw): + project_name, version, py_version, platform = [None] * 4 + basename, ext = os.path.splitext(basename) + if ext.lower() in _distributionImpl: + cls = _distributionImpl[ext.lower()] + + match = EGG_NAME(basename) + if match: + project_name, version, py_version, platform = match.group( + 'name', 'ver', 'pyver', 'plat' + ) + return cls( + location, metadata, project_name=project_name, version=version, + py_version=py_version, platform=platform, **kw + )._reload_version() + + def _reload_version(self): + return self + + @property + def hashcmp(self): + return ( + self.parsed_version, + self.precedence, + self.key, + _remove_md5_fragment(self.location), + self.py_version or '', + self.platform or '', + ) + + def __hash__(self): + return hash(self.hashcmp) + + def __lt__(self, other): + return self.hashcmp < other.hashcmp + + def __le__(self, other): + return self.hashcmp <= other.hashcmp + + def __gt__(self, other): + return self.hashcmp > other.hashcmp + + def __ge__(self, other): + return self.hashcmp >= other.hashcmp + + def __eq__(self, other): + if not isinstance(other, self.__class__): + # It's not a Distribution, so they are not equal + return False + return self.hashcmp == other.hashcmp + + def __ne__(self, other): + return not self == other + + # These properties have to be lazy so that we don't have to load any + # metadata until/unless it's actually needed. (i.e., some distributions + # may not know their name or version without loading PKG-INFO) + + @property + def key(self): + try: + return self._key + except AttributeError: + self._key = key = self.project_name.lower() + return key + + @property + def parsed_version(self): + if not hasattr(self, "_parsed_version"): + self._parsed_version = parse_version(self.version) + + return self._parsed_version + + def _warn_legacy_version(self): + LV = packaging.version.LegacyVersion + is_legacy = isinstance(self._parsed_version, LV) + if not is_legacy: + return + + # While an empty version is technically a legacy version and + # is not a valid PEP 440 version, it's also unlikely to + # actually come from someone and instead it is more likely that + # it comes from setuptools attempting to parse a filename and + # including it in the list. So for that we'll gate this warning + # on if the version is anything at all or not. + if not self.version: + return + + tmpl = textwrap.dedent(""" + '{project_name} ({version})' is being parsed as a legacy, + non PEP 440, + version. You may find odd behavior and sort order. + In particular it will be sorted as less than 0.0. It + is recommended to migrate to PEP 440 compatible + versions. + """).strip().replace('\n', ' ') + + warnings.warn(tmpl.format(**vars(self)), PEP440Warning) + + @property + def version(self): + try: + return self._version + except AttributeError: + version = self._get_version() + if version is None: + path = self._get_metadata_path_for_display(self.PKG_INFO) + msg = ( + "Missing 'Version:' header and/or {} file at path: {}" + ).format(self.PKG_INFO, path) + raise ValueError(msg, self) + + return version + + @property + def _dep_map(self): + """ + A map of extra to its list of (direct) requirements + for this distribution, including the null extra. + """ + try: + return self.__dep_map + except AttributeError: + self.__dep_map = self._filter_extras(self._build_dep_map()) + return self.__dep_map + + @staticmethod + def _filter_extras(dm): + """ + Given a mapping of extras to dependencies, strip off + environment markers and filter out any dependencies + not matching the markers. + """ + for extra in list(filter(None, dm)): + new_extra = extra + reqs = dm.pop(extra) + new_extra, _, marker = extra.partition(':') + fails_marker = marker and ( + invalid_marker(marker) + or not evaluate_marker(marker) + ) + if fails_marker: + reqs = [] + new_extra = safe_extra(new_extra) or None + + dm.setdefault(new_extra, []).extend(reqs) + return dm + + def _build_dep_map(self): + dm = {} + for name in 'requires.txt', 'depends.txt': + for extra, reqs in split_sections(self._get_metadata(name)): + dm.setdefault(extra, []).extend(parse_requirements(reqs)) + return dm + + def requires(self, extras=()): + """List of Requirements needed for this distro if `extras` are used""" + dm = self._dep_map + deps = [] + deps.extend(dm.get(None, ())) + for ext in extras: + try: + deps.extend(dm[safe_extra(ext)]) + except KeyError: + raise UnknownExtra( + "%s has no such extra feature %r" % (self, ext) + ) + return deps + + def _get_metadata_path_for_display(self, name): + """ + Return the path to the given metadata file, if available. + """ + try: + # We need to access _get_metadata_path() on the provider object + # directly rather than through this class's __getattr__() + # since _get_metadata_path() is marked private. + path = self._provider._get_metadata_path(name) + + # Handle exceptions e.g. in case the distribution's metadata + # provider doesn't support _get_metadata_path(). + except Exception: + return '[could not detect]' + + return path + + def _get_metadata(self, name): + if self.has_metadata(name): + for line in self.get_metadata_lines(name): + yield line + + def _get_version(self): + lines = self._get_metadata(self.PKG_INFO) + version = _version_from_file(lines) + + return version + + def activate(self, path=None, replace=False): + """Ensure distribution is importable on `path` (default=sys.path)""" + if path is None: + path = sys.path + self.insert_on(path, replace=replace) + if path is sys.path: + fixup_namespace_packages(self.location) + for pkg in self._get_metadata('namespace_packages.txt'): + if pkg in sys.modules: + declare_namespace(pkg) + + def egg_name(self): + """Return what this distribution's standard .egg filename should be""" + filename = "%s-%s-py%s" % ( + to_filename(self.project_name), to_filename(self.version), + self.py_version or PY_MAJOR + ) + + if self.platform: + filename += '-' + self.platform + return filename + + def __repr__(self): + if self.location: + return "%s (%s)" % (self, self.location) + else: + return str(self) + + def __str__(self): + try: + version = getattr(self, 'version', None) + except ValueError: + version = None + version = version or "[unknown version]" + return "%s %s" % (self.project_name, version) + + def __getattr__(self, attr): + """Delegate all unrecognized public attributes to .metadata provider""" + if attr.startswith('_'): + raise AttributeError(attr) + return getattr(self._provider, attr) + + def __dir__(self): + return list( + set(super(Distribution, self).__dir__()) + | set( + attr for attr in self._provider.__dir__() + if not attr.startswith('_') + ) + ) + + if not hasattr(object, '__dir__'): + # python 2.7 not supported + del __dir__ + + @classmethod + def from_filename(cls, filename, metadata=None, **kw): + return cls.from_location( + _normalize_cached(filename), os.path.basename(filename), metadata, + **kw + ) + + def as_requirement(self): + """Return a ``Requirement`` that matches this distribution exactly""" + if isinstance(self.parsed_version, packaging.version.Version): + spec = "%s==%s" % (self.project_name, self.parsed_version) + else: + spec = "%s===%s" % (self.project_name, self.parsed_version) + + return Requirement.parse(spec) + + def load_entry_point(self, group, name): + """Return the `name` entry point of `group` or raise ImportError""" + ep = self.get_entry_info(group, name) + if ep is None: + raise ImportError("Entry point %r not found" % ((group, name),)) + return ep.load() + + def get_entry_map(self, group=None): + """Return the entry point map for `group`, or the full entry map""" + try: + ep_map = self._ep_map + except AttributeError: + ep_map = self._ep_map = EntryPoint.parse_map( + self._get_metadata('entry_points.txt'), self + ) + if group is not None: + return ep_map.get(group, {}) + return ep_map + + def get_entry_info(self, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return self.get_entry_map(group).get(name) + + def insert_on(self, path, loc=None, replace=False): + """Ensure self.location is on path + + If replace=False (default): + - If location is already in path anywhere, do nothing. + - Else: + - If it's an egg and its parent directory is on path, + insert just ahead of the parent. + - Else: add to the end of path. + If replace=True: + - If location is already on path anywhere (not eggs) + or higher priority than its parent (eggs) + do nothing. + - Else: + - If it's an egg and its parent directory is on path, + insert just ahead of the parent, + removing any lower-priority entries. + - Else: add it to the front of path. + """ + + loc = loc or self.location + if not loc: + return + + nloc = _normalize_cached(loc) + bdir = os.path.dirname(nloc) + npath = [(p and _normalize_cached(p) or p) for p in path] + + for p, item in enumerate(npath): + if item == nloc: + if replace: + break + else: + # don't modify path (even removing duplicates) if + # found and not replace + return + elif item == bdir and self.precedence == EGG_DIST: + # if it's an .egg, give it precedence over its directory + # UNLESS it's already been added to sys.path and replace=False + if (not replace) and nloc in npath[p:]: + return + if path is sys.path: + self.check_version_conflict() + path.insert(p, loc) + npath.insert(p, nloc) + break + else: + if path is sys.path: + self.check_version_conflict() + if replace: + path.insert(0, loc) + else: + path.append(loc) + return + + # p is the spot where we found or inserted loc; now remove duplicates + while True: + try: + np = npath.index(nloc, p + 1) + except ValueError: + break + else: + del npath[np], path[np] + # ha! + p = np + + return + + def check_version_conflict(self): + if self.key == 'setuptools': + # ignore the inevitable setuptools self-conflicts :( + return + + nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt')) + loc = normalize_path(self.location) + for modname in self._get_metadata('top_level.txt'): + if (modname not in sys.modules or modname in nsp + or modname in _namespace_packages): + continue + if modname in ('pkg_resources', 'setuptools', 'site'): + continue + fn = getattr(sys.modules[modname], '__file__', None) + if fn and (normalize_path(fn).startswith(loc) or + fn.startswith(self.location)): + continue + issue_warning( + "Module %s was already imported from %s, but %s is being added" + " to sys.path" % (modname, fn, self.location), + ) + + def has_version(self): + try: + self.version + except ValueError: + issue_warning("Unbuilt egg for " + repr(self)) + return False + return True + + def clone(self, **kw): + """Copy this distribution, substituting in any changed keyword args""" + names = 'project_name version py_version platform location precedence' + for attr in names.split(): + kw.setdefault(attr, getattr(self, attr, None)) + kw.setdefault('metadata', self._provider) + return self.__class__(**kw) + + @property + def extras(self): + return [dep for dep in self._dep_map if dep] + + +class EggInfoDistribution(Distribution): + def _reload_version(self): + """ + Packages installed by distutils (e.g. numpy or scipy), + which uses an old safe_version, and so + their version numbers can get mangled when + converted to filenames (e.g., 1.11.0.dev0+2329eae to + 1.11.0.dev0_2329eae). These distributions will not be + parsed properly + downstream by Distribution and safe_version, so + take an extra step and try to get the version number from + the metadata file itself instead of the filename. + """ + md_version = self._get_version() + if md_version: + self._version = md_version + return self + + +class DistInfoDistribution(Distribution): + """ + Wrap an actual or potential sys.path entry + w/metadata, .dist-info style. + """ + PKG_INFO = 'METADATA' + EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])") + + @property + def _parsed_pkg_info(self): + """Parse and cache metadata""" + try: + return self._pkg_info + except AttributeError: + metadata = self.get_metadata(self.PKG_INFO) + self._pkg_info = email.parser.Parser().parsestr(metadata) + return self._pkg_info + + @property + def _dep_map(self): + try: + return self.__dep_map + except AttributeError: + self.__dep_map = self._compute_dependencies() + return self.__dep_map + + def _compute_dependencies(self): + """Recompute this distribution's dependencies.""" + dm = self.__dep_map = {None: []} + + reqs = [] + # Including any condition expressions + for req in self._parsed_pkg_info.get_all('Requires-Dist') or []: + reqs.extend(parse_requirements(req)) + + def reqs_for_extra(extra): + for req in reqs: + if not req.marker or req.marker.evaluate({'extra': extra}): + yield req + + common = frozenset(reqs_for_extra(None)) + dm[None].extend(common) + + for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []: + s_extra = safe_extra(extra.strip()) + dm[s_extra] = list(frozenset(reqs_for_extra(extra)) - common) + + return dm + + +_distributionImpl = { + '.egg': Distribution, + '.egg-info': EggInfoDistribution, + '.dist-info': DistInfoDistribution, +} + + +def issue_warning(*args, **kw): + level = 1 + g = globals() + try: + # find the first stack frame that is *not* code in + # the pkg_resources module, to use for the warning + while sys._getframe(level).f_globals is g: + level += 1 + except ValueError: + pass + warnings.warn(stacklevel=level + 1, *args, **kw) + + +class RequirementParseError(ValueError): + def __str__(self): + return ' '.join(self.args) + + +def parse_requirements(strs): + """Yield ``Requirement`` objects for each specification in `strs` + + `strs` must be a string, or a (possibly-nested) iterable thereof. + """ + # create a steppable iterator, so we can handle \-continuations + lines = iter(yield_lines(strs)) + + for line in lines: + # Drop comments -- a hash without a space may be in a URL. + if ' #' in line: + line = line[:line.find(' #')] + # If there is a line continuation, drop it, and append the next line. + if line.endswith('\\'): + line = line[:-2].strip() + try: + line += next(lines) + except StopIteration: + return + yield Requirement(line) + + +class Requirement(packaging.requirements.Requirement): + def __init__(self, requirement_string): + """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!""" + try: + super(Requirement, self).__init__(requirement_string) + except packaging.requirements.InvalidRequirement as e: + raise RequirementParseError(str(e)) + self.unsafe_name = self.name + project_name = safe_name(self.name) + self.project_name, self.key = project_name, project_name.lower() + self.specs = [ + (spec.operator, spec.version) for spec in self.specifier] + self.extras = tuple(map(safe_extra, self.extras)) + self.hashCmp = ( + self.key, + self.url, + self.specifier, + frozenset(self.extras), + str(self.marker) if self.marker else None, + ) + self.__hash = hash(self.hashCmp) + + def __eq__(self, other): + return ( + isinstance(other, Requirement) and + self.hashCmp == other.hashCmp + ) + + def __ne__(self, other): + return not self == other + + def __contains__(self, item): + if isinstance(item, Distribution): + if item.key != self.key: + return False + + item = item.version + + # Allow prereleases always in order to match the previous behavior of + # this method. In the future this should be smarter and follow PEP 440 + # more accurately. + return self.specifier.contains(item, prereleases=True) + + def __hash__(self): + return self.__hash + + def __repr__(self): + return "Requirement.parse(%r)" % str(self) + + @staticmethod + def parse(s): + req, = parse_requirements(s) + return req + + +def _always_object(classes): + """ + Ensure object appears in the mro even + for old-style classes. + """ + if object not in classes: + return classes + (object,) + return classes + + +def _find_adapter(registry, ob): + """Return an adapter factory for `ob` from `registry`""" + types = _always_object(inspect.getmro(getattr(ob, '__class__', type(ob)))) + for t in types: + if t in registry: + return registry[t] + + +def ensure_directory(path): + """Ensure that the parent directory of `path` exists""" + dirname = os.path.dirname(path) + py31compat.makedirs(dirname, exist_ok=True) + + +def _bypass_ensure_directory(path): + """Sandbox-bypassing version of ensure_directory()""" + if not WRITE_SUPPORT: + raise IOError('"os.mkdir" not supported on this platform.') + dirname, filename = split(path) + if dirname and filename and not isdir(dirname): + _bypass_ensure_directory(dirname) + try: + mkdir(dirname, 0o755) + except FileExistsError: + pass + + +def split_sections(s): + """Split a string or iterable thereof into (section, content) pairs + + Each ``section`` is a stripped version of the section header ("[section]") + and each ``content`` is a list of stripped lines excluding blank lines and + comment-only lines. If there are any such lines before the first section + header, they're returned in a first ``section`` of ``None``. + """ + section = None + content = [] + for line in yield_lines(s): + if line.startswith("["): + if line.endswith("]"): + if section or content: + yield section, content + section = line[1:-1].strip() + content = [] + else: + raise ValueError("Invalid section heading", line) + else: + content.append(line) + + # wrap up last segment + yield section, content + + +def _mkstemp(*args, **kw): + old_open = os.open + try: + # temporarily bypass sandboxing + os.open = os_open + return tempfile.mkstemp(*args, **kw) + finally: + # and then put it back + os.open = old_open + + +# Silence the PEP440Warning by default, so that end users don't get hit by it +# randomly just because they use pkg_resources. We want to append the rule +# because we want earlier uses of filterwarnings to take precedence over this +# one. +warnings.filterwarnings("ignore", category=PEP440Warning, append=True) + + +# from jaraco.functools 1.3 +def _call_aside(f, *args, **kwargs): + f(*args, **kwargs) + return f + + +@_call_aside +def _initialize(g=globals()): + "Set up global resource manager (deliberately not state-saved)" + manager = ResourceManager() + g['_manager'] = manager + g.update( + (name, getattr(manager, name)) + for name in dir(manager) + if not name.startswith('_') + ) + + +@_call_aside +def _initialize_master_working_set(): + """ + Prepare the master working set and make the ``require()`` + API available. + + This function has explicit effects on the global state + of pkg_resources. It is intended to be invoked once at + the initialization of this module. + + Invocation by other packages is unsupported and done + at their own risk. + """ + working_set = WorkingSet._build_master() + _declare_state('object', working_set=working_set) + + require = working_set.require + iter_entry_points = working_set.iter_entry_points + add_activation_listener = working_set.subscribe + run_script = working_set.run_script + # backward compatibility + run_main = run_script + # Activate all distributions already on sys.path with replace=False and + # ensure that all distributions added to the working set in the future + # (e.g. by calling ``require()``) will get activated as well, + # with higher priority (replace=True). + tuple( + dist.activate(replace=False) + for dist in working_set + ) + add_activation_listener( + lambda dist: dist.activate(replace=True), + existing=False, + ) + working_set.entries = [] + # match order + list(map(working_set.add_entry, sys.path)) + globals().update(locals()) + +class PkgResourcesDeprecationWarning(Warning): + """ + Base class for warning about deprecations in ``pkg_resources`` + + This class is not derived from ``DeprecationWarning``, and as such is + visible by default. + """ diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d2bb2c302543e68aeaa941068eb33d078235d76a GIT binary patch literal 100401 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 Vlgls3ugWj&2PSANWzD(%e*t{4aq<8F literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/__pycache__/py31compat.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/__pycache__/py31compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26c94ed9ab54d215d7a3be20bd8f88344fe81fc3 GIT binary patch literal 666 zcmYjOJ&)5s5Zwx3IfheFy0|?9Pe7Qz9Ts$6o?-J zC4XsKs`OM8h}oPt-K_SFXZCsKX(sFUyNqnH`<)F1W50ZG(DmtjiYdNg>6Pax zKg1#xN+`LKRgeapsg4R&>l;r)2$rq-rD}s%wgVyw;hU7MHV1wWx{Ul3dl8up!U*$>XyJErdktPz{1ob3c> zmv^=thg-3fja&w$#L-vcoRR#U_#$-o%8%HHGSr-(#-S6&x~R%ZPz74oel?vS8gwBb zYU5gy$@}NiH?edTI{(SAN0R<*lZB}ufz_%oO|vu$ZH-PW<_SV= zY?6HjON6^BYY2)8v@M7*2MtK6WOxDkB3Tt5lX}xEj2;gkB(@-Ko#kaV2bcs-NYSv~xZdo){Mq<8@^dO4 zMgN3t0$Rhyx)!V(K#l&lLkTBepWSo43qY@aR_IU04K#qV*8(u~WIvM|(Dx;yhm}$1 XD|qBLZGGp6(-A${?X~#rzasbt(AJ?X literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1353f240460ef67db1af4bb045ccaff2440289fd GIT binary patch literal 221 zcmYk0F%H5o3`J9k0U`Au4AcV?5<;ASg#$#PwVKd0j*_&f0}Hp|N~|0KCMKK-Ed6i& zuP4i@EEj@DU*9V4XSV+-IP6(*#@2|VSQdx72)X{*=LVX31hm#rN@vn8l7kp(2>q3#a;gG#S&j0IX{8` literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__pycache__/appdirs.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__pycache__/appdirs.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66697ed11d31cff05e2dc5f58cb3434e82662c6d GIT binary patch literal 20538 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 J|LK=n`ae9ORu2FG literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__pycache__/pyparsing.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/__pycache__/pyparsing.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0d6e65772aeb5a2251ecf67e85a61175d5dade4 GIT binary patch literal 201374 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 for details and usage. +""" +# Dev Notes: +# - MSDN on where to store app data files: +# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120 +# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html +# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + +__version_info__ = (1, 4, 3) +__version__ = '.'.join(map(str, __version_info__)) + + +import sys +import os + +PY3 = sys.version_info[0] == 3 + +if PY3: + unicode = str + +if sys.platform.startswith('java'): + import platform + os_name = platform.java_ver()[3][0] + if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc. + system = 'win32' + elif os_name.startswith('Mac'): # "Mac OS X", etc. + system = 'darwin' + else: # "Linux", "SunOS", "FreeBSD", etc. + # Setting this to "linux2" is not ideal, but only Windows or Mac + # are actually checked for and the rest of the module expects + # *sys.platform* style strings. + system = 'linux2' +else: + system = sys.platform + + + +def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + + for a discussion of issues. + + Typical user data directories are: + Mac OS X: ~/Library/Application Support/ + Unix: ~/.local/share/ # or in $XDG_DATA_HOME, if defined + Win XP (not roaming): C:\Documents and Settings\\Application Data\\ + Win XP (roaming): C:\Documents and Settings\\Local Settings\Application Data\\ + Win 7 (not roaming): C:\Users\\AppData\Local\\ + Win 7 (roaming): C:\Users\\AppData\Roaming\\ + + For Unix, we follow the XDG spec and support $XDG_DATA_HOME. + That means, by default "~/.local/share/". + """ + if system == "win32": + if appauthor is None: + appauthor = appname + const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" + path = os.path.normpath(_get_win_folder(const)) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('~/Library/Application Support/') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of data dirs should be + returned. By default, the first item from XDG_DATA_DIRS is + returned, or '/usr/local/share/', + if XDG_DATA_DIRS is not set + + Typical site data directories are: + Mac OS X: /Library/Application Support/ + Unix: /usr/local/share/ or /usr/share/ + Win XP: C:\Documents and Settings\All Users\Application Data\\ + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + Win 7: C:\ProgramData\\ # Hidden, but writeable on Win 7. + + For Unix, this is using the $XDG_DATA_DIRS[0] default. + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('/Library/Application Support') + if appname: + path = os.path.join(path, appname) + else: + # XDG default for $XDG_DATA_DIRS + # only first, if multipath is False + path = os.getenv('XDG_DATA_DIRS', + os.pathsep.join(['/usr/local/share', '/usr/share'])) + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + if appname and version: + path = os.path.join(path, version) + return path + + +def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific config dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + + for a discussion of issues. + + Typical user config directories are: + Mac OS X: same as user_data_dir + Unix: ~/.config/ # or in $XDG_CONFIG_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. + That means, by default "~/.config/". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_config_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of config dirs should be + returned. By default, the first item from XDG_CONFIG_DIRS is + returned, or '/etc/xdg/', if XDG_CONFIG_DIRS is not set + + Typical site config directories are: + Mac OS X: same as site_data_dir + Unix: /etc/xdg/ or $XDG_CONFIG_DIRS[i]/ for each value in + $XDG_CONFIG_DIRS + Win *: same as site_data_dir + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + + For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system in ["win32", "darwin"]: + path = site_data_dir(appname, appauthor) + if appname and version: + path = os.path.join(path, version) + else: + # XDG default for $XDG_CONFIG_DIRS + # only first, if multipath is False + path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + +def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific cache dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Cache" to the base app data dir for Windows. See + discussion below. + + Typical user cache directories are: + Mac OS X: ~/Library/Caches/ + Unix: ~/.cache/ (XDG default) + Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Cache + Vista: C:\Users\\AppData\Local\\\Cache + + On Windows the only suggestion in the MSDN docs is that local settings go in + the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming + app data dir (the default returned by `user_data_dir` above). Apps typically + put cache data somewhere *under* the given dir here. Some examples: + ...\Mozilla\Firefox\Profiles\\Cache + ...\Acme\SuperApp\Cache\1.0 + OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. + This can be disabled with the `opinion=False` option. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + if opinion: + path = os.path.join(path, "Cache") + elif system == 'darwin': + path = os.path.expanduser('~/Library/Caches') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_state_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific state dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + + for a discussion of issues. + + Typical user state directories are: + Mac OS X: same as user_data_dir + Unix: ~/.local/state/ # or in $XDG_STATE_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow this Debian proposal + to extend the XDG spec and support $XDG_STATE_HOME. + + That means, by default "~/.local/state/". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_STATE_HOME', os.path.expanduser("~/.local/state")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific log dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Logs" to the base app data dir for Windows, and "log" to the + base cache dir for Unix. See discussion below. + + Typical user log directories are: + Mac OS X: ~/Library/Logs/ + Unix: ~/.cache//log # or under $XDG_CACHE_HOME if defined + Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Logs + Vista: C:\Users\\AppData\Local\\\Logs + + On Windows the only suggestion in the MSDN docs is that local settings + go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in + examples of what some windows apps use for a logs dir.) + + OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` + value for Windows and appends "log" to the user cache dir for Unix. + This can be disabled with the `opinion=False` option. + """ + if system == "darwin": + path = os.path.join( + os.path.expanduser('~/Library/Logs'), + appname) + elif system == "win32": + path = user_data_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "Logs") + else: + path = user_cache_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "log") + if appname and version: + path = os.path.join(path, version) + return path + + +class AppDirs(object): + """Convenience wrapper for getting application dirs.""" + def __init__(self, appname=None, appauthor=None, version=None, + roaming=False, multipath=False): + self.appname = appname + self.appauthor = appauthor + self.version = version + self.roaming = roaming + self.multipath = multipath + + @property + def user_data_dir(self): + return user_data_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_data_dir(self): + return site_data_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_config_dir(self): + return user_config_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_config_dir(self): + return site_config_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_cache_dir(self): + return user_cache_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_state_dir(self): + return user_state_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_log_dir(self): + return user_log_dir(self.appname, self.appauthor, + version=self.version) + + +#---- internal support stuff + +def _get_win_folder_from_registry(csidl_name): + """This is a fallback technique at best. I'm not sure if using the + registry for this guarantees us the correct answer for all CSIDL_* + names. + """ + if PY3: + import winreg as _winreg + else: + import _winreg + + shell_folder_name = { + "CSIDL_APPDATA": "AppData", + "CSIDL_COMMON_APPDATA": "Common AppData", + "CSIDL_LOCAL_APPDATA": "Local AppData", + }[csidl_name] + + key = _winreg.OpenKey( + _winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" + ) + dir, type = _winreg.QueryValueEx(key, shell_folder_name) + return dir + + +def _get_win_folder_with_pywin32(csidl_name): + from win32com.shell import shellcon, shell + dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0) + # Try to make this a unicode path because SHGetFolderPath does + # not return unicode strings when there is unicode data in the + # path. + try: + dir = unicode(dir) + + # Downgrade to short path name if have highbit chars. See + # . + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + try: + import win32api + dir = win32api.GetShortPathName(dir) + except ImportError: + pass + except UnicodeError: + pass + return dir + + +def _get_win_folder_with_ctypes(csidl_name): + import ctypes + + csidl_const = { + "CSIDL_APPDATA": 26, + "CSIDL_COMMON_APPDATA": 35, + "CSIDL_LOCAL_APPDATA": 28, + }[csidl_name] + + buf = ctypes.create_unicode_buffer(1024) + ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) + + # Downgrade to short path name if have highbit chars. See + # . + has_high_char = False + for c in buf: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf2 = ctypes.create_unicode_buffer(1024) + if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): + buf = buf2 + + return buf.value + +def _get_win_folder_with_jna(csidl_name): + import array + from com.sun import jna + from com.sun.jna.platform import win32 + + buf_size = win32.WinDef.MAX_PATH * 2 + buf = array.zeros('c', buf_size) + shell = win32.Shell32.INSTANCE + shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf) + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + # Downgrade to short path name if have highbit chars. See + # . + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf = array.zeros('c', buf_size) + kernel = win32.Kernel32.INSTANCE + if kernel.GetShortPathName(dir, buf, buf_size): + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + return dir + +if system == "win32": + try: + import win32com.shell + _get_win_folder = _get_win_folder_with_pywin32 + except ImportError: + try: + from ctypes import windll + _get_win_folder = _get_win_folder_with_ctypes + except ImportError: + try: + import com.sun.jna + _get_win_folder = _get_win_folder_with_jna + except ImportError: + _get_win_folder = _get_win_folder_from_registry + + +#---- self test code + +if __name__ == "__main__": + appname = "MyApp" + appauthor = "MyCompany" + + props = ("user_data_dir", + "user_config_dir", + "user_cache_dir", + "user_state_dir", + "user_log_dir", + "site_data_dir", + "site_config_dir") + + print("-- app dirs %s --" % __version__) + + print("-- app dirs (with optional 'version')") + dirs = AppDirs(appname, appauthor, version="1.0") + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'version')") + dirs = AppDirs(appname, appauthor) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'appauthor')") + dirs = AppDirs(appname) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (with disabled 'appauthor')") + dirs = AppDirs(appname, appauthor=False) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__about__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__about__.py new file mode 100644 index 0000000..95d330e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__about__.py @@ -0,0 +1,21 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "16.8" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD or Apache License, Version 2.0" +__copyright__ = "Copyright 2014-2016 %s" % __author__ diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__init__.py new file mode 100644 index 0000000..5ee6220 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__init__.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +from .__about__ import ( + __author__, __copyright__, __email__, __license__, __summary__, __title__, + __uri__, __version__ +) + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2e75bb4c1d2ef9eaf52c09cb91567c0f1426eaf GIT binary patch literal 745 zcmYk4%Zd~+6oylMnXbO+ATsMX;G)5)%tZzjk`;qEMaW zN!`nPbwBSXs6@Q?J;?{WpAY#UKj6cB#1Hb6kMc23^9dj4Q$7*nBb3khbcGhP-%trH z`rSjec18s+sH_`feV1~%l};MnJ!q`do^FCJJj9E%8&m3~SAx=RN~sHV&Fl_>5v9S( zeReBs+zr8mQWkt=EUaOtsF_rIjgp1XE|!^7T9{^MWm)+sYglo^N~z2C_}W;3gO^Hr zDIDGyi$Ct5oW^^RaP5=I`^LQ@q?Eo2>#Q&}X?6`G_hklWm)VPUu{4?~j#oZxHXbw0 zvDC3q9+<*~(ca2+@W#6Kkl#wL+^sZ|ragYQT4MP7Tc}zI{C!+m9FkqHj!rCw3T92N9!)G-4bP--Vq<%m6=- zJ&fy!zu!n@YC(ij(s=*bRN5I$oGpkIjd6s15e@_=oOyt(!Ev}3QVK0Bq)4_EdP|gC zgJsdyi|i$F60~>rlIEtQ7K#L02uCRBxv}@&5;*&mb+VG&no7kCq1bEy_ Mhl2!W4`yWY4>!Byj{pDw literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..38e78fb9cde540865351b468dfc1fde37d3d68f4 GIT binary patch literal 583 zcmYk2yN=W_6o#E-E}2UfA@LAQ!MLD8LWq)zhR)5AC-x?0eTk0kK~wMsJOv%El$L6H zDk_dQ5?V|Cvm%2_G0f2;^2wI zbJSCaTz=D$1aFi~1mkFE8iWtpYa|yxU$wt-Yc71c(cb*q^E)05X(!n~$U#RwJq&=9 nBx6q&kX{Ak%eV0Z2Qc2y9Ovmax9?q0+3F8v##r#Ge!cz&T~VWw literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..acdb51b422067689e2da6d4e1ad9ca86f137cfda GIT binary patch literal 1045 zcmah{&1(}u6rYbxvW;mXSQI}F@gn5VEZCD!ilE@F2!h}u4AY%Svh993Gn?QEhcg;)6kXlNuj;7o1&JRh_K8e- zH-Jqh+>hjeEwkEbk>*utoDWsHOl?{geps2baAH;$i35B81{=G9j!8oC^(~>J3)};? zuRwetm*kSpn4*eZgo<6!bAHAg`9V*a;wnhV&j4EJoJ9RG&^x20(_=Y4kXDbAOj3MzYU9XcALJVzyp9=88k9;N&GDihp>!S((Vp?oIDpNzg#G z0(Im^z;*!Qik{Lda>~yUj_zLrrsqj!eNf0;`@UPGR^R~EQ+3UJr_}?5H@KNU-=jsD z>quu=S~_=FE(%)~ku^zVbXD3&9%~B;+X|Mktd1RwT-HyxiA1yn*=NY`KmNg8%~RPB$6_(q?=YN-xH$H$3nco`S7fS zo=pC`qUr6ceHcCj9VQpT_l3wyRcELVg!op=tc{q5fZGgjaD}Zl0?lvSZT&fzO#>k{ zTNoNSjsKxEE74rOc{O1^aH~o;h!bvx2)Bs>->j8r(1-U2!4%sZxA&NvCtytm*z~M+ zwSlG$&TsHnGMMGLU0FX^YJ>Y1X)!B3|M=xKiX8|#;|CyMp#od7zTcd>@igddJ9zW8 ZiNoD?M|)VpV*gt#f&q5M7cIMai-)Cob~QrbSMLfW`z`6iARFaM7YgF1jQqT^2NVEzzM!Wq0Mm zMsiXPx#f50FY%gF?mhLCH>)s}ZBlZJc7^?%*?l{+Gmnb4w>u1F{QA%6ZIiM0G+8YT zOb$`?uV@4lPRb_E(3!YHcj65_hyBikE4(*Mc(O6~hE3U=vtbjf4bjAE)2{l`$Eq*< zXRP1)fRk9?D|VwJou@M+c`}*i$`pY}P7|HvS+O%!NoM%*EQ<~1G3{6_E+&Vl`Z*fO zhK^uES2)6b!-k&lL<2qWg^#`|S|UL2i?-;XZ;36@MIVT5v4g%Xc0~_;N9>6k=(og8 z+;YDNo@U2MmYB2H0Z3VBO!XI3P0kSxwB3P%^VotdoT8y+daQg*ZS&W=aGXzMDAP2_ zjXBB3na;CNt2k70n(Hw7Lux2I5RpNXOk_qb2uCuL3QOU^smxBpG&u^VXJ(vdKO8&? zbpqXK6u*c@QiszQBd&1BOvRXS=!;y1OL3BoLavRP#bySbgXvijaA;2z=WViqT*;jC zz0%r)QhLQ~4~o|8E(V4f=M|efbC|zy1`D@nj3YfR8g#U3LE~>1C;}o_(%_u7SHUi& zvAqyfsL=R|w-@fe{PYvh0&?wP%SBxatW-Qgi_T|ZYpGWp> ztxbd>Ilobd0ofIdOKyAxH=a0i_Zd@LI0laFAO|vSqAZq08waG3)_9Z}eEE{|FKX~f zR*%1fU51tTUH0h)icYIT%V5#%8Z?q!L92Sb=W880!oz%713|LQ5b7>jU|*@mX(L?q z>pBcFgRWf`8ecHOl&ugDhTcTop@v+izM_THxQm(p(^Vhrn6WgA*AC%r(T3A6i)=z!9v1JtJ{Lba4`WIAZ zb5s$7RlT!)mG3q{UYF+9N3nhTa0TjCg>~2DxV7nG zf5iUs-Ks46Z<)o1gE}%S|ue>=6_3P)KC)12mKbY;_;0B$>4)XF{UWU6#Wk?{QT%d#%6g>(ysz4 Vf}fVG`h@mq`uni&_3rto9|0{N0D}Mk literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/markers.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/markers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..11614c95711d80cf9f993953e09472cf8d161ed7 GIT binary patch literal 8955 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42440b32c3b4cb9427ae4f0930e0da01bc84bd9e GIT binary patch literal 10666 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 WReWt*&K~EO>5e~k-Y*)?@c#klk(e3) literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/_compat.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/_compat.py new file mode 100644 index 0000000..210bb80 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/_compat.py @@ -0,0 +1,30 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import sys + + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +# flake8: noqa + +if PY3: + string_types = str, +else: + string_types = basestring, + + +def with_metaclass(meta, *bases): + """ + Create a base class with a metaclass. + """ + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/_structures.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/_structures.py new file mode 100644 index 0000000..ccc2786 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/_structures.py @@ -0,0 +1,68 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + + +class Infinity(object): + + def __repr__(self): + return "Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return False + + def __le__(self, other): + return False + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return True + + def __ge__(self, other): + return True + + def __neg__(self): + return NegativeInfinity + +Infinity = Infinity() + + +class NegativeInfinity(object): + + def __repr__(self): + return "-Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return True + + def __le__(self, other): + return True + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return False + + def __ge__(self, other): + return False + + def __neg__(self): + return Infinity + +NegativeInfinity = NegativeInfinity() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/markers.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/markers.py new file mode 100644 index 0000000..892e578 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/markers.py @@ -0,0 +1,301 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import operator +import os +import platform +import sys + +from pkg_resources.extern.pyparsing import ParseException, ParseResults, stringStart, stringEnd +from pkg_resources.extern.pyparsing import ZeroOrMore, Group, Forward, QuotedString +from pkg_resources.extern.pyparsing import Literal as L # noqa + +from ._compat import string_types +from .specifiers import Specifier, InvalidSpecifier + + +__all__ = [ + "InvalidMarker", "UndefinedComparison", "UndefinedEnvironmentName", + "Marker", "default_environment", +] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +class Node(object): + + def __init__(self, value): + self.value = value + + def __str__(self): + return str(self.value) + + def __repr__(self): + return "<{0}({1!r})>".format(self.__class__.__name__, str(self)) + + def serialize(self): + raise NotImplementedError + + +class Variable(Node): + + def serialize(self): + return str(self) + + +class Value(Node): + + def serialize(self): + return '"{0}"'.format(self) + + +class Op(Node): + + def serialize(self): + return str(self) + + +VARIABLE = ( + L("implementation_version") | + L("platform_python_implementation") | + L("implementation_name") | + L("python_full_version") | + L("platform_release") | + L("platform_version") | + L("platform_machine") | + L("platform_system") | + L("python_version") | + L("sys_platform") | + L("os_name") | + L("os.name") | # PEP-345 + L("sys.platform") | # PEP-345 + L("platform.version") | # PEP-345 + L("platform.machine") | # PEP-345 + L("platform.python_implementation") | # PEP-345 + L("python_implementation") | # undocumented setuptools legacy + L("extra") +) +ALIASES = { + 'os.name': 'os_name', + 'sys.platform': 'sys_platform', + 'platform.version': 'platform_version', + 'platform.machine': 'platform_machine', + 'platform.python_implementation': 'platform_python_implementation', + 'python_implementation': 'platform_python_implementation' +} +VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) + +VERSION_CMP = ( + L("===") | + L("==") | + L(">=") | + L("<=") | + L("!=") | + L("~=") | + L(">") | + L("<") +) + +MARKER_OP = VERSION_CMP | L("not in") | L("in") +MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) + +MARKER_VALUE = QuotedString("'") | QuotedString('"') +MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) + +BOOLOP = L("and") | L("or") + +MARKER_VAR = VARIABLE | MARKER_VALUE + +MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) +MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) + +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() + +MARKER_EXPR = Forward() +MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) +MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) + +MARKER = stringStart + MARKER_EXPR + stringEnd + + +def _coerce_parse_result(results): + if isinstance(results, ParseResults): + return [_coerce_parse_result(i) for i in results] + else: + return results + + +def _format_marker(marker, first=True): + assert isinstance(marker, (list, tuple, string_types)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if (isinstance(marker, list) and len(marker) == 1 and + isinstance(marker[0], (list, tuple))): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs, op, rhs): + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs) + + oper = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison( + "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs) + ) + + return oper(lhs, rhs) + + +_undefined = object() + + +def _get_env(environment, name): + value = environment.get(name, _undefined) + + if value is _undefined: + raise UndefinedEnvironmentName( + "{0!r} does not exist in evaluation environment.".format(name) + ) + + return value + + +def _evaluate_markers(markers, environment): + groups = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, string_types)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + lhs_value = _get_env(environment, lhs.value) + rhs_value = rhs.value + else: + lhs_value = lhs.value + rhs_value = _get_env(environment, rhs.value) + + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info): + version = '{0.major}.{0.minor}.{0.micro}'.format(info) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + +def default_environment(): + if hasattr(sys, 'implementation'): + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + iver = '0' + implementation_name = '' + + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": platform.python_version()[:3], + "sys_platform": sys.platform, + } + + +class Marker(object): + + def __init__(self, marker): + try: + self._markers = _coerce_parse_result(MARKER.parseString(marker)) + except ParseException as e: + err_str = "Invalid marker: {0!r}, parse error at {1!r}".format( + marker, marker[e.loc:e.loc + 8]) + raise InvalidMarker(err_str) + + def __str__(self): + return _format_marker(self._markers) + + def __repr__(self): + return "".format(str(self)) + + def evaluate(self, environment=None): + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = default_environment() + if environment is not None: + current_environment.update(environment) + + return _evaluate_markers(self._markers, current_environment) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/requirements.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/requirements.py new file mode 100644 index 0000000..0c8c4a3 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/requirements.py @@ -0,0 +1,127 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import string +import re + +from pkg_resources.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException +from pkg_resources.extern.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine +from pkg_resources.extern.pyparsing import Literal as L # noqa +from pkg_resources.extern.six.moves.urllib import parse as urlparse + +from .markers import MARKER_EXPR, Marker +from .specifiers import LegacySpecifier, Specifier, SpecifierSet + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +ALPHANUM = Word(string.ascii_letters + string.digits) + +LBRACKET = L("[").suppress() +RBRACKET = L("]").suppress() +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() +COMMA = L(",").suppress() +SEMICOLON = L(";").suppress() +AT = L("@").suppress() + +PUNCTUATION = Word("-_.") +IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM) +IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END)) + +NAME = IDENTIFIER("name") +EXTRA = IDENTIFIER + +URI = Regex(r'[^ ]+')("url") +URL = (AT + URI) + +EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA) +EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras") + +VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE) +VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE) + +VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY +VERSION_MANY = Combine(VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), + joinString=",", adjacent=False)("_raw_spec") +_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY)) +_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or '') + +VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier") +VERSION_SPEC.setParseAction(lambda s, l, t: t[1]) + +MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") +MARKER_EXPR.setParseAction( + lambda s, l, t: Marker(s[t._original_start:t._original_end]) +) +MARKER_SEPERATOR = SEMICOLON +MARKER = MARKER_SEPERATOR + MARKER_EXPR + +VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) +URL_AND_MARKER = URL + Optional(MARKER) + +NAMED_REQUIREMENT = \ + NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER) + +REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd + + +class Requirement(object): + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string): + try: + req = REQUIREMENT.parseString(requirement_string) + except ParseException as e: + raise InvalidRequirement( + "Invalid requirement, parse error at \"{0!r}\"".format( + requirement_string[e.loc:e.loc + 8])) + + self.name = req.name + if req.url: + parsed_url = urlparse.urlparse(req.url) + if not (parsed_url.scheme and parsed_url.netloc) or ( + not parsed_url.scheme and not parsed_url.netloc): + raise InvalidRequirement("Invalid URL given") + self.url = req.url + else: + self.url = None + self.extras = set(req.extras.asList() if req.extras else []) + self.specifier = SpecifierSet(req.specifier) + self.marker = req.marker if req.marker else None + + def __str__(self): + parts = [self.name] + + if self.extras: + parts.append("[{0}]".format(",".join(sorted(self.extras)))) + + if self.specifier: + parts.append(str(self.specifier)) + + if self.url: + parts.append("@ {0}".format(self.url)) + + if self.marker: + parts.append("; {0}".format(self.marker)) + + return "".join(parts) + + def __repr__(self): + return "".format(str(self)) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/specifiers.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/specifiers.py new file mode 100644 index 0000000..7f5a76c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/specifiers.py @@ -0,0 +1,774 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import abc +import functools +import itertools +import re + +from ._compat import string_types, with_metaclass +from .version import Version, LegacyVersion, parse + + +class InvalidSpecifier(ValueError): + """ + An invalid specifier was found, users should refer to PEP 440. + """ + + +class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): + + @abc.abstractmethod + def __str__(self): + """ + Returns the str representation of this Specifier like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self): + """ + Returns a hash value for this Specifier like object. + """ + + @abc.abstractmethod + def __eq__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are equal. + """ + + @abc.abstractmethod + def __ne__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are not equal. + """ + + @abc.abstractproperty + def prereleases(self): + """ + Returns whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @prereleases.setter + def prereleases(self, value): + """ + Sets whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @abc.abstractmethod + def contains(self, item, prereleases=None): + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter(self, iterable, prereleases=None): + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class _IndividualSpecifier(BaseSpecifier): + + _operators = {} + + def __init__(self, spec="", prereleases=None): + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec)) + + self._spec = ( + match.group("operator").strip(), + match.group("version").strip(), + ) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<{0}({1!r}{2})>".format( + self.__class__.__name__, + str(self), + pre, + ) + + def __str__(self): + return "{0}{1}".format(*self._spec) + + def __hash__(self): + return hash(self._spec) + + def __eq__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec == other._spec + + def __ne__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec != other._spec + + def _get_operator(self, op): + return getattr(self, "_compare_{0}".format(self._operators[op])) + + def _coerce_version(self, version): + if not isinstance(version, (LegacyVersion, Version)): + version = parse(version) + return version + + @property + def operator(self): + return self._spec[0] + + @property + def version(self): + return self._spec[1] + + @property + def prereleases(self): + return self._prereleases + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version or LegacyVersion, this allows us to have + # a shortcut for ``"2.0" in Specifier(">=2") + item = self._coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + return self._get_operator(self.operator)(item, self.version) + + def filter(self, iterable, prereleases=None): + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = self._coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later incase nothing + # else matches this specifier. + if (parsed_version.is_prerelease and not + (prereleases or self.prereleases)): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the begining. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +class LegacySpecifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P(==|!=|<=|>=|<|>)) + \s* + (?P + [^,;\s)]* # Since this is a "legacy" specifier, and the version + # string can be just about anything, we match everything + # except for whitespace, a semi-colon for marker support, + # a closing paren since versions can be enclosed in + # them, and a comma since it's a version separator. + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + } + + def _coerce_version(self, version): + if not isinstance(version, LegacyVersion): + version = LegacyVersion(str(version)) + return version + + def _compare_equal(self, prospective, spec): + return prospective == self._coerce_version(spec) + + def _compare_not_equal(self, prospective, spec): + return prospective != self._coerce_version(spec) + + def _compare_less_than_equal(self, prospective, spec): + return prospective <= self._coerce_version(spec) + + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= self._coerce_version(spec) + + def _compare_less_than(self, prospective, spec): + return prospective < self._coerce_version(spec) + + def _compare_greater_than(self, prospective, spec): + return prospective > self._coerce_version(spec) + + +def _require_version_compare(fn): + @functools.wraps(fn) + def wrapped(self, prospective, spec): + if not isinstance(prospective, Version): + return False + return fn(self, prospective, spec) + return wrapped + + +class Specifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P(~=|==|!=|<=|>=|<|>|===)) + (?P + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s]* # We just match everything, except for whitespace + # since we are only testing for strict identity. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + + # You cannot use a wild card and a dev or local version + # together so group them with a | and make them optional. + (?: + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + | + \.\* # Wild card syntax of .* + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + @_require_version_compare + def _compare_compatible(self, prospective, spec): + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore post and dev releases and we want to treat the pre-release as + # it's own separate segment. + prefix = ".".join( + list( + itertools.takewhile( + lambda x: (not x.startswith("post") and not + x.startswith("dev")), + _version_split(spec), + ) + )[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return (self._get_operator(">=")(prospective, spec) and + self._get_operator("==")(prospective, prefix)) + + @_require_version_compare + def _compare_equal(self, prospective, spec): + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + prospective = Version(prospective.public) + # Split the spec out by dots, and pretend that there is an implicit + # dot in between a release segment and a pre-release segment. + spec = _version_split(spec[:-2]) # Remove the trailing .* + + # Split the prospective version out by dots, and pretend that there + # is an implicit dot in between a release segment and a pre-release + # segment. + prospective = _version_split(str(prospective)) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + prospective = prospective[:len(spec)] + + # Pad out our two sides with zeros so that they both equal the same + # length. + spec, prospective = _pad_version(spec, prospective) + else: + # Convert our spec string into a Version + spec = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec.local: + prospective = Version(prospective.public) + + return prospective == spec + + @_require_version_compare + def _compare_not_equal(self, prospective, spec): + return not self._compare_equal(prospective, spec) + + @_require_version_compare + def _compare_less_than_equal(self, prospective, spec): + return prospective <= Version(spec) + + @_require_version_compare + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= Version(spec) + + @_require_version_compare + def _compare_less_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + @_require_version_compare + def _compare_greater_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is techincally greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective, spec): + return str(prospective).lower() == str(spec).lower() + + @property + def prereleases(self): + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "==="]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if parse(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version): + result = [] + for item in version.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _pad_version(left, right): + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]):]) + right_split.append(right[len(right_split[0]):]) + + # Insert our padding + left_split.insert( + 1, + ["0"] * max(0, len(right_split[0]) - len(left_split[0])), + ) + right_split.insert( + 1, + ["0"] * max(0, len(left_split[0]) - len(right_split[0])), + ) + + return ( + list(itertools.chain(*left_split)), + list(itertools.chain(*right_split)), + ) + + +class SpecifierSet(BaseSpecifier): + + def __init__(self, specifiers="", prereleases=None): + # Split on , to break each indidivual specifier into it's own item, and + # strip each item to remove leading/trailing whitespace. + specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Parsed each individual specifier, attempting first to make it a + # Specifier and falling back to a LegacySpecifier. + parsed = set() + for specifier in specifiers: + try: + parsed.add(Specifier(specifier)) + except InvalidSpecifier: + parsed.add(LegacySpecifier(specifier)) + + # Turn our parsed specifiers into a frozen set and save them for later. + self._specs = frozenset(parsed) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "".format(str(self), pre) + + def __str__(self): + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self): + return hash(self._specs) + + def __and__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __ne__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs != other._specs + + def __len__(self): + return len(self._specs) + + def __iter__(self): + return iter(self._specs) + + @property + def prereleases(self): + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Ensure that our item is a Version or LegacyVersion instance. + if not isinstance(item, (LegacyVersion, Version)): + item = parse(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all( + s.contains(item, prereleases=prereleases) + for s in self._specs + ) + + def filter(self, iterable, prereleases=None): + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iterable + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases, and which will filter out LegacyVersion in general. + else: + filtered = [] + found_prereleases = [] + + for item in iterable: + # Ensure that we some kind of Version class for this item. + if not isinstance(item, (LegacyVersion, Version)): + parsed_version = parse(item) + else: + parsed_version = item + + # Filter out any item which is parsed as a LegacyVersion + if isinstance(parsed_version, LegacyVersion): + continue + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return found_prereleases + + return filtered diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/utils.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/utils.py new file mode 100644 index 0000000..942387c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/utils.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import re + + +_canonicalize_regex = re.compile(r"[-_.]+") + + +def canonicalize_name(name): + # This is taken from PEP 503. + return _canonicalize_regex.sub("-", name).lower() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/version.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/version.py new file mode 100644 index 0000000..83b5ee8 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/version.py @@ -0,0 +1,393 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import collections +import itertools +import re + +from ._structures import Infinity + + +__all__ = [ + "parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN" +] + + +_Version = collections.namedtuple( + "_Version", + ["epoch", "release", "dev", "pre", "post", "local"], +) + + +def parse(version): + """ + Parse the given version string and return either a :class:`Version` object + or a :class:`LegacyVersion` object depending on if the given version is + a valid PEP 440 version or a legacy version. + """ + try: + return Version(version) + except InvalidVersion: + return LegacyVersion(version) + + +class InvalidVersion(ValueError): + """ + An invalid version was found, users should refer to PEP 440. + """ + + +class _BaseVersion(object): + + def __hash__(self): + return hash(self._key) + + def __lt__(self, other): + return self._compare(other, lambda s, o: s < o) + + def __le__(self, other): + return self._compare(other, lambda s, o: s <= o) + + def __eq__(self, other): + return self._compare(other, lambda s, o: s == o) + + def __ge__(self, other): + return self._compare(other, lambda s, o: s >= o) + + def __gt__(self, other): + return self._compare(other, lambda s, o: s > o) + + def __ne__(self, other): + return self._compare(other, lambda s, o: s != o) + + def _compare(self, other, method): + if not isinstance(other, _BaseVersion): + return NotImplemented + + return method(self._key, other._key) + + +class LegacyVersion(_BaseVersion): + + def __init__(self, version): + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + def __str__(self): + return self._version + + def __repr__(self): + return "".format(repr(str(self))) + + @property + def public(self): + return self._version + + @property + def base_version(self): + return self._version + + @property + def local(self): + return None + + @property + def is_prerelease(self): + return False + + @property + def is_postrelease(self): + return False + + +_legacy_version_component_re = re.compile( + r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE, +) + +_legacy_version_replacement_map = { + "pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@", +} + + +def _parse_version_parts(s): + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version): + # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # it's adoption of the packaging library. + parts = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + parts = tuple(parts) + + return epoch, parts + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +VERSION_PATTERN = r""" + v? + (?: + (?:(?P[0-9]+)!)? # epoch + (?P[0-9]+(?:\.[0-9]+)*) # release segment + (?P

                                          # pre-release
+            [-_\.]?
+            (?P(a|b|c|rc|alpha|beta|pre|preview))
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+        (?P                                         # post release
+            (?:-(?P[0-9]+))
+            |
+            (?:
+                [-_\.]?
+                (?Ppost|rev|r)
+                [-_\.]?
+                (?P[0-9]+)?
+            )
+        )?
+        (?P                                          # dev release
+            [-_\.]?
+            (?Pdev)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+    )
+    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
+"""
+
+
+class Version(_BaseVersion):
+
+    _regex = re.compile(
+        r"^\s*" + VERSION_PATTERN + r"\s*$",
+        re.VERBOSE | re.IGNORECASE,
+    )
+
+    def __init__(self, version):
+        # Validate the version and parse it into pieces
+        match = self._regex.search(version)
+        if not match:
+            raise InvalidVersion("Invalid version: '{0}'".format(version))
+
+        # Store the parsed out pieces of the version
+        self._version = _Version(
+            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
+            release=tuple(int(i) for i in match.group("release").split(".")),
+            pre=_parse_letter_version(
+                match.group("pre_l"),
+                match.group("pre_n"),
+            ),
+            post=_parse_letter_version(
+                match.group("post_l"),
+                match.group("post_n1") or match.group("post_n2"),
+            ),
+            dev=_parse_letter_version(
+                match.group("dev_l"),
+                match.group("dev_n"),
+            ),
+            local=_parse_local_version(match.group("local")),
+        )
+
+        # Generate a key which will be used for sorting
+        self._key = _cmpkey(
+            self._version.epoch,
+            self._version.release,
+            self._version.pre,
+            self._version.post,
+            self._version.dev,
+            self._version.local,
+        )
+
+    def __repr__(self):
+        return "".format(repr(str(self)))
+
+    def __str__(self):
+        parts = []
+
+        # Epoch
+        if self._version.epoch != 0:
+            parts.append("{0}!".format(self._version.epoch))
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self._version.release))
+
+        # Pre-release
+        if self._version.pre is not None:
+            parts.append("".join(str(x) for x in self._version.pre))
+
+        # Post-release
+        if self._version.post is not None:
+            parts.append(".post{0}".format(self._version.post[1]))
+
+        # Development release
+        if self._version.dev is not None:
+            parts.append(".dev{0}".format(self._version.dev[1]))
+
+        # Local version segment
+        if self._version.local is not None:
+            parts.append(
+                "+{0}".format(".".join(str(x) for x in self._version.local))
+            )
+
+        return "".join(parts)
+
+    @property
+    def public(self):
+        return str(self).split("+", 1)[0]
+
+    @property
+    def base_version(self):
+        parts = []
+
+        # Epoch
+        if self._version.epoch != 0:
+            parts.append("{0}!".format(self._version.epoch))
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self._version.release))
+
+        return "".join(parts)
+
+    @property
+    def local(self):
+        version_string = str(self)
+        if "+" in version_string:
+            return version_string.split("+", 1)[1]
+
+    @property
+    def is_prerelease(self):
+        return bool(self._version.dev or self._version.pre)
+
+    @property
+    def is_postrelease(self):
+        return bool(self._version.post)
+
+
+def _parse_letter_version(letter, number):
+    if letter:
+        # We consider there to be an implicit 0 in a pre-release if there is
+        # not a numeral associated with it.
+        if number is None:
+            number = 0
+
+        # We normalize any letters to their lower case form
+        letter = letter.lower()
+
+        # We consider some words to be alternate spellings of other words and
+        # in those cases we want to normalize the spellings to our preferred
+        # spelling.
+        if letter == "alpha":
+            letter = "a"
+        elif letter == "beta":
+            letter = "b"
+        elif letter in ["c", "pre", "preview"]:
+            letter = "rc"
+        elif letter in ["rev", "r"]:
+            letter = "post"
+
+        return letter, int(number)
+    if not letter and number:
+        # We assume if we are given a number, but we are not given a letter
+        # then this is using the implicit post release syntax (e.g. 1.0-1)
+        letter = "post"
+
+        return letter, int(number)
+
+
+_local_version_seperators = re.compile(r"[\._-]")
+
+
+def _parse_local_version(local):
+    """
+    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
+    """
+    if local is not None:
+        return tuple(
+            part.lower() if not part.isdigit() else int(part)
+            for part in _local_version_seperators.split(local)
+        )
+
+
+def _cmpkey(epoch, release, pre, post, dev, local):
+    # When we compare a release version, we want to compare it with all of the
+    # trailing zeros removed. So we'll use a reverse the list, drop all the now
+    # leading zeros until we come to something non zero, then take the rest
+    # re-reverse it back into the correct order and make it a tuple and use
+    # that for our sorting key.
+    release = tuple(
+        reversed(list(
+            itertools.dropwhile(
+                lambda x: x == 0,
+                reversed(release),
+            )
+        ))
+    )
+
+    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
+    # We'll do this by abusing the pre segment, but we _only_ want to do this
+    # if there is not a pre or a post segment. If we have one of those then
+    # the normal sorting rules will handle this case correctly.
+    if pre is None and post is None and dev is not None:
+        pre = -Infinity
+    # Versions without a pre-release (except as noted above) should sort after
+    # those with one.
+    elif pre is None:
+        pre = Infinity
+
+    # Versions without a post segment should sort before those with one.
+    if post is None:
+        post = -Infinity
+
+    # Versions without a development segment should sort after those with one.
+    if dev is None:
+        dev = Infinity
+
+    if local is None:
+        # Versions without a local segment should sort before those with one.
+        local = -Infinity
+    else:
+        # Versions with a local segment need that segment parsed to implement
+        # the sorting rules in PEP440.
+        # - Alpha numeric segments sort before numeric segments
+        # - Alpha numeric segments sort lexicographically
+        # - Numeric segments sort numerically
+        # - Shorter versions sort before longer versions when the prefixes
+        #   match exactly
+        local = tuple(
+            (i, "") if isinstance(i, int) else (-Infinity, i)
+            for i in local
+        )
+
+    return epoch, release, pre, post, dev, local
diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/pyparsing.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/pyparsing.py
new file mode 100644
index 0000000..cf75e1e
--- /dev/null
+++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/pyparsing.py
@@ -0,0 +1,5742 @@
+# module pyparsing.py
+#
+# Copyright (c) 2003-2018  Paul T. McGuire
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__doc__ = \
+"""
+pyparsing module - Classes and methods to define and execute parsing grammars
+=============================================================================
+
+The pyparsing module is an alternative approach to creating and executing simple grammars,
+vs. the traditional lex/yacc approach, or the use of regular expressions.  With pyparsing, you
+don't need to learn a new syntax for defining grammars or matching expressions - the parsing module
+provides a library of classes that you use to construct the grammar directly in Python.
+
+Here is a program to parse "Hello, World!" (or any greeting of the form 
+C{", !"}), built up using L{Word}, L{Literal}, and L{And} elements 
+(L{'+'} operator gives L{And} expressions, strings are auto-converted to
+L{Literal} expressions)::
+
+    from pyparsing import Word, alphas
+
+    # define grammar of a greeting
+    greet = Word(alphas) + "," + Word(alphas) + "!"
+
+    hello = "Hello, World!"
+    print (hello, "->", greet.parseString(hello))
+
+The program outputs the following::
+
+    Hello, World! -> ['Hello', ',', 'World', '!']
+
+The Python representation of the grammar is quite readable, owing to the self-explanatory
+class names, and the use of '+', '|' and '^' operators.
+
+The L{ParseResults} object returned from L{ParserElement.parseString} can be accessed as a nested list, a dictionary, or an
+object with named attributes.
+
+The pyparsing module handles some of the problems that are typically vexing when writing text parsers:
+ - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello  ,  World  !", etc.)
+ - quoted strings
+ - embedded comments
+
+
+Getting Started -
+-----------------
+Visit the classes L{ParserElement} and L{ParseResults} to see the base classes that most other pyparsing
+classes inherit from. Use the docstrings for examples of how to:
+ - construct literal match expressions from L{Literal} and L{CaselessLiteral} classes
+ - construct character word-group expressions using the L{Word} class
+ - see how to create repetitive expressions using L{ZeroOrMore} and L{OneOrMore} classes
+ - use L{'+'}, L{'|'}, L{'^'}, and L{'&'} operators to combine simple expressions into more complex ones
+ - associate names with your parsed results using L{ParserElement.setResultsName}
+ - find some helpful expression short-cuts like L{delimitedList} and L{oneOf}
+ - find more useful common expressions in the L{pyparsing_common} namespace class
+"""
+
+__version__ = "2.2.1"
+__versionTime__ = "18 Sep 2018 00:49 UTC"
+__author__ = "Paul McGuire "
+
+import string
+from weakref import ref as wkref
+import copy
+import sys
+import warnings
+import re
+import sre_constants
+import collections
+import pprint
+import traceback
+import types
+from datetime import datetime
+
+try:
+    from _thread import RLock
+except ImportError:
+    from threading import RLock
+
+try:
+    # Python 3
+    from collections.abc import Iterable
+    from collections.abc import MutableMapping
+except ImportError:
+    # Python 2.7
+    from collections import Iterable
+    from collections import MutableMapping
+
+try:
+    from collections import OrderedDict as _OrderedDict
+except ImportError:
+    try:
+        from ordereddict import OrderedDict as _OrderedDict
+    except ImportError:
+        _OrderedDict = None
+
+#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) )
+
+__all__ = [
+'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty',
+'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal',
+'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or',
+'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException',
+'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException',
+'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', 
+'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore',
+'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col',
+'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString',
+'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums',
+'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno',
+'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral',
+'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables',
+'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', 
+'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd',
+'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute',
+'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass',
+'CloseMatch', 'tokenMap', 'pyparsing_common',
+]
+
+system_version = tuple(sys.version_info)[:3]
+PY_3 = system_version[0] == 3
+if PY_3:
+    _MAX_INT = sys.maxsize
+    basestring = str
+    unichr = chr
+    _ustr = str
+
+    # build list of single arg builtins, that can be used as parse actions
+    singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max]
+
+else:
+    _MAX_INT = sys.maxint
+    range = xrange
+
+    def _ustr(obj):
+        """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries
+           str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It
+           then < returns the unicode object | encodes it with the default encoding | ... >.
+        """
+        if isinstance(obj,unicode):
+            return obj
+
+        try:
+            # If this works, then _ustr(obj) has the same behaviour as str(obj), so
+            # it won't break any existing code.
+            return str(obj)
+
+        except UnicodeEncodeError:
+            # Else encode it
+            ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace')
+            xmlcharref = Regex(r'&#\d+;')
+            xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:])
+            return xmlcharref.transformString(ret)
+
+    # build list of single arg builtins, tolerant of Python version, that can be used as parse actions
+    singleArgBuiltins = []
+    import __builtin__
+    for fname in "sum len sorted reversed list tuple set any all min max".split():
+        try:
+            singleArgBuiltins.append(getattr(__builtin__,fname))
+        except AttributeError:
+            continue
+            
+_generatorType = type((y for y in range(1)))
+ 
+def _xml_escape(data):
+    """Escape &, <, >, ", ', etc. in a string of data."""
+
+    # ampersand must be replaced first
+    from_symbols = '&><"\''
+    to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split())
+    for from_,to_ in zip(from_symbols, to_symbols):
+        data = data.replace(from_, to_)
+    return data
+
+class _Constants(object):
+    pass
+
+alphas     = string.ascii_uppercase + string.ascii_lowercase
+nums       = "0123456789"
+hexnums    = nums + "ABCDEFabcdef"
+alphanums  = alphas + nums
+_bslash    = chr(92)
+printables = "".join(c for c in string.printable if c not in string.whitespace)
+
+class ParseBaseException(Exception):
+    """base exception class for all parsing runtime exceptions"""
+    # Performance tuning: we construct a *lot* of these, so keep this
+    # constructor as small and fast as possible
+    def __init__( self, pstr, loc=0, msg=None, elem=None ):
+        self.loc = loc
+        if msg is None:
+            self.msg = pstr
+            self.pstr = ""
+        else:
+            self.msg = msg
+            self.pstr = pstr
+        self.parserElement = elem
+        self.args = (pstr, loc, msg)
+
+    @classmethod
+    def _from_exception(cls, pe):
+        """
+        internal factory method to simplify creating one type of ParseException 
+        from another - avoids having __init__ signature conflicts among subclasses
+        """
+        return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement)
+
+    def __getattr__( self, aname ):
+        """supported attributes by name are:
+            - lineno - returns the line number of the exception text
+            - col - returns the column number of the exception text
+            - line - returns the line containing the exception text
+        """
+        if( aname == "lineno" ):
+            return lineno( self.loc, self.pstr )
+        elif( aname in ("col", "column") ):
+            return col( self.loc, self.pstr )
+        elif( aname == "line" ):
+            return line( self.loc, self.pstr )
+        else:
+            raise AttributeError(aname)
+
+    def __str__( self ):
+        return "%s (at char %d), (line:%d, col:%d)" % \
+                ( self.msg, self.loc, self.lineno, self.column )
+    def __repr__( self ):
+        return _ustr(self)
+    def markInputline( self, markerString = ">!<" ):
+        """Extracts the exception line from the input string, and marks
+           the location of the exception with a special symbol.
+        """
+        line_str = self.line
+        line_column = self.column - 1
+        if markerString:
+            line_str = "".join((line_str[:line_column],
+                                markerString, line_str[line_column:]))
+        return line_str.strip()
+    def __dir__(self):
+        return "lineno col line".split() + dir(type(self))
+
+class ParseException(ParseBaseException):
+    """
+    Exception thrown when parse expressions don't match class;
+    supported attributes by name are:
+     - lineno - returns the line number of the exception text
+     - col - returns the column number of the exception text
+     - line - returns the line containing the exception text
+        
+    Example::
+        try:
+            Word(nums).setName("integer").parseString("ABC")
+        except ParseException as pe:
+            print(pe)
+            print("column: {}".format(pe.col))
+            
+    prints::
+       Expected integer (at char 0), (line:1, col:1)
+        column: 1
+    """
+    pass
+
+class ParseFatalException(ParseBaseException):
+    """user-throwable exception thrown when inconsistent parse content
+       is found; stops all parsing immediately"""
+    pass
+
+class ParseSyntaxException(ParseFatalException):
+    """just like L{ParseFatalException}, but thrown internally when an
+       L{ErrorStop} ('-' operator) indicates that parsing is to stop 
+       immediately because an unbacktrackable syntax error has been found"""
+    pass
+
+#~ class ReparseException(ParseBaseException):
+    #~ """Experimental class - parse actions can raise this exception to cause
+       #~ pyparsing to reparse the input string:
+        #~ - with a modified input string, and/or
+        #~ - with a modified start location
+       #~ Set the values of the ReparseException in the constructor, and raise the
+       #~ exception in a parse action to cause pyparsing to use the new string/location.
+       #~ Setting the values as None causes no change to be made.
+       #~ """
+    #~ def __init_( self, newstring, restartLoc ):
+        #~ self.newParseText = newstring
+        #~ self.reparseLoc = restartLoc
+
+class RecursiveGrammarException(Exception):
+    """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive"""
+    def __init__( self, parseElementList ):
+        self.parseElementTrace = parseElementList
+
+    def __str__( self ):
+        return "RecursiveGrammarException: %s" % self.parseElementTrace
+
+class _ParseResultsWithOffset(object):
+    def __init__(self,p1,p2):
+        self.tup = (p1,p2)
+    def __getitem__(self,i):
+        return self.tup[i]
+    def __repr__(self):
+        return repr(self.tup[0])
+    def setOffset(self,i):
+        self.tup = (self.tup[0],i)
+
+class ParseResults(object):
+    """
+    Structured parse results, to provide multiple means of access to the parsed data:
+       - as a list (C{len(results)})
+       - by list index (C{results[0], results[1]}, etc.)
+       - by attribute (C{results.} - see L{ParserElement.setResultsName})
+
+    Example::
+        integer = Word(nums)
+        date_str = (integer.setResultsName("year") + '/' 
+                        + integer.setResultsName("month") + '/' 
+                        + integer.setResultsName("day"))
+        # equivalent form:
+        # date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
+
+        # parseString returns a ParseResults object
+        result = date_str.parseString("1999/12/31")
+
+        def test(s, fn=repr):
+            print("%s -> %s" % (s, fn(eval(s))))
+        test("list(result)")
+        test("result[0]")
+        test("result['month']")
+        test("result.day")
+        test("'month' in result")
+        test("'minutes' in result")
+        test("result.dump()", str)
+    prints::
+        list(result) -> ['1999', '/', '12', '/', '31']
+        result[0] -> '1999'
+        result['month'] -> '12'
+        result.day -> '31'
+        'month' in result -> True
+        'minutes' in result -> False
+        result.dump() -> ['1999', '/', '12', '/', '31']
+        - day: 31
+        - month: 12
+        - year: 1999
+    """
+    def __new__(cls, toklist=None, name=None, asList=True, modal=True ):
+        if isinstance(toklist, cls):
+            return toklist
+        retobj = object.__new__(cls)
+        retobj.__doinit = True
+        return retobj
+
+    # Performance tuning: we construct a *lot* of these, so keep this
+    # constructor as small and fast as possible
+    def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ):
+        if self.__doinit:
+            self.__doinit = False
+            self.__name = None
+            self.__parent = None
+            self.__accumNames = {}
+            self.__asList = asList
+            self.__modal = modal
+            if toklist is None:
+                toklist = []
+            if isinstance(toklist, list):
+                self.__toklist = toklist[:]
+            elif isinstance(toklist, _generatorType):
+                self.__toklist = list(toklist)
+            else:
+                self.__toklist = [toklist]
+            self.__tokdict = dict()
+
+        if name is not None and name:
+            if not modal:
+                self.__accumNames[name] = 0
+            if isinstance(name,int):
+                name = _ustr(name) # will always return a str, but use _ustr for consistency
+            self.__name = name
+            if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])):
+                if isinstance(toklist,basestring):
+                    toklist = [ toklist ]
+                if asList:
+                    if isinstance(toklist,ParseResults):
+                        self[name] = _ParseResultsWithOffset(toklist.copy(),0)
+                    else:
+                        self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0)
+                    self[name].__name = name
+                else:
+                    try:
+                        self[name] = toklist[0]
+                    except (KeyError,TypeError,IndexError):
+                        self[name] = toklist
+
+    def __getitem__( self, i ):
+        if isinstance( i, (int,slice) ):
+            return self.__toklist[i]
+        else:
+            if i not in self.__accumNames:
+                return self.__tokdict[i][-1][0]
+            else:
+                return ParseResults([ v[0] for v in self.__tokdict[i] ])
+
+    def __setitem__( self, k, v, isinstance=isinstance ):
+        if isinstance(v,_ParseResultsWithOffset):
+            self.__tokdict[k] = self.__tokdict.get(k,list()) + [v]
+            sub = v[0]
+        elif isinstance(k,(int,slice)):
+            self.__toklist[k] = v
+            sub = v
+        else:
+            self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)]
+            sub = v
+        if isinstance(sub,ParseResults):
+            sub.__parent = wkref(self)
+
+    def __delitem__( self, i ):
+        if isinstance(i,(int,slice)):
+            mylen = len( self.__toklist )
+            del self.__toklist[i]
+
+            # convert int to slice
+            if isinstance(i, int):
+                if i < 0:
+                    i += mylen
+                i = slice(i, i+1)
+            # get removed indices
+            removed = list(range(*i.indices(mylen)))
+            removed.reverse()
+            # fixup indices in token dictionary
+            for name,occurrences in self.__tokdict.items():
+                for j in removed:
+                    for k, (value, position) in enumerate(occurrences):
+                        occurrences[k] = _ParseResultsWithOffset(value, position - (position > j))
+        else:
+            del self.__tokdict[i]
+
+    def __contains__( self, k ):
+        return k in self.__tokdict
+
+    def __len__( self ): return len( self.__toklist )
+    def __bool__(self): return ( not not self.__toklist )
+    __nonzero__ = __bool__
+    def __iter__( self ): return iter( self.__toklist )
+    def __reversed__( self ): return iter( self.__toklist[::-1] )
+    def _iterkeys( self ):
+        if hasattr(self.__tokdict, "iterkeys"):
+            return self.__tokdict.iterkeys()
+        else:
+            return iter(self.__tokdict)
+
+    def _itervalues( self ):
+        return (self[k] for k in self._iterkeys())
+            
+    def _iteritems( self ):
+        return ((k, self[k]) for k in self._iterkeys())
+
+    if PY_3:
+        keys = _iterkeys       
+        """Returns an iterator of all named result keys (Python 3.x only)."""
+
+        values = _itervalues
+        """Returns an iterator of all named result values (Python 3.x only)."""
+
+        items = _iteritems
+        """Returns an iterator of all named result key-value tuples (Python 3.x only)."""
+
+    else:
+        iterkeys = _iterkeys
+        """Returns an iterator of all named result keys (Python 2.x only)."""
+
+        itervalues = _itervalues
+        """Returns an iterator of all named result values (Python 2.x only)."""
+
+        iteritems = _iteritems
+        """Returns an iterator of all named result key-value tuples (Python 2.x only)."""
+
+        def keys( self ):
+            """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x)."""
+            return list(self.iterkeys())
+
+        def values( self ):
+            """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x)."""
+            return list(self.itervalues())
+                
+        def items( self ):
+            """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x)."""
+            return list(self.iteritems())
+
+    def haskeys( self ):
+        """Since keys() returns an iterator, this method is helpful in bypassing
+           code that looks for the existence of any defined results names."""
+        return bool(self.__tokdict)
+        
+    def pop( self, *args, **kwargs):
+        """
+        Removes and returns item at specified index (default=C{last}).
+        Supports both C{list} and C{dict} semantics for C{pop()}. If passed no
+        argument or an integer argument, it will use C{list} semantics
+        and pop tokens from the list of parsed tokens. If passed a 
+        non-integer argument (most likely a string), it will use C{dict}
+        semantics and pop the corresponding value from any defined 
+        results names. A second default return value argument is 
+        supported, just as in C{dict.pop()}.
+
+        Example::
+            def remove_first(tokens):
+                tokens.pop(0)
+            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']
+            print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321']
+
+            label = Word(alphas)
+            patt = label("LABEL") + OneOrMore(Word(nums))
+            print(patt.parseString("AAB 123 321").dump())
+
+            # Use pop() in a parse action to remove named result (note that corresponding value is not
+            # removed from list form of results)
+            def remove_LABEL(tokens):
+                tokens.pop("LABEL")
+                return tokens
+            patt.addParseAction(remove_LABEL)
+            print(patt.parseString("AAB 123 321").dump())
+        prints::
+            ['AAB', '123', '321']
+            - LABEL: AAB
+
+            ['AAB', '123', '321']
+        """
+        if not args:
+            args = [-1]
+        for k,v in kwargs.items():
+            if k == 'default':
+                args = (args[0], v)
+            else:
+                raise TypeError("pop() got an unexpected keyword argument '%s'" % k)
+        if (isinstance(args[0], int) or 
+                        len(args) == 1 or 
+                        args[0] in self):
+            index = args[0]
+            ret = self[index]
+            del self[index]
+            return ret
+        else:
+            defaultvalue = args[1]
+            return defaultvalue
+
+    def get(self, key, defaultValue=None):
+        """
+        Returns named result matching the given key, or if there is no
+        such name, then returns the given C{defaultValue} or C{None} if no
+        C{defaultValue} is specified.
+
+        Similar to C{dict.get()}.
+        
+        Example::
+            integer = Word(nums)
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           
+
+            result = date_str.parseString("1999/12/31")
+            print(result.get("year")) # -> '1999'
+            print(result.get("hour", "not specified")) # -> 'not specified'
+            print(result.get("hour")) # -> None
+        """
+        if key in self:
+            return self[key]
+        else:
+            return defaultValue
+
+    def insert( self, index, insStr ):
+        """
+        Inserts new element at location index in the list of parsed tokens.
+        
+        Similar to C{list.insert()}.
+
+        Example::
+            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']
+
+            # use a parse action to insert the parse location in the front of the parsed results
+            def insert_locn(locn, tokens):
+                tokens.insert(0, locn)
+            print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321']
+        """
+        self.__toklist.insert(index, insStr)
+        # fixup indices in token dictionary
+        for name,occurrences in self.__tokdict.items():
+            for k, (value, position) in enumerate(occurrences):
+                occurrences[k] = _ParseResultsWithOffset(value, position + (position > index))
+
+    def append( self, item ):
+        """
+        Add single element to end of ParseResults list of elements.
+
+        Example::
+            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']
+            
+            # use a parse action to compute the sum of the parsed integers, and add it to the end
+            def append_sum(tokens):
+                tokens.append(sum(map(int, tokens)))
+            print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444]
+        """
+        self.__toklist.append(item)
+
+    def extend( self, itemseq ):
+        """
+        Add sequence of elements to end of ParseResults list of elements.
+
+        Example::
+            patt = OneOrMore(Word(alphas))
+            
+            # use a parse action to append the reverse of the matched strings, to make a palindrome
+            def make_palindrome(tokens):
+                tokens.extend(reversed([t[::-1] for t in tokens]))
+                return ''.join(tokens)
+            print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl'
+        """
+        if isinstance(itemseq, ParseResults):
+            self += itemseq
+        else:
+            self.__toklist.extend(itemseq)
+
+    def clear( self ):
+        """
+        Clear all elements and results names.
+        """
+        del self.__toklist[:]
+        self.__tokdict.clear()
+
+    def __getattr__( self, name ):
+        try:
+            return self[name]
+        except KeyError:
+            return ""
+            
+        if name in self.__tokdict:
+            if name not in self.__accumNames:
+                return self.__tokdict[name][-1][0]
+            else:
+                return ParseResults([ v[0] for v in self.__tokdict[name] ])
+        else:
+            return ""
+
+    def __add__( self, other ):
+        ret = self.copy()
+        ret += other
+        return ret
+
+    def __iadd__( self, other ):
+        if other.__tokdict:
+            offset = len(self.__toklist)
+            addoffset = lambda a: offset if a<0 else a+offset
+            otheritems = other.__tokdict.items()
+            otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) )
+                                for (k,vlist) in otheritems for v in vlist]
+            for k,v in otherdictitems:
+                self[k] = v
+                if isinstance(v[0],ParseResults):
+                    v[0].__parent = wkref(self)
+            
+        self.__toklist += other.__toklist
+        self.__accumNames.update( other.__accumNames )
+        return self
+
+    def __radd__(self, other):
+        if isinstance(other,int) and other == 0:
+            # useful for merging many ParseResults using sum() builtin
+            return self.copy()
+        else:
+            # this may raise a TypeError - so be it
+            return other + self
+        
+    def __repr__( self ):
+        return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) )
+
+    def __str__( self ):
+        return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']'
+
+    def _asStringList( self, sep='' ):
+        out = []
+        for item in self.__toklist:
+            if out and sep:
+                out.append(sep)
+            if isinstance( item, ParseResults ):
+                out += item._asStringList()
+            else:
+                out.append( _ustr(item) )
+        return out
+
+    def asList( self ):
+        """
+        Returns the parse results as a nested list of matching tokens, all converted to strings.
+
+        Example::
+            patt = OneOrMore(Word(alphas))
+            result = patt.parseString("sldkj lsdkj sldkj")
+            # even though the result prints in string-like form, it is actually a pyparsing ParseResults
+            print(type(result), result) # ->  ['sldkj', 'lsdkj', 'sldkj']
+            
+            # Use asList() to create an actual list
+            result_list = result.asList()
+            print(type(result_list), result_list) # ->  ['sldkj', 'lsdkj', 'sldkj']
+        """
+        return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist]
+
+    def asDict( self ):
+        """
+        Returns the named parse results as a nested dictionary.
+
+        Example::
+            integer = Word(nums)
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
+            
+            result = date_str.parseString('12/31/1999')
+            print(type(result), repr(result)) # ->  (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]})
+            
+            result_dict = result.asDict()
+            print(type(result_dict), repr(result_dict)) # ->  {'day': '1999', 'year': '12', 'month': '31'}
+
+            # even though a ParseResults supports dict-like access, sometime you just need to have a dict
+            import json
+            print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable
+            print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"}
+        """
+        if PY_3:
+            item_fn = self.items
+        else:
+            item_fn = self.iteritems
+            
+        def toItem(obj):
+            if isinstance(obj, ParseResults):
+                if obj.haskeys():
+                    return obj.asDict()
+                else:
+                    return [toItem(v) for v in obj]
+            else:
+                return obj
+                
+        return dict((k,toItem(v)) for k,v in item_fn())
+
+    def copy( self ):
+        """
+        Returns a new copy of a C{ParseResults} object.
+        """
+        ret = ParseResults( self.__toklist )
+        ret.__tokdict = self.__tokdict.copy()
+        ret.__parent = self.__parent
+        ret.__accumNames.update( self.__accumNames )
+        ret.__name = self.__name
+        return ret
+
+    def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ):
+        """
+        (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names.
+        """
+        nl = "\n"
+        out = []
+        namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items()
+                                                            for v in vlist)
+        nextLevelIndent = indent + "  "
+
+        # collapse out indents if formatting is not desired
+        if not formatted:
+            indent = ""
+            nextLevelIndent = ""
+            nl = ""
+
+        selfTag = None
+        if doctag is not None:
+            selfTag = doctag
+        else:
+            if self.__name:
+                selfTag = self.__name
+
+        if not selfTag:
+            if namedItemsOnly:
+                return ""
+            else:
+                selfTag = "ITEM"
+
+        out += [ nl, indent, "<", selfTag, ">" ]
+
+        for i,res in enumerate(self.__toklist):
+            if isinstance(res,ParseResults):
+                if i in namedItems:
+                    out += [ res.asXML(namedItems[i],
+                                        namedItemsOnly and doctag is None,
+                                        nextLevelIndent,
+                                        formatted)]
+                else:
+                    out += [ res.asXML(None,
+                                        namedItemsOnly and doctag is None,
+                                        nextLevelIndent,
+                                        formatted)]
+            else:
+                # individual token, see if there is a name for it
+                resTag = None
+                if i in namedItems:
+                    resTag = namedItems[i]
+                if not resTag:
+                    if namedItemsOnly:
+                        continue
+                    else:
+                        resTag = "ITEM"
+                xmlBodyText = _xml_escape(_ustr(res))
+                out += [ nl, nextLevelIndent, "<", resTag, ">",
+                                                xmlBodyText,
+                                                "" ]
+
+        out += [ nl, indent, "" ]
+        return "".join(out)
+
+    def __lookup(self,sub):
+        for k,vlist in self.__tokdict.items():
+            for v,loc in vlist:
+                if sub is v:
+                    return k
+        return None
+
+    def getName(self):
+        r"""
+        Returns the results name for this token expression. Useful when several 
+        different expressions might match at a particular location.
+
+        Example::
+            integer = Word(nums)
+            ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d")
+            house_number_expr = Suppress('#') + Word(nums, alphanums)
+            user_data = (Group(house_number_expr)("house_number") 
+                        | Group(ssn_expr)("ssn")
+                        | Group(integer)("age"))
+            user_info = OneOrMore(user_data)
+            
+            result = user_info.parseString("22 111-22-3333 #221B")
+            for item in result:
+                print(item.getName(), ':', item[0])
+        prints::
+            age : 22
+            ssn : 111-22-3333
+            house_number : 221B
+        """
+        if self.__name:
+            return self.__name
+        elif self.__parent:
+            par = self.__parent()
+            if par:
+                return par.__lookup(self)
+            else:
+                return None
+        elif (len(self) == 1 and
+               len(self.__tokdict) == 1 and
+               next(iter(self.__tokdict.values()))[0][1] in (0,-1)):
+            return next(iter(self.__tokdict.keys()))
+        else:
+            return None
+
+    def dump(self, indent='', depth=0, full=True):
+        """
+        Diagnostic method for listing out the contents of a C{ParseResults}.
+        Accepts an optional C{indent} argument so that this string can be embedded
+        in a nested display of other data.
+
+        Example::
+            integer = Word(nums)
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
+            
+            result = date_str.parseString('12/31/1999')
+            print(result.dump())
+        prints::
+            ['12', '/', '31', '/', '1999']
+            - day: 1999
+            - month: 31
+            - year: 12
+        """
+        out = []
+        NL = '\n'
+        out.append( indent+_ustr(self.asList()) )
+        if full:
+            if self.haskeys():
+                items = sorted((str(k), v) for k,v in self.items())
+                for k,v in items:
+                    if out:
+                        out.append(NL)
+                    out.append( "%s%s- %s: " % (indent,('  '*depth), k) )
+                    if isinstance(v,ParseResults):
+                        if v:
+                            out.append( v.dump(indent,depth+1) )
+                        else:
+                            out.append(_ustr(v))
+                    else:
+                        out.append(repr(v))
+            elif any(isinstance(vv,ParseResults) for vv in self):
+                v = self
+                for i,vv in enumerate(v):
+                    if isinstance(vv,ParseResults):
+                        out.append("\n%s%s[%d]:\n%s%s%s" % (indent,('  '*(depth)),i,indent,('  '*(depth+1)),vv.dump(indent,depth+1) ))
+                    else:
+                        out.append("\n%s%s[%d]:\n%s%s%s" % (indent,('  '*(depth)),i,indent,('  '*(depth+1)),_ustr(vv)))
+            
+        return "".join(out)
+
+    def pprint(self, *args, **kwargs):
+        """
+        Pretty-printer for parsed results as a list, using the C{pprint} module.
+        Accepts additional positional or keyword args as defined for the 
+        C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint})
+
+        Example::
+            ident = Word(alphas, alphanums)
+            num = Word(nums)
+            func = Forward()
+            term = ident | num | Group('(' + func + ')')
+            func <<= ident + Group(Optional(delimitedList(term)))
+            result = func.parseString("fna a,b,(fnb c,d,200),100")
+            result.pprint(width=40)
+        prints::
+            ['fna',
+             ['a',
+              'b',
+              ['(', 'fnb', ['c', 'd', '200'], ')'],
+              '100']]
+        """
+        pprint.pprint(self.asList(), *args, **kwargs)
+
+    # add support for pickle protocol
+    def __getstate__(self):
+        return ( self.__toklist,
+                 ( self.__tokdict.copy(),
+                   self.__parent is not None and self.__parent() or None,
+                   self.__accumNames,
+                   self.__name ) )
+
+    def __setstate__(self,state):
+        self.__toklist = state[0]
+        (self.__tokdict,
+         par,
+         inAccumNames,
+         self.__name) = state[1]
+        self.__accumNames = {}
+        self.__accumNames.update(inAccumNames)
+        if par is not None:
+            self.__parent = wkref(par)
+        else:
+            self.__parent = None
+
+    def __getnewargs__(self):
+        return self.__toklist, self.__name, self.__asList, self.__modal
+
+    def __dir__(self):
+        return (dir(type(self)) + list(self.keys()))
+
+MutableMapping.register(ParseResults)
+
+def col (loc,strg):
+    """Returns current column within a string, counting newlines as line separators.
+   The first column is number 1.
+
+   Note: the default parsing behavior is to expand tabs in the input string
+   before starting the parsing process.  See L{I{ParserElement.parseString}} for more information
+   on parsing strings containing C{}s, and suggested methods to maintain a
+   consistent view of the parsed string, the parse location, and line and column
+   positions within the parsed string.
+   """
+    s = strg
+    return 1 if 0} for more information
+   on parsing strings containing C{}s, and suggested methods to maintain a
+   consistent view of the parsed string, the parse location, and line and column
+   positions within the parsed string.
+   """
+    return strg.count("\n",0,loc) + 1
+
+def line( loc, strg ):
+    """Returns the line of text containing loc within a string, counting newlines as line separators.
+       """
+    lastCR = strg.rfind("\n", 0, loc)
+    nextCR = strg.find("\n", loc)
+    if nextCR >= 0:
+        return strg[lastCR+1:nextCR]
+    else:
+        return strg[lastCR+1:]
+
+def _defaultStartDebugAction( instring, loc, expr ):
+    print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )))
+
+def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ):
+    print ("Matched " + _ustr(expr) + " -> " + str(toks.asList()))
+
+def _defaultExceptionDebugAction( instring, loc, expr, exc ):
+    print ("Exception raised:" + _ustr(exc))
+
+def nullDebugAction(*args):
+    """'Do-nothing' debug action, to suppress debugging output during parsing."""
+    pass
+
+# Only works on Python 3.x - nonlocal is toxic to Python 2 installs
+#~ 'decorator to trim function calls to match the arity of the target'
+#~ def _trim_arity(func, maxargs=3):
+    #~ if func in singleArgBuiltins:
+        #~ return lambda s,l,t: func(t)
+    #~ limit = 0
+    #~ foundArity = False
+    #~ def wrapper(*args):
+        #~ nonlocal limit,foundArity
+        #~ while 1:
+            #~ try:
+                #~ ret = func(*args[limit:])
+                #~ foundArity = True
+                #~ return ret
+            #~ except TypeError:
+                #~ if limit == maxargs or foundArity:
+                    #~ raise
+                #~ limit += 1
+                #~ continue
+    #~ return wrapper
+
+# this version is Python 2.x-3.x cross-compatible
+'decorator to trim function calls to match the arity of the target'
+def _trim_arity(func, maxargs=2):
+    if func in singleArgBuiltins:
+        return lambda s,l,t: func(t)
+    limit = [0]
+    foundArity = [False]
+    
+    # traceback return data structure changed in Py3.5 - normalize back to plain tuples
+    if system_version[:2] >= (3,5):
+        def extract_stack(limit=0):
+            # special handling for Python 3.5.0 - extra deep call stack by 1
+            offset = -3 if system_version == (3,5,0) else -2
+            frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset]
+            return [frame_summary[:2]]
+        def extract_tb(tb, limit=0):
+            frames = traceback.extract_tb(tb, limit=limit)
+            frame_summary = frames[-1]
+            return [frame_summary[:2]]
+    else:
+        extract_stack = traceback.extract_stack
+        extract_tb = traceback.extract_tb
+    
+    # synthesize what would be returned by traceback.extract_stack at the call to 
+    # user's parse action 'func', so that we don't incur call penalty at parse time
+    
+    LINE_DIFF = 6
+    # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND 
+    # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!!
+    this_line = extract_stack(limit=2)[-1]
+    pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF)
+
+    def wrapper(*args):
+        while 1:
+            try:
+                ret = func(*args[limit[0]:])
+                foundArity[0] = True
+                return ret
+            except TypeError:
+                # re-raise TypeErrors if they did not come from our arity testing
+                if foundArity[0]:
+                    raise
+                else:
+                    try:
+                        tb = sys.exc_info()[-1]
+                        if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth:
+                            raise
+                    finally:
+                        del tb
+
+                if limit[0] <= maxargs:
+                    limit[0] += 1
+                    continue
+                raise
+
+    # copy func name to wrapper for sensible debug output
+    func_name = ""
+    try:
+        func_name = getattr(func, '__name__', 
+                            getattr(func, '__class__').__name__)
+    except Exception:
+        func_name = str(func)
+    wrapper.__name__ = func_name
+
+    return wrapper
+
+class ParserElement(object):
+    """Abstract base level parser element class."""
+    DEFAULT_WHITE_CHARS = " \n\t\r"
+    verbose_stacktrace = False
+
+    @staticmethod
+    def setDefaultWhitespaceChars( chars ):
+        r"""
+        Overrides the default whitespace chars
+
+        Example::
+            # default whitespace chars are space,  and newline
+            OneOrMore(Word(alphas)).parseString("abc def\nghi jkl")  # -> ['abc', 'def', 'ghi', 'jkl']
+            
+            # change to just treat newline as significant
+            ParserElement.setDefaultWhitespaceChars(" \t")
+            OneOrMore(Word(alphas)).parseString("abc def\nghi jkl")  # -> ['abc', 'def']
+        """
+        ParserElement.DEFAULT_WHITE_CHARS = chars
+
+    @staticmethod
+    def inlineLiteralsUsing(cls):
+        """
+        Set class to be used for inclusion of string literals into a parser.
+        
+        Example::
+            # default literal class used is Literal
+            integer = Word(nums)
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           
+
+            date_str.parseString("1999/12/31")  # -> ['1999', '/', '12', '/', '31']
+
+
+            # change to Suppress
+            ParserElement.inlineLiteralsUsing(Suppress)
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           
+
+            date_str.parseString("1999/12/31")  # -> ['1999', '12', '31']
+        """
+        ParserElement._literalStringClass = cls
+
+    def __init__( self, savelist=False ):
+        self.parseAction = list()
+        self.failAction = None
+        #~ self.name = ""  # don't define self.name, let subclasses try/except upcall
+        self.strRepr = None
+        self.resultsName = None
+        self.saveAsList = savelist
+        self.skipWhitespace = True
+        self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
+        self.copyDefaultWhiteChars = True
+        self.mayReturnEmpty = False # used when checking for left-recursion
+        self.keepTabs = False
+        self.ignoreExprs = list()
+        self.debug = False
+        self.streamlined = False
+        self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index
+        self.errmsg = ""
+        self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all)
+        self.debugActions = ( None, None, None ) #custom debug actions
+        self.re = None
+        self.callPreparse = True # used to avoid redundant calls to preParse
+        self.callDuringTry = False
+
+    def copy( self ):
+        """
+        Make a copy of this C{ParserElement}.  Useful for defining different parse actions
+        for the same parsing pattern, using copies of the original parse element.
+        
+        Example::
+            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
+            integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K")
+            integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M")
+            
+            print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M"))
+        prints::
+            [5120, 100, 655360, 268435456]
+        Equivalent form of C{expr.copy()} is just C{expr()}::
+            integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M")
+        """
+        cpy = copy.copy( self )
+        cpy.parseAction = self.parseAction[:]
+        cpy.ignoreExprs = self.ignoreExprs[:]
+        if self.copyDefaultWhiteChars:
+            cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
+        return cpy
+
+    def setName( self, name ):
+        """
+        Define name for this expression, makes debugging and exception messages clearer.
+        
+        Example::
+            Word(nums).parseString("ABC")  # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1)
+            Word(nums).setName("integer").parseString("ABC")  # -> Exception: Expected integer (at char 0), (line:1, col:1)
+        """
+        self.name = name
+        self.errmsg = "Expected " + self.name
+        if hasattr(self,"exception"):
+            self.exception.msg = self.errmsg
+        return self
+
+    def setResultsName( self, name, listAllMatches=False ):
+        """
+        Define name for referencing matching tokens as a nested attribute
+        of the returned parse results.
+        NOTE: this returns a *copy* of the original C{ParserElement} object;
+        this is so that the client can define a basic element, such as an
+        integer, and reference it in multiple places with different names.
+
+        You can also set results names using the abbreviated syntax,
+        C{expr("name")} in place of C{expr.setResultsName("name")} - 
+        see L{I{__call__}<__call__>}.
+
+        Example::
+            date_str = (integer.setResultsName("year") + '/' 
+                        + integer.setResultsName("month") + '/' 
+                        + integer.setResultsName("day"))
+
+            # equivalent form:
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
+        """
+        newself = self.copy()
+        if name.endswith("*"):
+            name = name[:-1]
+            listAllMatches=True
+        newself.resultsName = name
+        newself.modalResults = not listAllMatches
+        return newself
+
+    def setBreak(self,breakFlag = True):
+        """Method to invoke the Python pdb debugger when this element is
+           about to be parsed. Set C{breakFlag} to True to enable, False to
+           disable.
+        """
+        if breakFlag:
+            _parseMethod = self._parse
+            def breaker(instring, loc, doActions=True, callPreParse=True):
+                import pdb
+                pdb.set_trace()
+                return _parseMethod( instring, loc, doActions, callPreParse )
+            breaker._originalParseMethod = _parseMethod
+            self._parse = breaker
+        else:
+            if hasattr(self._parse,"_originalParseMethod"):
+                self._parse = self._parse._originalParseMethod
+        return self
+
+    def setParseAction( self, *fns, **kwargs ):
+        """
+        Define one or more actions to perform when successfully matching parse element definition.
+        Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)},
+        C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where:
+         - s   = the original string being parsed (see note below)
+         - loc = the location of the matching substring
+         - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object
+        If the functions in fns modify the tokens, they can return them as the return
+        value from fn, and the modified list of tokens will replace the original.
+        Otherwise, fn does not need to return any value.
+
+        Optional keyword arguments:
+         - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing
+
+        Note: the default parsing behavior is to expand tabs in the input string
+        before starting the parsing process.  See L{I{parseString}} for more information
+        on parsing strings containing C{}s, and suggested methods to maintain a
+        consistent view of the parsed string, the parse location, and line and column
+        positions within the parsed string.
+        
+        Example::
+            integer = Word(nums)
+            date_str = integer + '/' + integer + '/' + integer
+
+            date_str.parseString("1999/12/31")  # -> ['1999', '/', '12', '/', '31']
+
+            # use parse action to convert to ints at parse time
+            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
+            date_str = integer + '/' + integer + '/' + integer
+
+            # note that integer fields are now ints, not strings
+            date_str.parseString("1999/12/31")  # -> [1999, '/', 12, '/', 31]
+        """
+        self.parseAction = list(map(_trim_arity, list(fns)))
+        self.callDuringTry = kwargs.get("callDuringTry", False)
+        return self
+
+    def addParseAction( self, *fns, **kwargs ):
+        """
+        Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}}.
+        
+        See examples in L{I{copy}}.
+        """
+        self.parseAction += list(map(_trim_arity, list(fns)))
+        self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False)
+        return self
+
+    def addCondition(self, *fns, **kwargs):
+        """Add a boolean predicate function to expression's list of parse actions. See 
+        L{I{setParseAction}} for function call signatures. Unlike C{setParseAction}, 
+        functions passed to C{addCondition} need to return boolean success/fail of the condition.
+
+        Optional keyword arguments:
+         - message = define a custom message to be used in the raised exception
+         - fatal   = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException
+         
+        Example::
+            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
+            year_int = integer.copy()
+            year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later")
+            date_str = year_int + '/' + integer + '/' + integer
+
+            result = date_str.parseString("1999/12/31")  # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1)
+        """
+        msg = kwargs.get("message", "failed user-defined condition")
+        exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException
+        for fn in fns:
+            def pa(s,l,t):
+                if not bool(_trim_arity(fn)(s,l,t)):
+                    raise exc_type(s,l,msg)
+            self.parseAction.append(pa)
+        self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False)
+        return self
+
+    def setFailAction( self, fn ):
+        """Define action to perform if parsing fails at this expression.
+           Fail acton fn is a callable function that takes the arguments
+           C{fn(s,loc,expr,err)} where:
+            - s = string being parsed
+            - loc = location where expression match was attempted and failed
+            - expr = the parse expression that failed
+            - err = the exception thrown
+           The function returns no value.  It may throw C{L{ParseFatalException}}
+           if it is desired to stop parsing immediately."""
+        self.failAction = fn
+        return self
+
+    def _skipIgnorables( self, instring, loc ):
+        exprsFound = True
+        while exprsFound:
+            exprsFound = False
+            for e in self.ignoreExprs:
+                try:
+                    while 1:
+                        loc,dummy = e._parse( instring, loc )
+                        exprsFound = True
+                except ParseException:
+                    pass
+        return loc
+
+    def preParse( self, instring, loc ):
+        if self.ignoreExprs:
+            loc = self._skipIgnorables( instring, loc )
+
+        if self.skipWhitespace:
+            wt = self.whiteChars
+            instrlen = len(instring)
+            while loc < instrlen and instring[loc] in wt:
+                loc += 1
+
+        return loc
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        return loc, []
+
+    def postParse( self, instring, loc, tokenlist ):
+        return tokenlist
+
+    #~ @profile
+    def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ):
+        debugging = ( self.debug ) #and doActions )
+
+        if debugging or self.failAction:
+            #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))
+            if (self.debugActions[0] ):
+                self.debugActions[0]( instring, loc, self )
+            if callPreParse and self.callPreparse:
+                preloc = self.preParse( instring, loc )
+            else:
+                preloc = loc
+            tokensStart = preloc
+            try:
+                try:
+                    loc,tokens = self.parseImpl( instring, preloc, doActions )
+                except IndexError:
+                    raise ParseException( instring, len(instring), self.errmsg, self )
+            except ParseBaseException as err:
+                #~ print ("Exception raised:", err)
+                if self.debugActions[2]:
+                    self.debugActions[2]( instring, tokensStart, self, err )
+                if self.failAction:
+                    self.failAction( instring, tokensStart, self, err )
+                raise
+        else:
+            if callPreParse and self.callPreparse:
+                preloc = self.preParse( instring, loc )
+            else:
+                preloc = loc
+            tokensStart = preloc
+            if self.mayIndexError or preloc >= len(instring):
+                try:
+                    loc,tokens = self.parseImpl( instring, preloc, doActions )
+                except IndexError:
+                    raise ParseException( instring, len(instring), self.errmsg, self )
+            else:
+                loc,tokens = self.parseImpl( instring, preloc, doActions )
+
+        tokens = self.postParse( instring, loc, tokens )
+
+        retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults )
+        if self.parseAction and (doActions or self.callDuringTry):
+            if debugging:
+                try:
+                    for fn in self.parseAction:
+                        tokens = fn( instring, tokensStart, retTokens )
+                        if tokens is not None:
+                            retTokens = ParseResults( tokens,
+                                                      self.resultsName,
+                                                      asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
+                                                      modal=self.modalResults )
+                except ParseBaseException as err:
+                    #~ print "Exception raised in user parse action:", err
+                    if (self.debugActions[2] ):
+                        self.debugActions[2]( instring, tokensStart, self, err )
+                    raise
+            else:
+                for fn in self.parseAction:
+                    tokens = fn( instring, tokensStart, retTokens )
+                    if tokens is not None:
+                        retTokens = ParseResults( tokens,
+                                                  self.resultsName,
+                                                  asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
+                                                  modal=self.modalResults )
+        if debugging:
+            #~ print ("Matched",self,"->",retTokens.asList())
+            if (self.debugActions[1] ):
+                self.debugActions[1]( instring, tokensStart, loc, self, retTokens )
+
+        return loc, retTokens
+
+    def tryParse( self, instring, loc ):
+        try:
+            return self._parse( instring, loc, doActions=False )[0]
+        except ParseFatalException:
+            raise ParseException( instring, loc, self.errmsg, self)
+    
+    def canParseNext(self, instring, loc):
+        try:
+            self.tryParse(instring, loc)
+        except (ParseException, IndexError):
+            return False
+        else:
+            return True
+
+    class _UnboundedCache(object):
+        def __init__(self):
+            cache = {}
+            self.not_in_cache = not_in_cache = object()
+
+            def get(self, key):
+                return cache.get(key, not_in_cache)
+
+            def set(self, key, value):
+                cache[key] = value
+
+            def clear(self):
+                cache.clear()
+                
+            def cache_len(self):
+                return len(cache)
+
+            self.get = types.MethodType(get, self)
+            self.set = types.MethodType(set, self)
+            self.clear = types.MethodType(clear, self)
+            self.__len__ = types.MethodType(cache_len, self)
+
+    if _OrderedDict is not None:
+        class _FifoCache(object):
+            def __init__(self, size):
+                self.not_in_cache = not_in_cache = object()
+
+                cache = _OrderedDict()
+
+                def get(self, key):
+                    return cache.get(key, not_in_cache)
+
+                def set(self, key, value):
+                    cache[key] = value
+                    while len(cache) > size:
+                        try:
+                            cache.popitem(False)
+                        except KeyError:
+                            pass
+
+                def clear(self):
+                    cache.clear()
+
+                def cache_len(self):
+                    return len(cache)
+
+                self.get = types.MethodType(get, self)
+                self.set = types.MethodType(set, self)
+                self.clear = types.MethodType(clear, self)
+                self.__len__ = types.MethodType(cache_len, self)
+
+    else:
+        class _FifoCache(object):
+            def __init__(self, size):
+                self.not_in_cache = not_in_cache = object()
+
+                cache = {}
+                key_fifo = collections.deque([], size)
+
+                def get(self, key):
+                    return cache.get(key, not_in_cache)
+
+                def set(self, key, value):
+                    cache[key] = value
+                    while len(key_fifo) > size:
+                        cache.pop(key_fifo.popleft(), None)
+                    key_fifo.append(key)
+
+                def clear(self):
+                    cache.clear()
+                    key_fifo.clear()
+
+                def cache_len(self):
+                    return len(cache)
+
+                self.get = types.MethodType(get, self)
+                self.set = types.MethodType(set, self)
+                self.clear = types.MethodType(clear, self)
+                self.__len__ = types.MethodType(cache_len, self)
+
+    # argument cache for optimizing repeated calls when backtracking through recursive expressions
+    packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail
+    packrat_cache_lock = RLock()
+    packrat_cache_stats = [0, 0]
+
+    # this method gets repeatedly called during backtracking with the same arguments -
+    # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression
+    def _parseCache( self, instring, loc, doActions=True, callPreParse=True ):
+        HIT, MISS = 0, 1
+        lookup = (self, instring, loc, callPreParse, doActions)
+        with ParserElement.packrat_cache_lock:
+            cache = ParserElement.packrat_cache
+            value = cache.get(lookup)
+            if value is cache.not_in_cache:
+                ParserElement.packrat_cache_stats[MISS] += 1
+                try:
+                    value = self._parseNoCache(instring, loc, doActions, callPreParse)
+                except ParseBaseException as pe:
+                    # cache a copy of the exception, without the traceback
+                    cache.set(lookup, pe.__class__(*pe.args))
+                    raise
+                else:
+                    cache.set(lookup, (value[0], value[1].copy()))
+                    return value
+            else:
+                ParserElement.packrat_cache_stats[HIT] += 1
+                if isinstance(value, Exception):
+                    raise value
+                return (value[0], value[1].copy())
+
+    _parse = _parseNoCache
+
+    @staticmethod
+    def resetCache():
+        ParserElement.packrat_cache.clear()
+        ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats)
+
+    _packratEnabled = False
+    @staticmethod
+    def enablePackrat(cache_size_limit=128):
+        """Enables "packrat" parsing, which adds memoizing to the parsing logic.
+           Repeated parse attempts at the same string location (which happens
+           often in many complex grammars) can immediately return a cached value,
+           instead of re-executing parsing/validating code.  Memoizing is done of
+           both valid results and parsing exceptions.
+           
+           Parameters:
+            - cache_size_limit - (default=C{128}) - if an integer value is provided
+              will limit the size of the packrat cache; if None is passed, then
+              the cache size will be unbounded; if 0 is passed, the cache will
+              be effectively disabled.
+            
+           This speedup may break existing programs that use parse actions that
+           have side-effects.  For this reason, packrat parsing is disabled when
+           you first import pyparsing.  To activate the packrat feature, your
+           program must call the class method C{ParserElement.enablePackrat()}.  If
+           your program uses C{psyco} to "compile as you go", you must call
+           C{enablePackrat} before calling C{psyco.full()}.  If you do not do this,
+           Python will crash.  For best results, call C{enablePackrat()} immediately
+           after importing pyparsing.
+           
+           Example::
+               import pyparsing
+               pyparsing.ParserElement.enablePackrat()
+        """
+        if not ParserElement._packratEnabled:
+            ParserElement._packratEnabled = True
+            if cache_size_limit is None:
+                ParserElement.packrat_cache = ParserElement._UnboundedCache()
+            else:
+                ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit)
+            ParserElement._parse = ParserElement._parseCache
+
+    def parseString( self, instring, parseAll=False ):
+        """
+        Execute the parse expression with the given string.
+        This is the main interface to the client code, once the complete
+        expression has been built.
+
+        If you want the grammar to require that the entire input string be
+        successfully parsed, then set C{parseAll} to True (equivalent to ending
+        the grammar with C{L{StringEnd()}}).
+
+        Note: C{parseString} implicitly calls C{expandtabs()} on the input string,
+        in order to report proper column numbers in parse actions.
+        If the input string contains tabs and
+        the grammar uses parse actions that use the C{loc} argument to index into the
+        string being parsed, you can ensure you have a consistent view of the input
+        string by:
+         - calling C{parseWithTabs} on your grammar before calling C{parseString}
+           (see L{I{parseWithTabs}})
+         - define your parse action using the full C{(s,loc,toks)} signature, and
+           reference the input string using the parse action's C{s} argument
+         - explictly expand the tabs in your input string before calling
+           C{parseString}
+        
+        Example::
+            Word('a').parseString('aaaaabaaa')  # -> ['aaaaa']
+            Word('a').parseString('aaaaabaaa', parseAll=True)  # -> Exception: Expected end of text
+        """
+        ParserElement.resetCache()
+        if not self.streamlined:
+            self.streamline()
+            #~ self.saveAsList = True
+        for e in self.ignoreExprs:
+            e.streamline()
+        if not self.keepTabs:
+            instring = instring.expandtabs()
+        try:
+            loc, tokens = self._parse( instring, 0 )
+            if parseAll:
+                loc = self.preParse( instring, loc )
+                se = Empty() + StringEnd()
+                se._parse( instring, loc )
+        except ParseBaseException as exc:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                raise exc
+        else:
+            return tokens
+
+    def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ):
+        """
+        Scan the input string for expression matches.  Each match will return the
+        matching tokens, start location, and end location.  May be called with optional
+        C{maxMatches} argument, to clip scanning after 'n' matches are found.  If
+        C{overlap} is specified, then overlapping matches will be reported.
+
+        Note that the start and end locations are reported relative to the string
+        being parsed.  See L{I{parseString}} for more information on parsing
+        strings with embedded tabs.
+
+        Example::
+            source = "sldjf123lsdjjkf345sldkjf879lkjsfd987"
+            print(source)
+            for tokens,start,end in Word(alphas).scanString(source):
+                print(' '*start + '^'*(end-start))
+                print(' '*start + tokens[0])
+        
+        prints::
+        
+            sldjf123lsdjjkf345sldkjf879lkjsfd987
+            ^^^^^
+            sldjf
+                    ^^^^^^^
+                    lsdjjkf
+                              ^^^^^^
+                              sldkjf
+                                       ^^^^^^
+                                       lkjsfd
+        """
+        if not self.streamlined:
+            self.streamline()
+        for e in self.ignoreExprs:
+            e.streamline()
+
+        if not self.keepTabs:
+            instring = _ustr(instring).expandtabs()
+        instrlen = len(instring)
+        loc = 0
+        preparseFn = self.preParse
+        parseFn = self._parse
+        ParserElement.resetCache()
+        matches = 0
+        try:
+            while loc <= instrlen and matches < maxMatches:
+                try:
+                    preloc = preparseFn( instring, loc )
+                    nextLoc,tokens = parseFn( instring, preloc, callPreParse=False )
+                except ParseException:
+                    loc = preloc+1
+                else:
+                    if nextLoc > loc:
+                        matches += 1
+                        yield tokens, preloc, nextLoc
+                        if overlap:
+                            nextloc = preparseFn( instring, loc )
+                            if nextloc > loc:
+                                loc = nextLoc
+                            else:
+                                loc += 1
+                        else:
+                            loc = nextLoc
+                    else:
+                        loc = preloc+1
+        except ParseBaseException as exc:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                raise exc
+
+    def transformString( self, instring ):
+        """
+        Extension to C{L{scanString}}, to modify matching text with modified tokens that may
+        be returned from a parse action.  To use C{transformString}, define a grammar and
+        attach a parse action to it that modifies the returned token list.
+        Invoking C{transformString()} on a target string will then scan for matches,
+        and replace the matched text patterns according to the logic in the parse
+        action.  C{transformString()} returns the resulting transformed string.
+        
+        Example::
+            wd = Word(alphas)
+            wd.setParseAction(lambda toks: toks[0].title())
+            
+            print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york."))
+        Prints::
+            Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York.
+        """
+        out = []
+        lastE = 0
+        # force preservation of s, to minimize unwanted transformation of string, and to
+        # keep string locs straight between transformString and scanString
+        self.keepTabs = True
+        try:
+            for t,s,e in self.scanString( instring ):
+                out.append( instring[lastE:s] )
+                if t:
+                    if isinstance(t,ParseResults):
+                        out += t.asList()
+                    elif isinstance(t,list):
+                        out += t
+                    else:
+                        out.append(t)
+                lastE = e
+            out.append(instring[lastE:])
+            out = [o for o in out if o]
+            return "".join(map(_ustr,_flatten(out)))
+        except ParseBaseException as exc:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                raise exc
+
+    def searchString( self, instring, maxMatches=_MAX_INT ):
+        """
+        Another extension to C{L{scanString}}, simplifying the access to the tokens found
+        to match the given parse expression.  May be called with optional
+        C{maxMatches} argument, to clip searching after 'n' matches are found.
+        
+        Example::
+            # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters
+            cap_word = Word(alphas.upper(), alphas.lower())
+            
+            print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))
+
+            # the sum() builtin can be used to merge results into a single ParseResults object
+            print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")))
+        prints::
+            [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']]
+            ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity']
+        """
+        try:
+            return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ])
+        except ParseBaseException as exc:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                raise exc
+
+    def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False):
+        """
+        Generator method to split a string using the given expression as a separator.
+        May be called with optional C{maxsplit} argument, to limit the number of splits;
+        and the optional C{includeSeparators} argument (default=C{False}), if the separating
+        matching text should be included in the split results.
+        
+        Example::        
+            punc = oneOf(list(".,;:/-!?"))
+            print(list(punc.split("This, this?, this sentence, is badly punctuated!")))
+        prints::
+            ['This', ' this', '', ' this sentence', ' is badly punctuated', '']
+        """
+        splits = 0
+        last = 0
+        for t,s,e in self.scanString(instring, maxMatches=maxsplit):
+            yield instring[last:s]
+            if includeSeparators:
+                yield t[0]
+            last = e
+        yield instring[last:]
+
+    def __add__(self, other ):
+        """
+        Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement
+        converts them to L{Literal}s by default.
+        
+        Example::
+            greet = Word(alphas) + "," + Word(alphas) + "!"
+            hello = "Hello, World!"
+            print (hello, "->", greet.parseString(hello))
+        Prints::
+            Hello, World! -> ['Hello', ',', 'World', '!']
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return And( [ self, other ] )
+
+    def __radd__(self, other ):
+        """
+        Implementation of + operator when left operand is not a C{L{ParserElement}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other + self
+
+    def __sub__(self, other):
+        """
+        Implementation of - operator, returns C{L{And}} with error stop
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return self + And._ErrorStop() + other
+
+    def __rsub__(self, other ):
+        """
+        Implementation of - operator when left operand is not a C{L{ParserElement}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other - self
+
+    def __mul__(self,other):
+        """
+        Implementation of * operator, allows use of C{expr * 3} in place of
+        C{expr + expr + expr}.  Expressions may also me multiplied by a 2-integer
+        tuple, similar to C{{min,max}} multipliers in regular expressions.  Tuples
+        may also include C{None} as in:
+         - C{expr*(n,None)} or C{expr*(n,)} is equivalent
+              to C{expr*n + L{ZeroOrMore}(expr)}
+              (read as "at least n instances of C{expr}")
+         - C{expr*(None,n)} is equivalent to C{expr*(0,n)}
+              (read as "0 to n instances of C{expr}")
+         - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)}
+         - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)}
+
+        Note that C{expr*(None,n)} does not raise an exception if
+        more than n exprs exist in the input stream; that is,
+        C{expr*(None,n)} does not enforce a maximum number of expr
+        occurrences.  If this behavior is desired, then write
+        C{expr*(None,n) + ~expr}
+        """
+        if isinstance(other,int):
+            minElements, optElements = other,0
+        elif isinstance(other,tuple):
+            other = (other + (None, None))[:2]
+            if other[0] is None:
+                other = (0, other[1])
+            if isinstance(other[0],int) and other[1] is None:
+                if other[0] == 0:
+                    return ZeroOrMore(self)
+                if other[0] == 1:
+                    return OneOrMore(self)
+                else:
+                    return self*other[0] + ZeroOrMore(self)
+            elif isinstance(other[0],int) and isinstance(other[1],int):
+                minElements, optElements = other
+                optElements -= minElements
+            else:
+                raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1]))
+        else:
+            raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other))
+
+        if minElements < 0:
+            raise ValueError("cannot multiply ParserElement by negative value")
+        if optElements < 0:
+            raise ValueError("second tuple value must be greater or equal to first tuple value")
+        if minElements == optElements == 0:
+            raise ValueError("cannot multiply ParserElement by 0 or (0,0)")
+
+        if (optElements):
+            def makeOptionalList(n):
+                if n>1:
+                    return Optional(self + makeOptionalList(n-1))
+                else:
+                    return Optional(self)
+            if minElements:
+                if minElements == 1:
+                    ret = self + makeOptionalList(optElements)
+                else:
+                    ret = And([self]*minElements) + makeOptionalList(optElements)
+            else:
+                ret = makeOptionalList(optElements)
+        else:
+            if minElements == 1:
+                ret = self
+            else:
+                ret = And([self]*minElements)
+        return ret
+
+    def __rmul__(self, other):
+        return self.__mul__(other)
+
+    def __or__(self, other ):
+        """
+        Implementation of | operator - returns C{L{MatchFirst}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return MatchFirst( [ self, other ] )
+
+    def __ror__(self, other ):
+        """
+        Implementation of | operator when left operand is not a C{L{ParserElement}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other | self
+
+    def __xor__(self, other ):
+        """
+        Implementation of ^ operator - returns C{L{Or}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return Or( [ self, other ] )
+
+    def __rxor__(self, other ):
+        """
+        Implementation of ^ operator when left operand is not a C{L{ParserElement}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other ^ self
+
+    def __and__(self, other ):
+        """
+        Implementation of & operator - returns C{L{Each}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return Each( [ self, other ] )
+
+    def __rand__(self, other ):
+        """
+        Implementation of & operator when left operand is not a C{L{ParserElement}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other & self
+
+    def __invert__( self ):
+        """
+        Implementation of ~ operator - returns C{L{NotAny}}
+        """
+        return NotAny( self )
+
+    def __call__(self, name=None):
+        """
+        Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}.
+        
+        If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be
+        passed as C{True}.
+           
+        If C{name} is omitted, same as calling C{L{copy}}.
+
+        Example::
+            # these are equivalent
+            userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno")
+            userdata = Word(alphas)("name") + Word(nums+"-")("socsecno")             
+        """
+        if name is not None:
+            return self.setResultsName(name)
+        else:
+            return self.copy()
+
+    def suppress( self ):
+        """
+        Suppresses the output of this C{ParserElement}; useful to keep punctuation from
+        cluttering up returned output.
+        """
+        return Suppress( self )
+
+    def leaveWhitespace( self ):
+        """
+        Disables the skipping of whitespace before matching the characters in the
+        C{ParserElement}'s defined pattern.  This is normally only used internally by
+        the pyparsing module, but may be needed in some whitespace-sensitive grammars.
+        """
+        self.skipWhitespace = False
+        return self
+
+    def setWhitespaceChars( self, chars ):
+        """
+        Overrides the default whitespace chars
+        """
+        self.skipWhitespace = True
+        self.whiteChars = chars
+        self.copyDefaultWhiteChars = False
+        return self
+
+    def parseWithTabs( self ):
+        """
+        Overrides default behavior to expand C{}s to spaces before parsing the input string.
+        Must be called before C{parseString} when the input grammar contains elements that
+        match C{} characters.
+        """
+        self.keepTabs = True
+        return self
+
+    def ignore( self, other ):
+        """
+        Define expression to be ignored (e.g., comments) while doing pattern
+        matching; may be called repeatedly, to define multiple comment or other
+        ignorable patterns.
+        
+        Example::
+            patt = OneOrMore(Word(alphas))
+            patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj']
+            
+            patt.ignore(cStyleComment)
+            patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd']
+        """
+        if isinstance(other, basestring):
+            other = Suppress(other)
+
+        if isinstance( other, Suppress ):
+            if other not in self.ignoreExprs:
+                self.ignoreExprs.append(other)
+        else:
+            self.ignoreExprs.append( Suppress( other.copy() ) )
+        return self
+
+    def setDebugActions( self, startAction, successAction, exceptionAction ):
+        """
+        Enable display of debugging messages while doing pattern matching.
+        """
+        self.debugActions = (startAction or _defaultStartDebugAction,
+                             successAction or _defaultSuccessDebugAction,
+                             exceptionAction or _defaultExceptionDebugAction)
+        self.debug = True
+        return self
+
+    def setDebug( self, flag=True ):
+        """
+        Enable display of debugging messages while doing pattern matching.
+        Set C{flag} to True to enable, False to disable.
+
+        Example::
+            wd = Word(alphas).setName("alphaword")
+            integer = Word(nums).setName("numword")
+            term = wd | integer
+            
+            # turn on debugging for wd
+            wd.setDebug()
+
+            OneOrMore(term).parseString("abc 123 xyz 890")
+        
+        prints::
+            Match alphaword at loc 0(1,1)
+            Matched alphaword -> ['abc']
+            Match alphaword at loc 3(1,4)
+            Exception raised:Expected alphaword (at char 4), (line:1, col:5)
+            Match alphaword at loc 7(1,8)
+            Matched alphaword -> ['xyz']
+            Match alphaword at loc 11(1,12)
+            Exception raised:Expected alphaword (at char 12), (line:1, col:13)
+            Match alphaword at loc 15(1,16)
+            Exception raised:Expected alphaword (at char 15), (line:1, col:16)
+
+        The output shown is that produced by the default debug actions - custom debug actions can be
+        specified using L{setDebugActions}. Prior to attempting
+        to match the C{wd} expression, the debugging message C{"Match  at loc (,)"}
+        is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"}
+        message is shown. Also note the use of L{setName} to assign a human-readable name to the expression,
+        which makes debugging and exception messages easier to understand - for instance, the default
+        name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}.
+        """
+        if flag:
+            self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction )
+        else:
+            self.debug = False
+        return self
+
+    def __str__( self ):
+        return self.name
+
+    def __repr__( self ):
+        return _ustr(self)
+
+    def streamline( self ):
+        self.streamlined = True
+        self.strRepr = None
+        return self
+
+    def checkRecursion( self, parseElementList ):
+        pass
+
+    def validate( self, validateTrace=[] ):
+        """
+        Check defined expressions for valid structure, check for infinite recursive definitions.
+        """
+        self.checkRecursion( [] )
+
+    def parseFile( self, file_or_filename, parseAll=False ):
+        """
+        Execute the parse expression on the given file or filename.
+        If a filename is specified (instead of a file object),
+        the entire file is opened, read, and closed before parsing.
+        """
+        try:
+            file_contents = file_or_filename.read()
+        except AttributeError:
+            with open(file_or_filename, "r") as f:
+                file_contents = f.read()
+        try:
+            return self.parseString(file_contents, parseAll)
+        except ParseBaseException as exc:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                raise exc
+
+    def __eq__(self,other):
+        if isinstance(other, ParserElement):
+            return self is other or vars(self) == vars(other)
+        elif isinstance(other, basestring):
+            return self.matches(other)
+        else:
+            return super(ParserElement,self)==other
+
+    def __ne__(self,other):
+        return not (self == other)
+
+    def __hash__(self):
+        return hash(id(self))
+
+    def __req__(self,other):
+        return self == other
+
+    def __rne__(self,other):
+        return not (self == other)
+
+    def matches(self, testString, parseAll=True):
+        """
+        Method for quick testing of a parser against a test string. Good for simple 
+        inline microtests of sub expressions while building up larger parser.
+           
+        Parameters:
+         - testString - to test against this expression for a match
+         - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests
+            
+        Example::
+            expr = Word(nums)
+            assert expr.matches("100")
+        """
+        try:
+            self.parseString(_ustr(testString), parseAll=parseAll)
+            return True
+        except ParseBaseException:
+            return False
+                
+    def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False):
+        """
+        Execute the parse expression on a series of test strings, showing each
+        test, the parsed results or where the parse failed. Quick and easy way to
+        run a parse expression against a list of sample strings.
+           
+        Parameters:
+         - tests - a list of separate test strings, or a multiline string of test strings
+         - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests           
+         - comment - (default=C{'#'}) - expression for indicating embedded comments in the test 
+              string; pass None to disable comment filtering
+         - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline;
+              if False, only dump nested list
+         - printResults - (default=C{True}) prints test output to stdout
+         - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing
+
+        Returns: a (success, results) tuple, where success indicates that all tests succeeded
+        (or failed if C{failureTests} is True), and the results contain a list of lines of each 
+        test's output
+        
+        Example::
+            number_expr = pyparsing_common.number.copy()
+
+            result = number_expr.runTests('''
+                # unsigned integer
+                100
+                # negative integer
+                -100
+                # float with scientific notation
+                6.02e23
+                # integer with scientific notation
+                1e-12
+                ''')
+            print("Success" if result[0] else "Failed!")
+
+            result = number_expr.runTests('''
+                # stray character
+                100Z
+                # missing leading digit before '.'
+                -.100
+                # too many '.'
+                3.14.159
+                ''', failureTests=True)
+            print("Success" if result[0] else "Failed!")
+        prints::
+            # unsigned integer
+            100
+            [100]
+
+            # negative integer
+            -100
+            [-100]
+
+            # float with scientific notation
+            6.02e23
+            [6.02e+23]
+
+            # integer with scientific notation
+            1e-12
+            [1e-12]
+
+            Success
+            
+            # stray character
+            100Z
+               ^
+            FAIL: Expected end of text (at char 3), (line:1, col:4)
+
+            # missing leading digit before '.'
+            -.100
+            ^
+            FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1)
+
+            # too many '.'
+            3.14.159
+                ^
+            FAIL: Expected end of text (at char 4), (line:1, col:5)
+
+            Success
+
+        Each test string must be on a single line. If you want to test a string that spans multiple
+        lines, create a test like this::
+
+            expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines")
+        
+        (Note that this is a raw string literal, you must include the leading 'r'.)
+        """
+        if isinstance(tests, basestring):
+            tests = list(map(str.strip, tests.rstrip().splitlines()))
+        if isinstance(comment, basestring):
+            comment = Literal(comment)
+        allResults = []
+        comments = []
+        success = True
+        for t in tests:
+            if comment is not None and comment.matches(t, False) or comments and not t:
+                comments.append(t)
+                continue
+            if not t:
+                continue
+            out = ['\n'.join(comments), t]
+            comments = []
+            try:
+                t = t.replace(r'\n','\n')
+                result = self.parseString(t, parseAll=parseAll)
+                out.append(result.dump(full=fullDump))
+                success = success and not failureTests
+            except ParseBaseException as pe:
+                fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else ""
+                if '\n' in t:
+                    out.append(line(pe.loc, t))
+                    out.append(' '*(col(pe.loc,t)-1) + '^' + fatal)
+                else:
+                    out.append(' '*pe.loc + '^' + fatal)
+                out.append("FAIL: " + str(pe))
+                success = success and failureTests
+                result = pe
+            except Exception as exc:
+                out.append("FAIL-EXCEPTION: " + str(exc))
+                success = success and failureTests
+                result = exc
+
+            if printResults:
+                if fullDump:
+                    out.append('')
+                print('\n'.join(out))
+
+            allResults.append((t, result))
+        
+        return success, allResults
+
+        
+class Token(ParserElement):
+    """
+    Abstract C{ParserElement} subclass, for defining atomic matching patterns.
+    """
+    def __init__( self ):
+        super(Token,self).__init__( savelist=False )
+
+
+class Empty(Token):
+    """
+    An empty token, will always match.
+    """
+    def __init__( self ):
+        super(Empty,self).__init__()
+        self.name = "Empty"
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+
+
+class NoMatch(Token):
+    """
+    A token that will never match.
+    """
+    def __init__( self ):
+        super(NoMatch,self).__init__()
+        self.name = "NoMatch"
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+        self.errmsg = "Unmatchable token"
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        raise ParseException(instring, loc, self.errmsg, self)
+
+
+class Literal(Token):
+    """
+    Token to exactly match a specified string.
+    
+    Example::
+        Literal('blah').parseString('blah')  # -> ['blah']
+        Literal('blah').parseString('blahfooblah')  # -> ['blah']
+        Literal('blah').parseString('bla')  # -> Exception: Expected "blah"
+    
+    For case-insensitive matching, use L{CaselessLiteral}.
+    
+    For keyword matching (force word break before and after the matched string),
+    use L{Keyword} or L{CaselessKeyword}.
+    """
+    def __init__( self, matchString ):
+        super(Literal,self).__init__()
+        self.match = matchString
+        self.matchLen = len(matchString)
+        try:
+            self.firstMatchChar = matchString[0]
+        except IndexError:
+            warnings.warn("null string passed to Literal; use Empty() instead",
+                            SyntaxWarning, stacklevel=2)
+            self.__class__ = Empty
+        self.name = '"%s"' % _ustr(self.match)
+        self.errmsg = "Expected " + self.name
+        self.mayReturnEmpty = False
+        self.mayIndexError = False
+
+    # Performance tuning: this routine gets called a *lot*
+    # if this is a single character match string  and the first character matches,
+    # short-circuit as quickly as possible, and avoid calling startswith
+    #~ @profile
+    def parseImpl( self, instring, loc, doActions=True ):
+        if (instring[loc] == self.firstMatchChar and
+            (self.matchLen==1 or instring.startswith(self.match,loc)) ):
+            return loc+self.matchLen, self.match
+        raise ParseException(instring, loc, self.errmsg, self)
+_L = Literal
+ParserElement._literalStringClass = Literal
+
+class Keyword(Token):
+    """
+    Token to exactly match a specified string as a keyword, that is, it must be
+    immediately followed by a non-keyword character.  Compare with C{L{Literal}}:
+     - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}.
+     - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'}
+    Accepts two optional constructor arguments in addition to the keyword string:
+     - C{identChars} is a string of characters that would be valid identifier characters,
+          defaulting to all alphanumerics + "_" and "$"
+     - C{caseless} allows case-insensitive matching, default is C{False}.
+       
+    Example::
+        Keyword("start").parseString("start")  # -> ['start']
+        Keyword("start").parseString("starting")  # -> Exception
+
+    For case-insensitive matching, use L{CaselessKeyword}.
+    """
+    DEFAULT_KEYWORD_CHARS = alphanums+"_$"
+
+    def __init__( self, matchString, identChars=None, caseless=False ):
+        super(Keyword,self).__init__()
+        if identChars is None:
+            identChars = Keyword.DEFAULT_KEYWORD_CHARS
+        self.match = matchString
+        self.matchLen = len(matchString)
+        try:
+            self.firstMatchChar = matchString[0]
+        except IndexError:
+            warnings.warn("null string passed to Keyword; use Empty() instead",
+                            SyntaxWarning, stacklevel=2)
+        self.name = '"%s"' % self.match
+        self.errmsg = "Expected " + self.name
+        self.mayReturnEmpty = False
+        self.mayIndexError = False
+        self.caseless = caseless
+        if caseless:
+            self.caselessmatch = matchString.upper()
+            identChars = identChars.upper()
+        self.identChars = set(identChars)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.caseless:
+            if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
+                 (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and
+                 (loc == 0 or instring[loc-1].upper() not in self.identChars) ):
+                return loc+self.matchLen, self.match
+        else:
+            if (instring[loc] == self.firstMatchChar and
+                (self.matchLen==1 or instring.startswith(self.match,loc)) and
+                (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and
+                (loc == 0 or instring[loc-1] not in self.identChars) ):
+                return loc+self.matchLen, self.match
+        raise ParseException(instring, loc, self.errmsg, self)
+
+    def copy(self):
+        c = super(Keyword,self).copy()
+        c.identChars = Keyword.DEFAULT_KEYWORD_CHARS
+        return c
+
+    @staticmethod
+    def setDefaultKeywordChars( chars ):
+        """Overrides the default Keyword chars
+        """
+        Keyword.DEFAULT_KEYWORD_CHARS = chars
+
+class CaselessLiteral(Literal):
+    """
+    Token to match a specified string, ignoring case of letters.
+    Note: the matched results will always be in the case of the given
+    match string, NOT the case of the input text.
+
+    Example::
+        OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD']
+        
+    (Contrast with example for L{CaselessKeyword}.)
+    """
+    def __init__( self, matchString ):
+        super(CaselessLiteral,self).__init__( matchString.upper() )
+        # Preserve the defining literal.
+        self.returnString = matchString
+        self.name = "'%s'" % self.returnString
+        self.errmsg = "Expected " + self.name
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if instring[ loc:loc+self.matchLen ].upper() == self.match:
+            return loc+self.matchLen, self.returnString
+        raise ParseException(instring, loc, self.errmsg, self)
+
+class CaselessKeyword(Keyword):
+    """
+    Caseless version of L{Keyword}.
+
+    Example::
+        OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD']
+        
+    (Contrast with example for L{CaselessLiteral}.)
+    """
+    def __init__( self, matchString, identChars=None ):
+        super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True )
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
+             (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ):
+            return loc+self.matchLen, self.match
+        raise ParseException(instring, loc, self.errmsg, self)
+
+class CloseMatch(Token):
+    """
+    A variation on L{Literal} which matches "close" matches, that is, 
+    strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters:
+     - C{match_string} - string to be matched
+     - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match
+    
+    The results from a successful parse will contain the matched text from the input string and the following named results:
+     - C{mismatches} - a list of the positions within the match_string where mismatches were found
+     - C{original} - the original match_string used to compare against the input string
+    
+    If C{mismatches} is an empty list, then the match was an exact match.
+    
+    Example::
+        patt = CloseMatch("ATCATCGAATGGA")
+        patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']})
+        patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1)
+
+        # exact match
+        patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']})
+
+        # close match allowing up to 2 mismatches
+        patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2)
+        patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']})
+    """
+    def __init__(self, match_string, maxMismatches=1):
+        super(CloseMatch,self).__init__()
+        self.name = match_string
+        self.match_string = match_string
+        self.maxMismatches = maxMismatches
+        self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches)
+        self.mayIndexError = False
+        self.mayReturnEmpty = False
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        start = loc
+        instrlen = len(instring)
+        maxloc = start + len(self.match_string)
+
+        if maxloc <= instrlen:
+            match_string = self.match_string
+            match_stringloc = 0
+            mismatches = []
+            maxMismatches = self.maxMismatches
+
+            for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)):
+                src,mat = s_m
+                if src != mat:
+                    mismatches.append(match_stringloc)
+                    if len(mismatches) > maxMismatches:
+                        break
+            else:
+                loc = match_stringloc + 1
+                results = ParseResults([instring[start:loc]])
+                results['original'] = self.match_string
+                results['mismatches'] = mismatches
+                return loc, results
+
+        raise ParseException(instring, loc, self.errmsg, self)
+
+
+class Word(Token):
+    """
+    Token for matching words composed of allowed character sets.
+    Defined with string containing all allowed initial characters,
+    an optional string containing allowed body characters (if omitted,
+    defaults to the initial character set), and an optional minimum,
+    maximum, and/or exact length.  The default value for C{min} is 1 (a
+    minimum value < 1 is not valid); the default values for C{max} and C{exact}
+    are 0, meaning no maximum or exact length restriction. An optional
+    C{excludeChars} parameter can list characters that might be found in 
+    the input C{bodyChars} string; useful to define a word of all printables
+    except for one or two characters, for instance.
+    
+    L{srange} is useful for defining custom character set strings for defining 
+    C{Word} expressions, using range notation from regular expression character sets.
+    
+    A common mistake is to use C{Word} to match a specific literal string, as in 
+    C{Word("Address")}. Remember that C{Word} uses the string argument to define
+    I{sets} of matchable characters. This expression would match "Add", "AAA",
+    "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'.
+    To match an exact literal string, use L{Literal} or L{Keyword}.
+
+    pyparsing includes helper strings for building Words:
+     - L{alphas}
+     - L{nums}
+     - L{alphanums}
+     - L{hexnums}
+     - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.)
+     - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.)
+     - L{printables} (any non-whitespace character)
+
+    Example::
+        # a word composed of digits
+        integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9"))
+        
+        # a word with a leading capital, and zero or more lowercase
+        capital_word = Word(alphas.upper(), alphas.lower())
+
+        # hostnames are alphanumeric, with leading alpha, and '-'
+        hostname = Word(alphas, alphanums+'-')
+        
+        # roman numeral (not a strict parser, accepts invalid mix of characters)
+        roman = Word("IVXLCDM")
+        
+        # any string of non-whitespace characters, except for ','
+        csv_value = Word(printables, excludeChars=",")
+    """
+    def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ):
+        super(Word,self).__init__()
+        if excludeChars:
+            initChars = ''.join(c for c in initChars if c not in excludeChars)
+            if bodyChars:
+                bodyChars = ''.join(c for c in bodyChars if c not in excludeChars)
+        self.initCharsOrig = initChars
+        self.initChars = set(initChars)
+        if bodyChars :
+            self.bodyCharsOrig = bodyChars
+            self.bodyChars = set(bodyChars)
+        else:
+            self.bodyCharsOrig = initChars
+            self.bodyChars = set(initChars)
+
+        self.maxSpecified = max > 0
+
+        if min < 1:
+            raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted")
+
+        self.minLen = min
+
+        if max > 0:
+            self.maxLen = max
+        else:
+            self.maxLen = _MAX_INT
+
+        if exact > 0:
+            self.maxLen = exact
+            self.minLen = exact
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayIndexError = False
+        self.asKeyword = asKeyword
+
+        if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0):
+            if self.bodyCharsOrig == self.initCharsOrig:
+                self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig)
+            elif len(self.initCharsOrig) == 1:
+                self.reString = "%s[%s]*" % \
+                                      (re.escape(self.initCharsOrig),
+                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
+            else:
+                self.reString = "[%s][%s]*" % \
+                                      (_escapeRegexRangeChars(self.initCharsOrig),
+                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
+            if self.asKeyword:
+                self.reString = r"\b"+self.reString+r"\b"
+            try:
+                self.re = re.compile( self.reString )
+            except Exception:
+                self.re = None
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.re:
+            result = self.re.match(instring,loc)
+            if not result:
+                raise ParseException(instring, loc, self.errmsg, self)
+
+            loc = result.end()
+            return loc, result.group()
+
+        if not(instring[ loc ] in self.initChars):
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        start = loc
+        loc += 1
+        instrlen = len(instring)
+        bodychars = self.bodyChars
+        maxloc = start + self.maxLen
+        maxloc = min( maxloc, instrlen )
+        while loc < maxloc and instring[loc] in bodychars:
+            loc += 1
+
+        throwException = False
+        if loc - start < self.minLen:
+            throwException = True
+        if self.maxSpecified and loc < instrlen and instring[loc] in bodychars:
+            throwException = True
+        if self.asKeyword:
+            if (start>0 and instring[start-1] in bodychars) or (loc4:
+                    return s[:4]+"..."
+                else:
+                    return s
+
+            if ( self.initCharsOrig != self.bodyCharsOrig ):
+                self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) )
+            else:
+                self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig)
+
+        return self.strRepr
+
+
+class Regex(Token):
+    r"""
+    Token for matching strings that match a given regular expression.
+    Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module.
+    If the given regex contains named groups (defined using C{(?P...)}), these will be preserved as 
+    named parse results.
+
+    Example::
+        realnum = Regex(r"[+-]?\d+\.\d*")
+        date = Regex(r'(?P\d{4})-(?P\d\d?)-(?P\d\d?)')
+        # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression
+        roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})")
+    """
+    compiledREtype = type(re.compile("[A-Z]"))
+    def __init__( self, pattern, flags=0):
+        """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags."""
+        super(Regex,self).__init__()
+
+        if isinstance(pattern, basestring):
+            if not pattern:
+                warnings.warn("null string passed to Regex; use Empty() instead",
+                        SyntaxWarning, stacklevel=2)
+
+            self.pattern = pattern
+            self.flags = flags
+
+            try:
+                self.re = re.compile(self.pattern, self.flags)
+                self.reString = self.pattern
+            except sre_constants.error:
+                warnings.warn("invalid pattern (%s) passed to Regex" % pattern,
+                    SyntaxWarning, stacklevel=2)
+                raise
+
+        elif isinstance(pattern, Regex.compiledREtype):
+            self.re = pattern
+            self.pattern = \
+            self.reString = str(pattern)
+            self.flags = flags
+            
+        else:
+            raise ValueError("Regex may only be constructed with a string or a compiled RE object")
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayIndexError = False
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        result = self.re.match(instring,loc)
+        if not result:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        loc = result.end()
+        d = result.groupdict()
+        ret = ParseResults(result.group())
+        if d:
+            for k in d:
+                ret[k] = d[k]
+        return loc,ret
+
+    def __str__( self ):
+        try:
+            return super(Regex,self).__str__()
+        except Exception:
+            pass
+
+        if self.strRepr is None:
+            self.strRepr = "Re:(%s)" % repr(self.pattern)
+
+        return self.strRepr
+
+
+class QuotedString(Token):
+    r"""
+    Token for matching strings that are delimited by quoting characters.
+    
+    Defined with the following parameters:
+        - quoteChar - string of one or more characters defining the quote delimiting string
+        - escChar - character to escape quotes, typically backslash (default=C{None})
+        - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None})
+        - multiline - boolean indicating whether quotes can span multiple lines (default=C{False})
+        - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True})
+        - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar)
+        - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True})
+
+    Example::
+        qs = QuotedString('"')
+        print(qs.searchString('lsjdf "This is the quote" sldjf'))
+        complex_qs = QuotedString('{{', endQuoteChar='}}')
+        print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf'))
+        sql_qs = QuotedString('"', escQuote='""')
+        print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf'))
+    prints::
+        [['This is the quote']]
+        [['This is the "quote"']]
+        [['This is the quote with "embedded" quotes']]
+    """
+    def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True):
+        super(QuotedString,self).__init__()
+
+        # remove white space from quote chars - wont work anyway
+        quoteChar = quoteChar.strip()
+        if not quoteChar:
+            warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
+            raise SyntaxError()
+
+        if endQuoteChar is None:
+            endQuoteChar = quoteChar
+        else:
+            endQuoteChar = endQuoteChar.strip()
+            if not endQuoteChar:
+                warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
+                raise SyntaxError()
+
+        self.quoteChar = quoteChar
+        self.quoteCharLen = len(quoteChar)
+        self.firstQuoteChar = quoteChar[0]
+        self.endQuoteChar = endQuoteChar
+        self.endQuoteCharLen = len(endQuoteChar)
+        self.escChar = escChar
+        self.escQuote = escQuote
+        self.unquoteResults = unquoteResults
+        self.convertWhitespaceEscapes = convertWhitespaceEscapes
+
+        if multiline:
+            self.flags = re.MULTILINE | re.DOTALL
+            self.pattern = r'%s(?:[^%s%s]' % \
+                ( re.escape(self.quoteChar),
+                  _escapeRegexRangeChars(self.endQuoteChar[0]),
+                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
+        else:
+            self.flags = 0
+            self.pattern = r'%s(?:[^%s\n\r%s]' % \
+                ( re.escape(self.quoteChar),
+                  _escapeRegexRangeChars(self.endQuoteChar[0]),
+                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
+        if len(self.endQuoteChar) > 1:
+            self.pattern += (
+                '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]),
+                                               _escapeRegexRangeChars(self.endQuoteChar[i]))
+                                    for i in range(len(self.endQuoteChar)-1,0,-1)) + ')'
+                )
+        if escQuote:
+            self.pattern += (r'|(?:%s)' % re.escape(escQuote))
+        if escChar:
+            self.pattern += (r'|(?:%s.)' % re.escape(escChar))
+            self.escCharReplacePattern = re.escape(self.escChar)+"(.)"
+        self.pattern += (r')*%s' % re.escape(self.endQuoteChar))
+
+        try:
+            self.re = re.compile(self.pattern, self.flags)
+            self.reString = self.pattern
+        except sre_constants.error:
+            warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern,
+                SyntaxWarning, stacklevel=2)
+            raise
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayIndexError = False
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None
+        if not result:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        loc = result.end()
+        ret = result.group()
+
+        if self.unquoteResults:
+
+            # strip off quotes
+            ret = ret[self.quoteCharLen:-self.endQuoteCharLen]
+
+            if isinstance(ret,basestring):
+                # replace escaped whitespace
+                if '\\' in ret and self.convertWhitespaceEscapes:
+                    ws_map = {
+                        r'\t' : '\t',
+                        r'\n' : '\n',
+                        r'\f' : '\f',
+                        r'\r' : '\r',
+                    }
+                    for wslit,wschar in ws_map.items():
+                        ret = ret.replace(wslit, wschar)
+
+                # replace escaped characters
+                if self.escChar:
+                    ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret)
+
+                # replace escaped quotes
+                if self.escQuote:
+                    ret = ret.replace(self.escQuote, self.endQuoteChar)
+
+        return loc, ret
+
+    def __str__( self ):
+        try:
+            return super(QuotedString,self).__str__()
+        except Exception:
+            pass
+
+        if self.strRepr is None:
+            self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar)
+
+        return self.strRepr
+
+
+class CharsNotIn(Token):
+    """
+    Token for matching words composed of characters I{not} in a given set (will
+    include whitespace in matched characters if not listed in the provided exclusion set - see example).
+    Defined with string containing all disallowed characters, and an optional
+    minimum, maximum, and/or exact length.  The default value for C{min} is 1 (a
+    minimum value < 1 is not valid); the default values for C{max} and C{exact}
+    are 0, meaning no maximum or exact length restriction.
+
+    Example::
+        # define a comma-separated-value as anything that is not a ','
+        csv_value = CharsNotIn(',')
+        print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213"))
+    prints::
+        ['dkls', 'lsdkjf', 's12 34', '@!#', '213']
+    """
+    def __init__( self, notChars, min=1, max=0, exact=0 ):
+        super(CharsNotIn,self).__init__()
+        self.skipWhitespace = False
+        self.notChars = notChars
+
+        if min < 1:
+            raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted")
+
+        self.minLen = min
+
+        if max > 0:
+            self.maxLen = max
+        else:
+            self.maxLen = _MAX_INT
+
+        if exact > 0:
+            self.maxLen = exact
+            self.minLen = exact
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayReturnEmpty = ( self.minLen == 0 )
+        self.mayIndexError = False
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if instring[loc] in self.notChars:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        start = loc
+        loc += 1
+        notchars = self.notChars
+        maxlen = min( start+self.maxLen, len(instring) )
+        while loc < maxlen and \
+              (instring[loc] not in notchars):
+            loc += 1
+
+        if loc - start < self.minLen:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        return loc, instring[start:loc]
+
+    def __str__( self ):
+        try:
+            return super(CharsNotIn, self).__str__()
+        except Exception:
+            pass
+
+        if self.strRepr is None:
+            if len(self.notChars) > 4:
+                self.strRepr = "!W:(%s...)" % self.notChars[:4]
+            else:
+                self.strRepr = "!W:(%s)" % self.notChars
+
+        return self.strRepr
+
+class White(Token):
+    """
+    Special matching class for matching whitespace.  Normally, whitespace is ignored
+    by pyparsing grammars.  This class is included when some whitespace structures
+    are significant.  Define with a string containing the whitespace characters to be
+    matched; default is C{" \\t\\r\\n"}.  Also takes optional C{min}, C{max}, and C{exact} arguments,
+    as defined for the C{L{Word}} class.
+    """
+    whiteStrs = {
+        " " : "",
+        "\t": "",
+        "\n": "",
+        "\r": "",
+        "\f": "",
+        }
+    def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0):
+        super(White,self).__init__()
+        self.matchWhite = ws
+        self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) )
+        #~ self.leaveWhitespace()
+        self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite))
+        self.mayReturnEmpty = True
+        self.errmsg = "Expected " + self.name
+
+        self.minLen = min
+
+        if max > 0:
+            self.maxLen = max
+        else:
+            self.maxLen = _MAX_INT
+
+        if exact > 0:
+            self.maxLen = exact
+            self.minLen = exact
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if not(instring[ loc ] in self.matchWhite):
+            raise ParseException(instring, loc, self.errmsg, self)
+        start = loc
+        loc += 1
+        maxloc = start + self.maxLen
+        maxloc = min( maxloc, len(instring) )
+        while loc < maxloc and instring[loc] in self.matchWhite:
+            loc += 1
+
+        if loc - start < self.minLen:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        return loc, instring[start:loc]
+
+
+class _PositionToken(Token):
+    def __init__( self ):
+        super(_PositionToken,self).__init__()
+        self.name=self.__class__.__name__
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+
+class GoToColumn(_PositionToken):
+    """
+    Token to advance to a specific column of input text; useful for tabular report scraping.
+    """
+    def __init__( self, colno ):
+        super(GoToColumn,self).__init__()
+        self.col = colno
+
+    def preParse( self, instring, loc ):
+        if col(loc,instring) != self.col:
+            instrlen = len(instring)
+            if self.ignoreExprs:
+                loc = self._skipIgnorables( instring, loc )
+            while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col :
+                loc += 1
+        return loc
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        thiscol = col( loc, instring )
+        if thiscol > self.col:
+            raise ParseException( instring, loc, "Text not in expected column", self )
+        newloc = loc + self.col - thiscol
+        ret = instring[ loc: newloc ]
+        return newloc, ret
+
+
+class LineStart(_PositionToken):
+    """
+    Matches if current position is at the beginning of a line within the parse string
+    
+    Example::
+    
+        test = '''\
+        AAA this line
+        AAA and this line
+          AAA but not this one
+        B AAA and definitely not this one
+        '''
+
+        for t in (LineStart() + 'AAA' + restOfLine).searchString(test):
+            print(t)
+    
+    Prints::
+        ['AAA', ' this line']
+        ['AAA', ' and this line']    
+
+    """
+    def __init__( self ):
+        super(LineStart,self).__init__()
+        self.errmsg = "Expected start of line"
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if col(loc, instring) == 1:
+            return loc, []
+        raise ParseException(instring, loc, self.errmsg, self)
+
+class LineEnd(_PositionToken):
+    """
+    Matches if current position is at the end of a line within the parse string
+    """
+    def __init__( self ):
+        super(LineEnd,self).__init__()
+        self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") )
+        self.errmsg = "Expected end of line"
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if loc len(instring):
+            return loc, []
+        else:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+class WordStart(_PositionToken):
+    """
+    Matches if the current position is at the beginning of a Word, and
+    is not preceded by any character in a given set of C{wordChars}
+    (default=C{printables}). To emulate the C{\b} behavior of regular expressions,
+    use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of
+    the string being parsed, or at the beginning of a line.
+    """
+    def __init__(self, wordChars = printables):
+        super(WordStart,self).__init__()
+        self.wordChars = set(wordChars)
+        self.errmsg = "Not at the start of a word"
+
+    def parseImpl(self, instring, loc, doActions=True ):
+        if loc != 0:
+            if (instring[loc-1] in self.wordChars or
+                instring[loc] not in self.wordChars):
+                raise ParseException(instring, loc, self.errmsg, self)
+        return loc, []
+
+class WordEnd(_PositionToken):
+    """
+    Matches if the current position is at the end of a Word, and
+    is not followed by any character in a given set of C{wordChars}
+    (default=C{printables}). To emulate the C{\b} behavior of regular expressions,
+    use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of
+    the string being parsed, or at the end of a line.
+    """
+    def __init__(self, wordChars = printables):
+        super(WordEnd,self).__init__()
+        self.wordChars = set(wordChars)
+        self.skipWhitespace = False
+        self.errmsg = "Not at the end of a word"
+
+    def parseImpl(self, instring, loc, doActions=True ):
+        instrlen = len(instring)
+        if instrlen>0 and loc maxExcLoc:
+                    maxException = err
+                    maxExcLoc = err.loc
+            except IndexError:
+                if len(instring) > maxExcLoc:
+                    maxException = ParseException(instring,len(instring),e.errmsg,self)
+                    maxExcLoc = len(instring)
+            else:
+                # save match among all matches, to retry longest to shortest
+                matches.append((loc2, e))
+
+        if matches:
+            matches.sort(key=lambda x: -x[0])
+            for _,e in matches:
+                try:
+                    return e._parse( instring, loc, doActions )
+                except ParseException as err:
+                    err.__traceback__ = None
+                    if err.loc > maxExcLoc:
+                        maxException = err
+                        maxExcLoc = err.loc
+
+        if maxException is not None:
+            maxException.msg = self.errmsg
+            raise maxException
+        else:
+            raise ParseException(instring, loc, "no defined alternatives to match", self)
+
+
+    def __ixor__(self, other ):
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        return self.append( other ) #Or( [ self, other ] )
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}"
+
+        return self.strRepr
+
+    def checkRecursion( self, parseElementList ):
+        subRecCheckList = parseElementList[:] + [ self ]
+        for e in self.exprs:
+            e.checkRecursion( subRecCheckList )
+
+
+class MatchFirst(ParseExpression):
+    """
+    Requires that at least one C{ParseExpression} is found.
+    If two expressions match, the first one listed is the one that will match.
+    May be constructed using the C{'|'} operator.
+
+    Example::
+        # construct MatchFirst using '|' operator
+        
+        # watch the order of expressions to match
+        number = Word(nums) | Combine(Word(nums) + '.' + Word(nums))
+        print(number.searchString("123 3.1416 789")) #  Fail! -> [['123'], ['3'], ['1416'], ['789']]
+
+        # put more selective expression first
+        number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums)
+        print(number.searchString("123 3.1416 789")) #  Better -> [['123'], ['3.1416'], ['789']]
+    """
+    def __init__( self, exprs, savelist = False ):
+        super(MatchFirst,self).__init__(exprs, savelist)
+        if self.exprs:
+            self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs)
+        else:
+            self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        maxExcLoc = -1
+        maxException = None
+        for e in self.exprs:
+            try:
+                ret = e._parse( instring, loc, doActions )
+                return ret
+            except ParseException as err:
+                if err.loc > maxExcLoc:
+                    maxException = err
+                    maxExcLoc = err.loc
+            except IndexError:
+                if len(instring) > maxExcLoc:
+                    maxException = ParseException(instring,len(instring),e.errmsg,self)
+                    maxExcLoc = len(instring)
+
+        # only got here if no expression matched, raise exception for match that made it the furthest
+        else:
+            if maxException is not None:
+                maxException.msg = self.errmsg
+                raise maxException
+            else:
+                raise ParseException(instring, loc, "no defined alternatives to match", self)
+
+    def __ior__(self, other ):
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        return self.append( other ) #MatchFirst( [ self, other ] )
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}"
+
+        return self.strRepr
+
+    def checkRecursion( self, parseElementList ):
+        subRecCheckList = parseElementList[:] + [ self ]
+        for e in self.exprs:
+            e.checkRecursion( subRecCheckList )
+
+
+class Each(ParseExpression):
+    """
+    Requires all given C{ParseExpression}s to be found, but in any order.
+    Expressions may be separated by whitespace.
+    May be constructed using the C{'&'} operator.
+
+    Example::
+        color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN")
+        shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON")
+        integer = Word(nums)
+        shape_attr = "shape:" + shape_type("shape")
+        posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn")
+        color_attr = "color:" + color("color")
+        size_attr = "size:" + integer("size")
+
+        # use Each (using operator '&') to accept attributes in any order 
+        # (shape and posn are required, color and size are optional)
+        shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr)
+
+        shape_spec.runTests('''
+            shape: SQUARE color: BLACK posn: 100, 120
+            shape: CIRCLE size: 50 color: BLUE posn: 50,80
+            color:GREEN size:20 shape:TRIANGLE posn:20,40
+            '''
+            )
+    prints::
+        shape: SQUARE color: BLACK posn: 100, 120
+        ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']]
+        - color: BLACK
+        - posn: ['100', ',', '120']
+          - x: 100
+          - y: 120
+        - shape: SQUARE
+
+
+        shape: CIRCLE size: 50 color: BLUE posn: 50,80
+        ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']]
+        - color: BLUE
+        - posn: ['50', ',', '80']
+          - x: 50
+          - y: 80
+        - shape: CIRCLE
+        - size: 50
+
+
+        color: GREEN size: 20 shape: TRIANGLE posn: 20,40
+        ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']]
+        - color: GREEN
+        - posn: ['20', ',', '40']
+          - x: 20
+          - y: 40
+        - shape: TRIANGLE
+        - size: 20
+    """
+    def __init__( self, exprs, savelist = True ):
+        super(Each,self).__init__(exprs, savelist)
+        self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs)
+        self.skipWhitespace = True
+        self.initExprGroups = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.initExprGroups:
+            self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional))
+            opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ]
+            opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)]
+            self.optionals = opt1 + opt2
+            self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ]
+            self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ]
+            self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ]
+            self.required += self.multirequired
+            self.initExprGroups = False
+        tmpLoc = loc
+        tmpReqd = self.required[:]
+        tmpOpt  = self.optionals[:]
+        matchOrder = []
+
+        keepMatching = True
+        while keepMatching:
+            tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired
+            failed = []
+            for e in tmpExprs:
+                try:
+                    tmpLoc = e.tryParse( instring, tmpLoc )
+                except ParseException:
+                    failed.append(e)
+                else:
+                    matchOrder.append(self.opt1map.get(id(e),e))
+                    if e in tmpReqd:
+                        tmpReqd.remove(e)
+                    elif e in tmpOpt:
+                        tmpOpt.remove(e)
+            if len(failed) == len(tmpExprs):
+                keepMatching = False
+
+        if tmpReqd:
+            missing = ", ".join(_ustr(e) for e in tmpReqd)
+            raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing )
+
+        # add any unmatched Optionals, in case they have default values defined
+        matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt]
+
+        resultlist = []
+        for e in matchOrder:
+            loc,results = e._parse(instring,loc,doActions)
+            resultlist.append(results)
+
+        finalResults = sum(resultlist, ParseResults([]))
+        return loc, finalResults
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}"
+
+        return self.strRepr
+
+    def checkRecursion( self, parseElementList ):
+        subRecCheckList = parseElementList[:] + [ self ]
+        for e in self.exprs:
+            e.checkRecursion( subRecCheckList )
+
+
+class ParseElementEnhance(ParserElement):
+    """
+    Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens.
+    """
+    def __init__( self, expr, savelist=False ):
+        super(ParseElementEnhance,self).__init__(savelist)
+        if isinstance( expr, basestring ):
+            if issubclass(ParserElement._literalStringClass, Token):
+                expr = ParserElement._literalStringClass(expr)
+            else:
+                expr = ParserElement._literalStringClass(Literal(expr))
+        self.expr = expr
+        self.strRepr = None
+        if expr is not None:
+            self.mayIndexError = expr.mayIndexError
+            self.mayReturnEmpty = expr.mayReturnEmpty
+            self.setWhitespaceChars( expr.whiteChars )
+            self.skipWhitespace = expr.skipWhitespace
+            self.saveAsList = expr.saveAsList
+            self.callPreparse = expr.callPreparse
+            self.ignoreExprs.extend(expr.ignoreExprs)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.expr is not None:
+            return self.expr._parse( instring, loc, doActions, callPreParse=False )
+        else:
+            raise ParseException("",loc,self.errmsg,self)
+
+    def leaveWhitespace( self ):
+        self.skipWhitespace = False
+        self.expr = self.expr.copy()
+        if self.expr is not None:
+            self.expr.leaveWhitespace()
+        return self
+
+    def ignore( self, other ):
+        if isinstance( other, Suppress ):
+            if other not in self.ignoreExprs:
+                super( ParseElementEnhance, self).ignore( other )
+                if self.expr is not None:
+                    self.expr.ignore( self.ignoreExprs[-1] )
+        else:
+            super( ParseElementEnhance, self).ignore( other )
+            if self.expr is not None:
+                self.expr.ignore( self.ignoreExprs[-1] )
+        return self
+
+    def streamline( self ):
+        super(ParseElementEnhance,self).streamline()
+        if self.expr is not None:
+            self.expr.streamline()
+        return self
+
+    def checkRecursion( self, parseElementList ):
+        if self in parseElementList:
+            raise RecursiveGrammarException( parseElementList+[self] )
+        subRecCheckList = parseElementList[:] + [ self ]
+        if self.expr is not None:
+            self.expr.checkRecursion( subRecCheckList )
+
+    def validate( self, validateTrace=[] ):
+        tmp = validateTrace[:]+[self]
+        if self.expr is not None:
+            self.expr.validate(tmp)
+        self.checkRecursion( [] )
+
+    def __str__( self ):
+        try:
+            return super(ParseElementEnhance,self).__str__()
+        except Exception:
+            pass
+
+        if self.strRepr is None and self.expr is not None:
+            self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) )
+        return self.strRepr
+
+
+class FollowedBy(ParseElementEnhance):
+    """
+    Lookahead matching of the given parse expression.  C{FollowedBy}
+    does I{not} advance the parsing position within the input string, it only
+    verifies that the specified parse expression matches at the current
+    position.  C{FollowedBy} always returns a null token list.
+
+    Example::
+        # use FollowedBy to match a label only if it is followed by a ':'
+        data_word = Word(alphas)
+        label = data_word + FollowedBy(':')
+        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
+        
+        OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint()
+    prints::
+        [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']]
+    """
+    def __init__( self, expr ):
+        super(FollowedBy,self).__init__(expr)
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        self.expr.tryParse( instring, loc )
+        return loc, []
+
+
+class NotAny(ParseElementEnhance):
+    """
+    Lookahead to disallow matching with the given parse expression.  C{NotAny}
+    does I{not} advance the parsing position within the input string, it only
+    verifies that the specified parse expression does I{not} match at the current
+    position.  Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny}
+    always returns a null token list.  May be constructed using the '~' operator.
+
+    Example::
+        
+    """
+    def __init__( self, expr ):
+        super(NotAny,self).__init__(expr)
+        #~ self.leaveWhitespace()
+        self.skipWhitespace = False  # do NOT use self.leaveWhitespace(), don't want to propagate to exprs
+        self.mayReturnEmpty = True
+        self.errmsg = "Found unwanted token, "+_ustr(self.expr)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.expr.canParseNext(instring, loc):
+            raise ParseException(instring, loc, self.errmsg, self)
+        return loc, []
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "~{" + _ustr(self.expr) + "}"
+
+        return self.strRepr
+
+class _MultipleMatch(ParseElementEnhance):
+    def __init__( self, expr, stopOn=None):
+        super(_MultipleMatch, self).__init__(expr)
+        self.saveAsList = True
+        ender = stopOn
+        if isinstance(ender, basestring):
+            ender = ParserElement._literalStringClass(ender)
+        self.not_ender = ~ender if ender is not None else None
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        self_expr_parse = self.expr._parse
+        self_skip_ignorables = self._skipIgnorables
+        check_ender = self.not_ender is not None
+        if check_ender:
+            try_not_ender = self.not_ender.tryParse
+        
+        # must be at least one (but first see if we are the stopOn sentinel;
+        # if so, fail)
+        if check_ender:
+            try_not_ender(instring, loc)
+        loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False )
+        try:
+            hasIgnoreExprs = (not not self.ignoreExprs)
+            while 1:
+                if check_ender:
+                    try_not_ender(instring, loc)
+                if hasIgnoreExprs:
+                    preloc = self_skip_ignorables( instring, loc )
+                else:
+                    preloc = loc
+                loc, tmptokens = self_expr_parse( instring, preloc, doActions )
+                if tmptokens or tmptokens.haskeys():
+                    tokens += tmptokens
+        except (ParseException,IndexError):
+            pass
+
+        return loc, tokens
+        
+class OneOrMore(_MultipleMatch):
+    """
+    Repetition of one or more of the given expression.
+    
+    Parameters:
+     - expr - expression that must match one or more times
+     - stopOn - (default=C{None}) - expression for a terminating sentinel
+          (only required if the sentinel would ordinarily match the repetition 
+          expression)          
+
+    Example::
+        data_word = Word(alphas)
+        label = data_word + FollowedBy(':')
+        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join))
+
+        text = "shape: SQUARE posn: upper left color: BLACK"
+        OneOrMore(attr_expr).parseString(text).pprint()  # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']]
+
+        # use stopOn attribute for OneOrMore to avoid reading label string as part of the data
+        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
+        OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']]
+        
+        # could also be written as
+        (attr_expr * (1,)).parseString(text).pprint()
+    """
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + _ustr(self.expr) + "}..."
+
+        return self.strRepr
+
+class ZeroOrMore(_MultipleMatch):
+    """
+    Optional repetition of zero or more of the given expression.
+    
+    Parameters:
+     - expr - expression that must match zero or more times
+     - stopOn - (default=C{None}) - expression for a terminating sentinel
+          (only required if the sentinel would ordinarily match the repetition 
+          expression)          
+
+    Example: similar to L{OneOrMore}
+    """
+    def __init__( self, expr, stopOn=None):
+        super(ZeroOrMore,self).__init__(expr, stopOn=stopOn)
+        self.mayReturnEmpty = True
+        
+    def parseImpl( self, instring, loc, doActions=True ):
+        try:
+            return super(ZeroOrMore, self).parseImpl(instring, loc, doActions)
+        except (ParseException,IndexError):
+            return loc, []
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "[" + _ustr(self.expr) + "]..."
+
+        return self.strRepr
+
+class _NullToken(object):
+    def __bool__(self):
+        return False
+    __nonzero__ = __bool__
+    def __str__(self):
+        return ""
+
+_optionalNotMatched = _NullToken()
+class Optional(ParseElementEnhance):
+    """
+    Optional matching of the given expression.
+
+    Parameters:
+     - expr - expression that must match zero or more times
+     - default (optional) - value to be returned if the optional expression is not found.
+
+    Example::
+        # US postal code can be a 5-digit zip, plus optional 4-digit qualifier
+        zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4)))
+        zip.runTests('''
+            # traditional ZIP code
+            12345
+            
+            # ZIP+4 form
+            12101-0001
+            
+            # invalid ZIP
+            98765-
+            ''')
+    prints::
+        # traditional ZIP code
+        12345
+        ['12345']
+
+        # ZIP+4 form
+        12101-0001
+        ['12101-0001']
+
+        # invalid ZIP
+        98765-
+             ^
+        FAIL: Expected end of text (at char 5), (line:1, col:6)
+    """
+    def __init__( self, expr, default=_optionalNotMatched ):
+        super(Optional,self).__init__( expr, savelist=False )
+        self.saveAsList = self.expr.saveAsList
+        self.defaultValue = default
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        try:
+            loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
+        except (ParseException,IndexError):
+            if self.defaultValue is not _optionalNotMatched:
+                if self.expr.resultsName:
+                    tokens = ParseResults([ self.defaultValue ])
+                    tokens[self.expr.resultsName] = self.defaultValue
+                else:
+                    tokens = [ self.defaultValue ]
+            else:
+                tokens = []
+        return loc, tokens
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "[" + _ustr(self.expr) + "]"
+
+        return self.strRepr
+
+class SkipTo(ParseElementEnhance):
+    """
+    Token for skipping over all undefined text until the matched expression is found.
+
+    Parameters:
+     - expr - target expression marking the end of the data to be skipped
+     - include - (default=C{False}) if True, the target expression is also parsed 
+          (the skipped text and target expression are returned as a 2-element list).
+     - ignore - (default=C{None}) used to define grammars (typically quoted strings and 
+          comments) that might contain false matches to the target expression
+     - failOn - (default=C{None}) define expressions that are not allowed to be 
+          included in the skipped test; if found before the target expression is found, 
+          the SkipTo is not a match
+
+    Example::
+        report = '''
+            Outstanding Issues Report - 1 Jan 2000
+
+               # | Severity | Description                               |  Days Open
+            -----+----------+-------------------------------------------+-----------
+             101 | Critical | Intermittent system crash                 |          6
+              94 | Cosmetic | Spelling error on Login ('log|n')         |         14
+              79 | Minor    | System slow when running too many reports |         47
+            '''
+        integer = Word(nums)
+        SEP = Suppress('|')
+        # use SkipTo to simply match everything up until the next SEP
+        # - ignore quoted strings, so that a '|' character inside a quoted string does not match
+        # - parse action will call token.strip() for each matched token, i.e., the description body
+        string_data = SkipTo(SEP, ignore=quotedString)
+        string_data.setParseAction(tokenMap(str.strip))
+        ticket_expr = (integer("issue_num") + SEP 
+                      + string_data("sev") + SEP 
+                      + string_data("desc") + SEP 
+                      + integer("days_open"))
+        
+        for tkt in ticket_expr.searchString(report):
+            print tkt.dump()
+    prints::
+        ['101', 'Critical', 'Intermittent system crash', '6']
+        - days_open: 6
+        - desc: Intermittent system crash
+        - issue_num: 101
+        - sev: Critical
+        ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14']
+        - days_open: 14
+        - desc: Spelling error on Login ('log|n')
+        - issue_num: 94
+        - sev: Cosmetic
+        ['79', 'Minor', 'System slow when running too many reports', '47']
+        - days_open: 47
+        - desc: System slow when running too many reports
+        - issue_num: 79
+        - sev: Minor
+    """
+    def __init__( self, other, include=False, ignore=None, failOn=None ):
+        super( SkipTo, self ).__init__( other )
+        self.ignoreExpr = ignore
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+        self.includeMatch = include
+        self.asList = False
+        if isinstance(failOn, basestring):
+            self.failOn = ParserElement._literalStringClass(failOn)
+        else:
+            self.failOn = failOn
+        self.errmsg = "No match found for "+_ustr(self.expr)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        startloc = loc
+        instrlen = len(instring)
+        expr = self.expr
+        expr_parse = self.expr._parse
+        self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None
+        self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None
+        
+        tmploc = loc
+        while tmploc <= instrlen:
+            if self_failOn_canParseNext is not None:
+                # break if failOn expression matches
+                if self_failOn_canParseNext(instring, tmploc):
+                    break
+                    
+            if self_ignoreExpr_tryParse is not None:
+                # advance past ignore expressions
+                while 1:
+                    try:
+                        tmploc = self_ignoreExpr_tryParse(instring, tmploc)
+                    except ParseBaseException:
+                        break
+            
+            try:
+                expr_parse(instring, tmploc, doActions=False, callPreParse=False)
+            except (ParseException, IndexError):
+                # no match, advance loc in string
+                tmploc += 1
+            else:
+                # matched skipto expr, done
+                break
+
+        else:
+            # ran off the end of the input string without matching skipto expr, fail
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        # build up return values
+        loc = tmploc
+        skiptext = instring[startloc:loc]
+        skipresult = ParseResults(skiptext)
+        
+        if self.includeMatch:
+            loc, mat = expr_parse(instring,loc,doActions,callPreParse=False)
+            skipresult += mat
+
+        return loc, skipresult
+
+class Forward(ParseElementEnhance):
+    """
+    Forward declaration of an expression to be defined later -
+    used for recursive grammars, such as algebraic infix notation.
+    When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator.
+
+    Note: take care when assigning to C{Forward} not to overlook precedence of operators.
+    Specifically, '|' has a lower precedence than '<<', so that::
+        fwdExpr << a | b | c
+    will actually be evaluated as::
+        (fwdExpr << a) | b | c
+    thereby leaving b and c out as parseable alternatives.  It is recommended that you
+    explicitly group the values inserted into the C{Forward}::
+        fwdExpr << (a | b | c)
+    Converting to use the '<<=' operator instead will avoid this problem.
+
+    See L{ParseResults.pprint} for an example of a recursive parser created using
+    C{Forward}.
+    """
+    def __init__( self, other=None ):
+        super(Forward,self).__init__( other, savelist=False )
+
+    def __lshift__( self, other ):
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass(other)
+        self.expr = other
+        self.strRepr = None
+        self.mayIndexError = self.expr.mayIndexError
+        self.mayReturnEmpty = self.expr.mayReturnEmpty
+        self.setWhitespaceChars( self.expr.whiteChars )
+        self.skipWhitespace = self.expr.skipWhitespace
+        self.saveAsList = self.expr.saveAsList
+        self.ignoreExprs.extend(self.expr.ignoreExprs)
+        return self
+        
+    def __ilshift__(self, other):
+        return self << other
+    
+    def leaveWhitespace( self ):
+        self.skipWhitespace = False
+        return self
+
+    def streamline( self ):
+        if not self.streamlined:
+            self.streamlined = True
+            if self.expr is not None:
+                self.expr.streamline()
+        return self
+
+    def validate( self, validateTrace=[] ):
+        if self not in validateTrace:
+            tmp = validateTrace[:]+[self]
+            if self.expr is not None:
+                self.expr.validate(tmp)
+        self.checkRecursion([])
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+        return self.__class__.__name__ + ": ..."
+
+        # stubbed out for now - creates awful memory and perf issues
+        self._revertClass = self.__class__
+        self.__class__ = _ForwardNoRecurse
+        try:
+            if self.expr is not None:
+                retString = _ustr(self.expr)
+            else:
+                retString = "None"
+        finally:
+            self.__class__ = self._revertClass
+        return self.__class__.__name__ + ": " + retString
+
+    def copy(self):
+        if self.expr is not None:
+            return super(Forward,self).copy()
+        else:
+            ret = Forward()
+            ret <<= self
+            return ret
+
+class _ForwardNoRecurse(Forward):
+    def __str__( self ):
+        return "..."
+
+class TokenConverter(ParseElementEnhance):
+    """
+    Abstract subclass of C{ParseExpression}, for converting parsed results.
+    """
+    def __init__( self, expr, savelist=False ):
+        super(TokenConverter,self).__init__( expr )#, savelist )
+        self.saveAsList = False
+
+class Combine(TokenConverter):
+    """
+    Converter to concatenate all matching tokens to a single string.
+    By default, the matching patterns must also be contiguous in the input string;
+    this can be disabled by specifying C{'adjacent=False'} in the constructor.
+
+    Example::
+        real = Word(nums) + '.' + Word(nums)
+        print(real.parseString('3.1416')) # -> ['3', '.', '1416']
+        # will also erroneously match the following
+        print(real.parseString('3. 1416')) # -> ['3', '.', '1416']
+
+        real = Combine(Word(nums) + '.' + Word(nums))
+        print(real.parseString('3.1416')) # -> ['3.1416']
+        # no match when there are internal spaces
+        print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...)
+    """
+    def __init__( self, expr, joinString="", adjacent=True ):
+        super(Combine,self).__init__( expr )
+        # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself
+        if adjacent:
+            self.leaveWhitespace()
+        self.adjacent = adjacent
+        self.skipWhitespace = True
+        self.joinString = joinString
+        self.callPreparse = True
+
+    def ignore( self, other ):
+        if self.adjacent:
+            ParserElement.ignore(self, other)
+        else:
+            super( Combine, self).ignore( other )
+        return self
+
+    def postParse( self, instring, loc, tokenlist ):
+        retToks = tokenlist.copy()
+        del retToks[:]
+        retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults)
+
+        if self.resultsName and retToks.haskeys():
+            return [ retToks ]
+        else:
+            return retToks
+
+class Group(TokenConverter):
+    """
+    Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions.
+
+    Example::
+        ident = Word(alphas)
+        num = Word(nums)
+        term = ident | num
+        func = ident + Optional(delimitedList(term))
+        print(func.parseString("fn a,b,100"))  # -> ['fn', 'a', 'b', '100']
+
+        func = ident + Group(Optional(delimitedList(term)))
+        print(func.parseString("fn a,b,100"))  # -> ['fn', ['a', 'b', '100']]
+    """
+    def __init__( self, expr ):
+        super(Group,self).__init__( expr )
+        self.saveAsList = True
+
+    def postParse( self, instring, loc, tokenlist ):
+        return [ tokenlist ]
+
+class Dict(TokenConverter):
+    """
+    Converter to return a repetitive expression as a list, but also as a dictionary.
+    Each element can also be referenced using the first token in the expression as its key.
+    Useful for tabular report scraping when the first column can be used as a item key.
+
+    Example::
+        data_word = Word(alphas)
+        label = data_word + FollowedBy(':')
+        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join))
+
+        text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
+        attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
+        
+        # print attributes as plain groups
+        print(OneOrMore(attr_expr).parseString(text).dump())
+        
+        # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names
+        result = Dict(OneOrMore(Group(attr_expr))).parseString(text)
+        print(result.dump())
+        
+        # access named fields as dict entries, or output as dict
+        print(result['shape'])        
+        print(result.asDict())
+    prints::
+        ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap']
+
+        [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
+        - color: light blue
+        - posn: upper left
+        - shape: SQUARE
+        - texture: burlap
+        SQUARE
+        {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'}
+    See more examples at L{ParseResults} of accessing fields by results name.
+    """
+    def __init__( self, expr ):
+        super(Dict,self).__init__( expr )
+        self.saveAsList = True
+
+    def postParse( self, instring, loc, tokenlist ):
+        for i,tok in enumerate(tokenlist):
+            if len(tok) == 0:
+                continue
+            ikey = tok[0]
+            if isinstance(ikey,int):
+                ikey = _ustr(tok[0]).strip()
+            if len(tok)==1:
+                tokenlist[ikey] = _ParseResultsWithOffset("",i)
+            elif len(tok)==2 and not isinstance(tok[1],ParseResults):
+                tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i)
+            else:
+                dictvalue = tok.copy() #ParseResults(i)
+                del dictvalue[0]
+                if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()):
+                    tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i)
+                else:
+                    tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i)
+
+        if self.resultsName:
+            return [ tokenlist ]
+        else:
+            return tokenlist
+
+
+class Suppress(TokenConverter):
+    """
+    Converter for ignoring the results of a parsed expression.
+
+    Example::
+        source = "a, b, c,d"
+        wd = Word(alphas)
+        wd_list1 = wd + ZeroOrMore(',' + wd)
+        print(wd_list1.parseString(source))
+
+        # often, delimiters that are useful during parsing are just in the
+        # way afterward - use Suppress to keep them out of the parsed output
+        wd_list2 = wd + ZeroOrMore(Suppress(',') + wd)
+        print(wd_list2.parseString(source))
+    prints::
+        ['a', ',', 'b', ',', 'c', ',', 'd']
+        ['a', 'b', 'c', 'd']
+    (See also L{delimitedList}.)
+    """
+    def postParse( self, instring, loc, tokenlist ):
+        return []
+
+    def suppress( self ):
+        return self
+
+
+class OnlyOnce(object):
+    """
+    Wrapper for parse actions, to ensure they are only called once.
+    """
+    def __init__(self, methodCall):
+        self.callable = _trim_arity(methodCall)
+        self.called = False
+    def __call__(self,s,l,t):
+        if not self.called:
+            results = self.callable(s,l,t)
+            self.called = True
+            return results
+        raise ParseException(s,l,"")
+    def reset(self):
+        self.called = False
+
+def traceParseAction(f):
+    """
+    Decorator for debugging parse actions. 
+    
+    When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".}
+    When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised.
+
+    Example::
+        wd = Word(alphas)
+
+        @traceParseAction
+        def remove_duplicate_chars(tokens):
+            return ''.join(sorted(set(''.join(tokens))))
+
+        wds = OneOrMore(wd).setParseAction(remove_duplicate_chars)
+        print(wds.parseString("slkdjs sld sldd sdlf sdljf"))
+    prints::
+        >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {}))
+        <3:
+            thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc
+        sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) )
+        try:
+            ret = f(*paArgs)
+        except Exception as exc:
+            sys.stderr.write( "< ['aa', 'bb', 'cc']
+        delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE']
+    """
+    dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..."
+    if combine:
+        return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName)
+    else:
+        return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName)
+
+def countedArray( expr, intExpr=None ):
+    """
+    Helper to define a counted list of expressions.
+    This helper defines a pattern of the form::
+        integer expr expr expr...
+    where the leading integer tells how many expr expressions follow.
+    The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed.
+    
+    If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value.
+
+    Example::
+        countedArray(Word(alphas)).parseString('2 ab cd ef')  # -> ['ab', 'cd']
+
+        # in this parser, the leading integer value is given in binary,
+        # '10' indicating that 2 values are in the array
+        binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2))
+        countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef')  # -> ['ab', 'cd']
+    """
+    arrayExpr = Forward()
+    def countFieldParseAction(s,l,t):
+        n = t[0]
+        arrayExpr << (n and Group(And([expr]*n)) or Group(empty))
+        return []
+    if intExpr is None:
+        intExpr = Word(nums).setParseAction(lambda t:int(t[0]))
+    else:
+        intExpr = intExpr.copy()
+    intExpr.setName("arrayLen")
+    intExpr.addParseAction(countFieldParseAction, callDuringTry=True)
+    return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...')
+
+def _flatten(L):
+    ret = []
+    for i in L:
+        if isinstance(i,list):
+            ret.extend(_flatten(i))
+        else:
+            ret.append(i)
+    return ret
+
+def matchPreviousLiteral(expr):
+    """
+    Helper to define an expression that is indirectly defined from
+    the tokens matched in a previous expression, that is, it looks
+    for a 'repeat' of a previous expression.  For example::
+        first = Word(nums)
+        second = matchPreviousLiteral(first)
+        matchExpr = first + ":" + second
+    will match C{"1:1"}, but not C{"1:2"}.  Because this matches a
+    previous literal, will also match the leading C{"1:1"} in C{"1:10"}.
+    If this is not desired, use C{matchPreviousExpr}.
+    Do I{not} use with packrat parsing enabled.
+    """
+    rep = Forward()
+    def copyTokenToRepeater(s,l,t):
+        if t:
+            if len(t) == 1:
+                rep << t[0]
+            else:
+                # flatten t tokens
+                tflat = _flatten(t.asList())
+                rep << And(Literal(tt) for tt in tflat)
+        else:
+            rep << Empty()
+    expr.addParseAction(copyTokenToRepeater, callDuringTry=True)
+    rep.setName('(prev) ' + _ustr(expr))
+    return rep
+
+def matchPreviousExpr(expr):
+    """
+    Helper to define an expression that is indirectly defined from
+    the tokens matched in a previous expression, that is, it looks
+    for a 'repeat' of a previous expression.  For example::
+        first = Word(nums)
+        second = matchPreviousExpr(first)
+        matchExpr = first + ":" + second
+    will match C{"1:1"}, but not C{"1:2"}.  Because this matches by
+    expressions, will I{not} match the leading C{"1:1"} in C{"1:10"};
+    the expressions are evaluated first, and then compared, so
+    C{"1"} is compared with C{"10"}.
+    Do I{not} use with packrat parsing enabled.
+    """
+    rep = Forward()
+    e2 = expr.copy()
+    rep <<= e2
+    def copyTokenToRepeater(s,l,t):
+        matchTokens = _flatten(t.asList())
+        def mustMatchTheseTokens(s,l,t):
+            theseTokens = _flatten(t.asList())
+            if  theseTokens != matchTokens:
+                raise ParseException("",0,"")
+        rep.setParseAction( mustMatchTheseTokens, callDuringTry=True )
+    expr.addParseAction(copyTokenToRepeater, callDuringTry=True)
+    rep.setName('(prev) ' + _ustr(expr))
+    return rep
+
+def _escapeRegexRangeChars(s):
+    #~  escape these chars: ^-]
+    for c in r"\^-]":
+        s = s.replace(c,_bslash+c)
+    s = s.replace("\n",r"\n")
+    s = s.replace("\t",r"\t")
+    return _ustr(s)
+
+def oneOf( strs, caseless=False, useRegex=True ):
+    """
+    Helper to quickly define a set of alternative Literals, and makes sure to do
+    longest-first testing when there is a conflict, regardless of the input order,
+    but returns a C{L{MatchFirst}} for best performance.
+
+    Parameters:
+     - strs - a string of space-delimited literals, or a collection of string literals
+     - caseless - (default=C{False}) - treat all literals as caseless
+     - useRegex - (default=C{True}) - as an optimization, will generate a Regex
+          object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or
+          if creating a C{Regex} raises an exception)
+
+    Example::
+        comp_oper = oneOf("< = > <= >= !=")
+        var = Word(alphas)
+        number = Word(nums)
+        term = var | number
+        comparison_expr = term + comp_oper + term
+        print(comparison_expr.searchString("B = 12  AA=23 B<=AA AA>12"))
+    prints::
+        [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']]
+    """
+    if caseless:
+        isequal = ( lambda a,b: a.upper() == b.upper() )
+        masks = ( lambda a,b: b.upper().startswith(a.upper()) )
+        parseElementClass = CaselessLiteral
+    else:
+        isequal = ( lambda a,b: a == b )
+        masks = ( lambda a,b: b.startswith(a) )
+        parseElementClass = Literal
+
+    symbols = []
+    if isinstance(strs,basestring):
+        symbols = strs.split()
+    elif isinstance(strs, Iterable):
+        symbols = list(strs)
+    else:
+        warnings.warn("Invalid argument to oneOf, expected string or iterable",
+                SyntaxWarning, stacklevel=2)
+    if not symbols:
+        return NoMatch()
+
+    i = 0
+    while i < len(symbols)-1:
+        cur = symbols[i]
+        for j,other in enumerate(symbols[i+1:]):
+            if ( isequal(other, cur) ):
+                del symbols[i+j+1]
+                break
+            elif ( masks(cur, other) ):
+                del symbols[i+j+1]
+                symbols.insert(i,other)
+                cur = other
+                break
+        else:
+            i += 1
+
+    if not caseless and useRegex:
+        #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] ))
+        try:
+            if len(symbols)==len("".join(symbols)):
+                return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols))
+            else:
+                return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols))
+        except Exception:
+            warnings.warn("Exception creating Regex for oneOf, building MatchFirst",
+                    SyntaxWarning, stacklevel=2)
+
+
+    # last resort, just use MatchFirst
+    return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols))
+
+def dictOf( key, value ):
+    """
+    Helper to easily and clearly define a dictionary by specifying the respective patterns
+    for the key and value.  Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens
+    in the proper order.  The key pattern can include delimiting markers or punctuation,
+    as long as they are suppressed, thereby leaving the significant key text.  The value
+    pattern can include named results, so that the C{Dict} results can include named token
+    fields.
+
+    Example::
+        text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
+        attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
+        print(OneOrMore(attr_expr).parseString(text).dump())
+        
+        attr_label = label
+        attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)
+
+        # similar to Dict, but simpler call format
+        result = dictOf(attr_label, attr_value).parseString(text)
+        print(result.dump())
+        print(result['shape'])
+        print(result.shape)  # object attribute access works too
+        print(result.asDict())
+    prints::
+        [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
+        - color: light blue
+        - posn: upper left
+        - shape: SQUARE
+        - texture: burlap
+        SQUARE
+        SQUARE
+        {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'}
+    """
+    return Dict( ZeroOrMore( Group ( key + value ) ) )
+
+def originalTextFor(expr, asString=True):
+    """
+    Helper to return the original, untokenized text for a given expression.  Useful to
+    restore the parsed fields of an HTML start tag into the raw tag text itself, or to
+    revert separate tokens with intervening whitespace back to the original matching
+    input text. By default, returns astring containing the original parsed text.  
+       
+    If the optional C{asString} argument is passed as C{False}, then the return value is a 
+    C{L{ParseResults}} containing any results names that were originally matched, and a 
+    single token containing the original matched text from the input string.  So if 
+    the expression passed to C{L{originalTextFor}} contains expressions with defined
+    results names, you must set C{asString} to C{False} if you want to preserve those
+    results name values.
+
+    Example::
+        src = "this is test  bold text  normal text "
+        for tag in ("b","i"):
+            opener,closer = makeHTMLTags(tag)
+            patt = originalTextFor(opener + SkipTo(closer) + closer)
+            print(patt.searchString(src)[0])
+    prints::
+        [' bold text ']
+        ['text']
+    """
+    locMarker = Empty().setParseAction(lambda s,loc,t: loc)
+    endlocMarker = locMarker.copy()
+    endlocMarker.callPreparse = False
+    matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end")
+    if asString:
+        extractText = lambda s,l,t: s[t._original_start:t._original_end]
+    else:
+        def extractText(s,l,t):
+            t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]]
+    matchExpr.setParseAction(extractText)
+    matchExpr.ignoreExprs = expr.ignoreExprs
+    return matchExpr
+
+def ungroup(expr): 
+    """
+    Helper to undo pyparsing's default grouping of And expressions, even
+    if all but one are non-empty.
+    """
+    return TokenConverter(expr).setParseAction(lambda t:t[0])
+
+def locatedExpr(expr):
+    """
+    Helper to decorate a returned token with its starting and ending locations in the input string.
+    This helper adds the following results names:
+     - locn_start = location where matched expression begins
+     - locn_end = location where matched expression ends
+     - value = the actual parsed results
+
+    Be careful if the input text contains C{} characters, you may want to call
+    C{L{ParserElement.parseWithTabs}}
+
+    Example::
+        wd = Word(alphas)
+        for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"):
+            print(match)
+    prints::
+        [[0, 'ljsdf', 5]]
+        [[8, 'lksdjjf', 15]]
+        [[18, 'lkkjj', 23]]
+    """
+    locator = Empty().setParseAction(lambda s,l,t: l)
+    return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end"))
+
+
+# convenience constants for positional expressions
+empty       = Empty().setName("empty")
+lineStart   = LineStart().setName("lineStart")
+lineEnd     = LineEnd().setName("lineEnd")
+stringStart = StringStart().setName("stringStart")
+stringEnd   = StringEnd().setName("stringEnd")
+
+_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1])
+_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16)))
+_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8)))
+_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1)
+_charRange = Group(_singleChar + Suppress("-") + _singleChar)
+_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]"
+
+def srange(s):
+    r"""
+    Helper to easily define string ranges for use in Word construction.  Borrows
+    syntax from regexp '[]' string range definitions::
+        srange("[0-9]")   -> "0123456789"
+        srange("[a-z]")   -> "abcdefghijklmnopqrstuvwxyz"
+        srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_"
+    The input string must be enclosed in []'s, and the returned string is the expanded
+    character set joined into a single string.
+    The values enclosed in the []'s may be:
+     - a single character
+     - an escaped character with a leading backslash (such as C{\-} or C{\]})
+     - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) 
+         (C{\0x##} is also supported for backwards compatibility) 
+     - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character)
+     - a range of any of the above, separated by a dash (C{'a-z'}, etc.)
+     - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.)
+    """
+    _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1))
+    try:
+        return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body)
+    except Exception:
+        return ""
+
+def matchOnlyAtCol(n):
+    """
+    Helper method for defining parse actions that require matching at a specific
+    column in the input text.
+    """
+    def verifyCol(strg,locn,toks):
+        if col(locn,strg) != n:
+            raise ParseException(strg,locn,"matched token not at column %d" % n)
+    return verifyCol
+
+def replaceWith(replStr):
+    """
+    Helper method for common parse actions that simply return a literal value.  Especially
+    useful when used with C{L{transformString}()}.
+
+    Example::
+        num = Word(nums).setParseAction(lambda toks: int(toks[0]))
+        na = oneOf("N/A NA").setParseAction(replaceWith(math.nan))
+        term = na | num
+        
+        OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234]
+    """
+    return lambda s,l,t: [replStr]
+
+def removeQuotes(s,l,t):
+    """
+    Helper parse action for removing quotation marks from parsed quoted strings.
+
+    Example::
+        # by default, quotation marks are included in parsed results
+        quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"]
+
+        # use removeQuotes to strip quotation marks from parsed results
+        quotedString.setParseAction(removeQuotes)
+        quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"]
+    """
+    return t[0][1:-1]
+
+def tokenMap(func, *args):
+    """
+    Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional 
+    args are passed, they are forwarded to the given function as additional arguments after
+    the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the
+    parsed data to an integer using base 16.
+
+    Example (compare the last to example in L{ParserElement.transformString}::
+        hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16))
+        hex_ints.runTests('''
+            00 11 22 aa FF 0a 0d 1a
+            ''')
+        
+        upperword = Word(alphas).setParseAction(tokenMap(str.upper))
+        OneOrMore(upperword).runTests('''
+            my kingdom for a horse
+            ''')
+
+        wd = Word(alphas).setParseAction(tokenMap(str.title))
+        OneOrMore(wd).setParseAction(' '.join).runTests('''
+            now is the winter of our discontent made glorious summer by this sun of york
+            ''')
+    prints::
+        00 11 22 aa FF 0a 0d 1a
+        [0, 17, 34, 170, 255, 10, 13, 26]
+
+        my kingdom for a horse
+        ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE']
+
+        now is the winter of our discontent made glorious summer by this sun of york
+        ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York']
+    """
+    def pa(s,l,t):
+        return [func(tokn, *args) for tokn in t]
+
+    try:
+        func_name = getattr(func, '__name__', 
+                            getattr(func, '__class__').__name__)
+    except Exception:
+        func_name = str(func)
+    pa.__name__ = func_name
+
+    return pa
+
+upcaseTokens = tokenMap(lambda t: _ustr(t).upper())
+"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}"""
+
+downcaseTokens = tokenMap(lambda t: _ustr(t).lower())
+"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}"""
+    
+def _makeTags(tagStr, xml):
+    """Internal helper to construct opening and closing tag expressions, given a tag name"""
+    if isinstance(tagStr,basestring):
+        resname = tagStr
+        tagStr = Keyword(tagStr, caseless=not xml)
+    else:
+        resname = tagStr.name
+
+    tagAttrName = Word(alphas,alphanums+"_-:")
+    if (xml):
+        tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes )
+        openTag = Suppress("<") + tagStr("tag") + \
+                Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \
+                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
+    else:
+        printablesLessRAbrack = "".join(c for c in printables if c not in ">")
+        tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack)
+        openTag = Suppress("<") + tagStr("tag") + \
+                Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \
+                Optional( Suppress("=") + tagAttrValue ) ))) + \
+                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
+    closeTag = Combine(_L("")
+
+    openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname)
+    closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("" % resname)
+    openTag.tag = resname
+    closeTag.tag = resname
+    return openTag, closeTag
+
+def makeHTMLTags(tagStr):
+    """
+    Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches
+    tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values.
+
+    Example::
+        text = 'More info at the pyparsing wiki page'
+        # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple
+        a,a_end = makeHTMLTags("A")
+        link_expr = a + SkipTo(a_end)("link_text") + a_end
+        
+        for link in link_expr.searchString(text):
+            # attributes in the  tag (like "href" shown here) are also accessible as named results
+            print(link.link_text, '->', link.href)
+    prints::
+        pyparsing -> http://pyparsing.wikispaces.com
+    """
+    return _makeTags( tagStr, False )
+
+def makeXMLTags(tagStr):
+    """
+    Helper to construct opening and closing tag expressions for XML, given a tag name. Matches
+    tags only in the given upper/lower case.
+
+    Example: similar to L{makeHTMLTags}
+    """
+    return _makeTags( tagStr, True )
+
+def withAttribute(*args,**attrDict):
+    """
+    Helper to create a validating parse action to be used with start tags created
+    with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag
+    with a required attribute value, to avoid false matches on common tags such as
+    C{} or C{
}. + + Call C{withAttribute} with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in C{(align="right")}, or + - as an explicit dict with C{**} operator, when an attribute name is also a Python + reserved word, as in C{**{"class":"Customer", "align":"right"}} + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + If just testing for C{class} (with or without a namespace), use C{L{withClass}}. + + To verify that the attribute exists, but without specifying a value, pass + C{withAttribute.ANY_VALUE} as the value. + + Example:: + html = ''' +
+ Some text +
1 4 0 1 0
+
1,3 2,3 1,1
+
this has no type
+
+ + ''' + div,div_end = makeHTMLTags("div") + + # only match div tag having a type attribute with value "grid" + div_grid = div().setParseAction(withAttribute(type="grid")) + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + # construct a match with any div tag having a type attribute, regardless of the value + div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +def withClass(classname, namespace=''): + """ + Simplified version of C{L{withAttribute}} when matching on a div class - made + difficult because C{class} is a reserved word in Python. + + Example:: + html = ''' +
+ Some text +
1 4 0 1 0
+
1,3 2,3 1,1
+
this <div> has no class
+
+ + ''' + div,div_end = makeHTMLTags("div") + div_grid = div().setParseAction(withClass("grid")) + + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + classattr = "%s:class" % namespace if namespace else "class" + return withAttribute(**{classattr : classname}) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): + """ + Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. The generated parser will also recognize the use + of parentheses to override operator precedences (see example below). + + Note: if you define a deep operator list, you may see performance issues + when using infixNotation. See L{ParserElement.enablePackrat} for a + mechanism to potentially improve your parser performance. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted); if the parse action + is passed a tuple or list of functions, this is equivalent to + calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) + - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) + - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) + + Example:: + # simple example of four-function arithmetic with ints and variable names + integer = pyparsing_common.signed_integer + varname = pyparsing_common.identifier + + arith_expr = infixNotation(integer | varname, + [ + ('-', 1, opAssoc.RIGHT), + (oneOf('* /'), 2, opAssoc.LEFT), + (oneOf('+ -'), 2, opAssoc.LEFT), + ]) + + arith_expr.runTests(''' + 5+3*6 + (5+3)*6 + -2--11 + ''', fullDump=False) + prints:: + 5+3*6 + [[5, '+', [3, '*', 6]]] + + (5+3)*6 + [[[5, '+', 3], '*', 6]] + + -2--11 + [[['-', 2], '-', ['-', 11]]] + """ + ret = Forward() + lastExpr = baseExpr | ( lpar + ret + rpar ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward().setName(termName) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + if isinstance(pa, (tuple, list)): + matchExpr.setParseAction(*pa) + else: + matchExpr.setParseAction(pa) + thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) + lastExpr = thisExpr + ret <<= lastExpr + return ret + +operatorPrecedence = infixNotation +"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" + +dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") +sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") +quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| + Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): + """ + Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression + - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression + - content - expression for items within the nested lists (default=C{None}) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the C{ignoreExpr} argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. + The default is L{quotedString}, but if no expressions are to be ignored, + then pass C{None} for this argument. + + Example:: + data_type = oneOf("void int short long char float double") + decl_data_type = Combine(data_type + Optional(Word('*'))) + ident = Word(alphas+'_', alphanums+'_') + number = pyparsing_common.number + arg = Group(decl_data_type + ident) + LPAR,RPAR = map(Suppress, "()") + + code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) + + c_function = (decl_data_type("type") + + ident("name") + + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + + code_body("body")) + c_function.ignore(cStyleComment) + + source_code = ''' + int is_odd(int x) { + return (x%2); + } + + int dec_to_hex(char hchar) { + if (hchar >= '0' && hchar <= '9') { + return (ord(hchar)-ord('0')); + } else { + return (10+ord(hchar)-ord('A')); + } + } + ''' + for func in c_function.searchString(source_code): + print("%(name)s (%(type)s) args: %(args)s" % func) + + prints:: + is_odd (int) args: [['int', 'x']] + dec_to_hex (int) args: [['char', 'hchar']] + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + ret.setName('nested %s%s expression' % (opener,closer)) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """ + Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=C{True}) + + A valid block must contain at least one C{blockStatement}. + + Example:: + data = ''' + def A(z): + A1 + B = 100 + G = A2 + A2 + A3 + B + def BB(a,b,c): + BB1 + def BBA(): + bba1 + bba2 + bba3 + C + D + def spam(x,y): + def eggs(z): + pass + ''' + + + indentStack = [1] + stmt = Forward() + + identifier = Word(alphas, alphanums) + funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") + func_body = indentedBlock(stmt, indentStack) + funcDef = Group( funcDecl + func_body ) + + rvalue = Forward() + funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") + rvalue << (funcCall | identifier | Word(nums)) + assignment = Group(identifier + "=" + rvalue) + stmt << ( funcDef | assignment | identifier ) + + module_body = OneOrMore(stmt) + + parseTree = module_body.parseString(data) + parseTree.pprint() + prints:: + [['def', + 'A', + ['(', 'z', ')'], + ':', + [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], + 'B', + ['def', + 'BB', + ['(', 'a', 'b', 'c', ')'], + ':', + [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], + 'C', + 'D', + ['def', + 'spam', + ['(', 'x', 'y', ')'], + ':', + [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') + PEER = Empty().setParseAction(checkPeerIndent).setName('') + UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') + if indent: + smExpr = Group( Optional(NL) + + #~ FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr.setName('indented block') + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) +_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) +commonHTMLEntity = Regex('&(?P' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") +def replaceHTMLEntity(t): + """Helper parser action to replace common HTML entities with their special characters""" + return _htmlEntityMap.get(t.entity) + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") +"Comment of the form C{/* ... */}" + +htmlComment = Regex(r"").setName("HTML comment") +"Comment of the form C{}" + +restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") +dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") +"Comment of the form C{// ... (to end of line)}" + +cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") +"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" + +javaStyleComment = cppStyleComment +"Same as C{L{cppStyleComment}}" + +pythonStyleComment = Regex(r"#.*").setName("Python style comment") +"Comment of the form C{# ... (to end of line)}" + +_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + + Optional( Word(" \t") + + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") +commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") +"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. + This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" + +# some other useful expressions - using lower-case class name since we are really using this as a namespace +class pyparsing_common: + """ + Here are some common low-level expressions that may be useful in jump-starting parser development: + - numeric forms (L{integers}, L{reals}, L{scientific notation}) + - common L{programming identifiers} + - network addresses (L{MAC}, L{IPv4}, L{IPv6}) + - ISO8601 L{dates} and L{datetime} + - L{UUID} + - L{comma-separated list} + Parse actions: + - C{L{convertToInteger}} + - C{L{convertToFloat}} + - C{L{convertToDate}} + - C{L{convertToDatetime}} + - C{L{stripHTMLTags}} + - C{L{upcaseTokens}} + - C{L{downcaseTokens}} + + Example:: + pyparsing_common.number.runTests(''' + # any int or real number, returned as the appropriate type + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.fnumber.runTests(''' + # any int or real number, returned as float + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.hex_integer.runTests(''' + # hex numbers + 100 + FF + ''') + + pyparsing_common.fraction.runTests(''' + # fractions + 1/2 + -3/4 + ''') + + pyparsing_common.mixed_integer.runTests(''' + # mixed fractions + 1 + 1/2 + -3/4 + 1-3/4 + ''') + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(''' + # uuid + 12345678-1234-5678-1234-567812345678 + ''') + prints:: + # any int or real number, returned as the appropriate type + 100 + [100] + + -100 + [-100] + + +100 + [100] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # any int or real number, returned as float + 100 + [100.0] + + -100 + [-100.0] + + +100 + [100.0] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # hex numbers + 100 + [256] + + FF + [255] + + # fractions + 1/2 + [0.5] + + -3/4 + [-0.75] + + # mixed fractions + 1 + [1] + + 1/2 + [0.5] + + -3/4 + [-0.75] + + 1-3/4 + [1.75] + + # uuid + 12345678-1234-5678-1234-567812345678 + [UUID('12345678-1234-5678-1234-567812345678')] + """ + + convertToInteger = tokenMap(int) + """ + Parse action for converting parsed integers to Python int + """ + + convertToFloat = tokenMap(float) + """ + Parse action for converting parsed numbers to Python float + """ + + integer = Word(nums).setName("integer").setParseAction(convertToInteger) + """expression that parses an unsigned integer, returns an int""" + + hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) + """expression that parses a hexadecimal integer, returns an int""" + + signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) + """expression that parses an integer with optional leading sign, returns an int""" + + fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") + """fractional expression of an integer divided by an integer, returns a float""" + fraction.addParseAction(lambda t: t[0]/t[-1]) + + mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") + """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" + mixed_integer.addParseAction(sum) + + real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) + """expression that parses a floating point number and returns a float""" + + sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) + """expression that parses a floating point number with optional scientific notation and returns a float""" + + # streamlining this expression makes the docs nicer-looking + number = (sci_real | real | signed_integer).streamline() + """any numeric expression, returns the corresponding Python type""" + + fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) + """any int or real number, returned as float""" + + identifier = Word(alphas+'_', alphanums+'_').setName("identifier") + """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" + + ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") + "IPv4 address (C{0.0.0.0 - 255.255.255.255})" + + _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") + _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") + _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") + _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) + _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") + ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") + "IPv6 address (long, short, or mixed form)" + + mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") + "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" + + @staticmethod + def convertToDate(fmt="%Y-%m-%d"): + """ + Helper to create a parse action for converting parsed date string to Python datetime.date + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) + + Example:: + date_expr = pyparsing_common.iso8601_date.copy() + date_expr.setParseAction(pyparsing_common.convertToDate()) + print(date_expr.parseString("1999-12-31")) + prints:: + [datetime.date(1999, 12, 31)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt).date() + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + @staticmethod + def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): + """ + Helper to create a parse action for converting parsed datetime string to Python datetime.datetime + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) + + Example:: + dt_expr = pyparsing_common.iso8601_datetime.copy() + dt_expr.setParseAction(pyparsing_common.convertToDatetime()) + print(dt_expr.parseString("1999-12-31T23:59:59.999")) + prints:: + [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt) + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + iso8601_date = Regex(r'(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?').setName("ISO8601 date") + "ISO8601 date (C{yyyy-mm-dd})" + + iso8601_datetime = Regex(r'(?P\d{4})-(?P\d\d)-(?P\d\d)[T ](?P\d\d):(?P\d\d)(:(?P\d\d(\.\d*)?)?)?(?PZ|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") + "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" + + uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") + "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" + + _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() + @staticmethod + def stripHTMLTags(s, l, tokens): + """ + Parse action to remove HTML tags from web page HTML source + + Example:: + # strip HTML links from normal text + text = 'More info at the
pyparsing wiki page' + td,td_end = makeHTMLTags("TD") + table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end + + print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' + """ + return pyparsing_common._html_stripper.transformString(tokens[0]) + + _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + + Optional( White(" \t") ) ) ).streamline().setName("commaItem") + comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") + """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" + + upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) + """Parse action to convert tokens to upper case.""" + + downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) + """Parse action to convert tokens to lower case.""" + + +if __name__ == "__main__": + + selectToken = CaselessLiteral("select") + fromToken = CaselessLiteral("from") + + ident = Word(alphas, alphanums + "_$") + + columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + columnNameList = Group(delimitedList(columnName)).setName("columns") + columnSpec = ('*' | columnNameList) + + tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + tableNameList = Group(delimitedList(tableName)).setName("tables") + + simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") + + # demo runTests method, including embedded comments in test string + simpleSQL.runTests(""" + # '*' as column list and dotted table name + select * from SYS.XYZZY + + # caseless match on "SELECT", and casts back to "select" + SELECT * from XYZZY, ABC + + # list of column names, and mixed case SELECT keyword + Select AA,BB,CC from Sys.dual + + # multiple tables + Select A, B, C from Sys.dual, Table2 + + # invalid SELECT keyword - should fail + Xelect A, B, C from Sys.dual + + # incomplete command - should fail + Select + + # invalid column name - should fail + Select ^^^ frox Sys.dual + + """) + + pyparsing_common.number.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + # any int or real number, returned as float + pyparsing_common.fnumber.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + pyparsing_common.hex_integer.runTests(""" + 100 + FF + """) + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(""" + 12345678-1234-5678-1234-567812345678 + """) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/six.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/six.py new file mode 100644 index 0000000..190c023 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/_vendor/six.py @@ -0,0 +1,868 @@ +"""Utilities for writing code that runs on Python 2 and 3""" + +# Copyright (c) 2010-2015 Benjamin Peterson +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson " +__version__ = "1.10.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + if from_value is None: + raise value + raise value from from_value +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + raise value from from_value +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/extern/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/extern/__init__.py new file mode 100644 index 0000000..c1eb9e9 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/extern/__init__.py @@ -0,0 +1,73 @@ +import sys + + +class VendorImporter: + """ + A PEP 302 meta path importer for finding optionally-vendored + or otherwise naturally-installed packages from root_name. + """ + + def __init__(self, root_name, vendored_names=(), vendor_pkg=None): + self.root_name = root_name + self.vendored_names = set(vendored_names) + self.vendor_pkg = vendor_pkg or root_name.replace('extern', '_vendor') + + @property + def search_path(self): + """ + Search first the vendor package then as a natural package. + """ + yield self.vendor_pkg + '.' + yield '' + + def find_module(self, fullname, path=None): + """ + Return self when fullname starts with root_name and the + target module is one vendored through this importer. + """ + root, base, target = fullname.partition(self.root_name + '.') + if root: + return + if not any(map(target.startswith, self.vendored_names)): + return + return self + + def load_module(self, fullname): + """ + Iterate over the search path to locate and load fullname. + """ + root, base, target = fullname.partition(self.root_name + '.') + for prefix in self.search_path: + try: + extant = prefix + target + __import__(extant) + mod = sys.modules[extant] + sys.modules[fullname] = mod + # mysterious hack: + # Remove the reference to the extant package/module + # on later Python versions to cause relative imports + # in the vendor package to resolve the same modules + # as those going through this importer. + if prefix and sys.version_info > (3, 3): + del sys.modules[extant] + return mod + except ImportError: + pass + else: + raise ImportError( + "The '{target}' package is required; " + "normally this is bundled with this package so if you get " + "this warning, consult the packager of your " + "distribution.".format(**locals()) + ) + + def install(self): + """ + Install this importer into sys.meta_path if not already present. + """ + if self not in sys.meta_path: + sys.meta_path.append(self) + + +names = 'packaging', 'pyparsing', 'six', 'appdirs' +VendorImporter(__name__, names).install() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/extern/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/extern/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e5912209a3e965a421bb83d6d4bcce0bfec471c GIT binary patch literal 2472 zcmZ`*&5s*36u0LqADi8l9(HLdl?4)2piL^u0YpJXZG|e(s%lXYQPF5Nb~dw}jHkA< z+l0vhvf{`I?p=vX{|){OUpe*82?@b_o+P{76^`bO$9}fo$M5}|WPQC!pbck#C4V#s z`4c}*HXlB2!=tZ(;DpnR^vIWld)z-H+@E_r%7dOKsPKh1_g(}?go4&1(hgt23bNft zd9tl`ybYs*z9{nDOl9nVUhL+wOdtT`mS4#TA=ahR#9*hK>fP4P7jl^?sE4Q_{vacQ5 z#_BZdYhmoh(sE~kwlyV+Ea?l|tR~{(>25o)ffm_7MR2;Rqrl87OotPH|JWVMk?4vn zOQkV;a+qtGceUzwVLPe2$$`+IaGfUxL^=|=hRAhyMJ^N!bvtm_em6^Zy2Zo{Wqz~s zNmr+!yNpy9%!n0iGFE+|yOm$vI8O7_#BryX*!uDVP19&8p%HD;>DJ@dlH6J9^(pEs z8umSS5OR7GL`n7li(BL|V$yRGF%wL`c1c2Lo$~C2Vjpv}Y#59c zf26Xy28Cj#CXOp!@U4B!Z~0}e}to@!_@TWmHQ6`06S+0 z40eF74#ruAFlGRAWi&fTp>S4kV@b|2B&+qHv?~l7Nj}a5OEr`EGK5efW~k(NcL;Bo zSytb1;M4}VvE7brqkywgtV4%R>nHid`lF<<&B_e4!eO=@x$xTh(oP#-NNs>7+F&Qq z!bX)*XHtL_A6J%c!ND36L&8lO!0!S)XHs!uK_79oY*;+Nl~pnS3Y{~l@Guz=dhagz z{>dzy-Yvs2*dntCk`m1+B_`Ml%jhDR)ykUd(_5qr)f4DP+&sk^v#LNB`asW4TQQz$ zqtcx*;-|CSZmJ7lUPW_nK+iUTEFAO4G0^1%=&=HUwk-$;au_hsK-#tH3c070R5pS; zVw4ygVQ4blu2*G^tfJmTaS_EO+&?Om7^Ke~Q75?p;7Wc5d>GaR_}+y@`W+A?*aU9# zXdQk{+Ke{byG83BjQPPo!M|r9d19M0)Q73LgL|V@B{9Ga`&4b>`vu%6M*ur_F?-X8 z$H1trv)3z>r8!^%BGtjW({UE2CYOdKnGy+~FmPFm+#KU$yA8wx=i0_~gRe#&f!EFkp zg?|75pU|BEgK6yg8jw%}$2r_6?a;-$fV0KF7PvU4V6e<8DCz E14jXjC;$Ke literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/py31compat.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/py31compat.py new file mode 100644 index 0000000..a381c42 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/pkg_resources/py31compat.py @@ -0,0 +1,23 @@ +import os +import errno +import sys + +from .extern import six + + +def _makedirs_31(path, exist_ok=False): + try: + os.makedirs(path) + except OSError as exc: + if not exist_ok or exc.errno != errno.EEXIST: + raise + + +# rely on compatibility behavior until mode considerations +# and exists_ok considerations are disentangled. +# See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663 +needs_makedirs = ( + six.PY2 or + (3, 4) <= sys.version_info < (3, 4, 1) +) +makedirs = _makedirs_31 if needs_makedirs else os.makedirs diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/AUTHORS.txt b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/AUTHORS.txt new file mode 100644 index 0000000..0360f98 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/AUTHORS.txt @@ -0,0 +1,590 @@ +@Switch01 +A_Rog +Aakanksha Agrawal +Abhinav Sagar +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Wentz +admin +Adrien Morison +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Aleks Bunin +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andre Aguiar +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrey Bulgakov +Andrés Delfino +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anudit Nagar +Anuj Godase +AQNOUCH Mohammed +AraHaan +Arindam Choudhury +Armin Ronacher +Artem +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avinash Karhana +Avner Cohen +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Darnell +Ben Hoyt +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernard +Bernard Tyers +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bhavam Vidyarthi +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Brandon L. Reiss +Brandt Bucher +Brett Randall +Brian Cristante +Brian Rosner +BrownTruck +Bruno Oliveira +Bruno Renié +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris McDonough +Chris Wolfe +Christian Clauss +Christian Heimes +Christian Oudard +Christoph Reiter +Christopher Hunt +Christopher Snyder +cjc7373 +Clark Boylan +Clay McClure +Cody +Cody Soyland +Colin Watson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Cristina +Cristina Muñoz +Curtis Doty +cytolentino +Damian Quiroga +Dan Black +Dan Savilonis +Dan Sully +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Katz +Daniel Shaulov +Daniele Esposti +Daniele Procida +Danny Hermes +Danny McClanahan +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Caro +David Evans +David Linke +David Poggi +David Pursehouse +David Tucker +David Wales +Davidovich +Deepak Sharma +derwolfe +Desetude +Devesh Kumar Singh +Diego Caraballo +DiegoCaraballo +Dmitry Gladkov +Domen Kožar +Donald Stufft +Dongweiming +Douglas Thor +DrFeathers +Dustin Ingram +Dwayne Bailey +Ed Morley +Eitan Adler +ekristina +elainechan +Eli Schwartz +Elisha Hollander +Ellen Marie Dash +Emil Burzo +Emil Styrke +Emmanuel Arias +Endoh Takanao +enoch +Erdinc Mutlu +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Ernest W Durbin III +Ernest W. Durbin III +Erwin Janssen +Eugene Vereshchagin +everdimension +Felix Yan +fiber-space +Filip Kokosiński +Filipe Laíns +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gdanielson +Geoffrey Sneddon +George Song +Georgi Valkov +ghost +Giftlin Rajaiah +gizmoguy1 +gkdoc +Gopinath M +GOTO Hayato +gpiks +Greg Ward +Guilherme Espada +gutsytechster +Guy Rozendorn +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +Herbert Pfennig +Hsiaoming Yang +Hugo +Hugo Lopes Tavares +Hugo van Kemenade +hugovk +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ilan Schnell +Ilya Baryshev +INADA Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Ivan Pozdeev +Jacob Kim +jakirkham +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Firth +James Polley +Jan Pokorný +Jannis Leidel +jarondl +Jason R. Coombs +Jay Graves +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jelmer Vernooij +jenix21 +Jeremy Stanley +Jeremy Zafran +Jiashuo Li +Jim Garrison +Jivan Amara +John Paton +John T. Wodder II +John-Scott Atlakson +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joost Molenaar +Jorge Niedbalski +Joseph Long +Josh Bronson +Josh Hansen +Josh Schneier +Juanjo Bazán +Julian Berman +Julian Gethmann +Julien Demoor +Jussi Kukkonen +jwg4 +Jyrki Pulliainen +Kai Chen +Kamal Bin Mustafa +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +KOLANICH +kpinc +Krishna Oza +Kumar McMillan +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurie O +Laurie Opperman +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark Williams +Markus Hametner +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Matt Good +Matt Maker +Matt Robenolt +matthew +Matthew Einhorn +Matthew Gilliard +Matthew Iversen +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna +mdebi +memoselyk +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Williamson +michaelpacer +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +Nate Coraor +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nguyễn Gia Phong +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nicole Harris +Nikhil Benesch +Nikolay Korolev +Nitesh Sharma +Noah +Noah Gorny +Nowell Strite +NtaleGrey +nvdv +Ofekmeister +ofrinevo +Oliver Jeeves +Oliver Mannion +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +onlinejudge95 +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavithra Eswaramoorthy +Pawel Jasinski +Pekka Klärck +Peter Lisák +Peter Waller +petr-tik +Phaneendra Chiruvella +Phil Elson +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Prashant Sharma +Pratik Mallya +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal +Qiangning Hong +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Razzi Abuissa +rdb +Reece Dunham +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Richard Jones +Ricky Ng-Adam +RobberPhex +Robert Collins +Robert McGibbon +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Roman Bogorodskiy +Romuald Brunet +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Ruairidh MacLeod +Ryan Wooden +ryneeverett +Sachi King +Salvatore Rinchiera +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Woodworth +shireenrao +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +sinscary +socketubs +Sorin Sbarnea +Srinivas Nyayapati +Stavros Korokithakis +Stefan Scherfke +Stefano Rivera +Stephan Erb +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +stonebig +Stéphane Bidoul +Stéphane Bidoul (ACSONE) +Stéphane Klein +Sumana Harihareswara +Surbhi Sharma +Sviatoslav Sydorenko +Swat009 +Takayuki SHIMIZUKAWA +tbeswick +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tom Forbes +Tom Freudenheim +Tom V +Tomas Hrnciar +Tomas Orsava +Tomer Chachamu +Tony Beswick +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +toxinu +Travis Swicegood +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Vikram - Google +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo +Vipul Kumar +Vitaly Babiy +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William ML Leslie +William T Olson +Wilson Mo +wim glenn +Wolfgang Maier +Xavier Fernandez +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Zearin +Zhiping Deng +Zvezdan Petkovic +Łukasz Langa +Семён Марьясин diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/INSTALLER b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/LICENSE.txt b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/LICENSE.txt new file mode 100644 index 0000000..75eb0fd --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2020 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/METADATA b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/METADATA new file mode 100644 index 0000000..a1a8d09 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/METADATA @@ -0,0 +1,82 @@ +Metadata-Version: 2.1 +Name: setuptools +Version: 44.1.1 +Summary: Easily download, build, install, upgrade, and uninstall Python packages +Home-page: https://github.com/pypa/setuptools +Author: Python Packaging Authority +Author-email: distutils-sig@python.org +License: UNKNOWN +Project-URL: Documentation, https://setuptools.readthedocs.io/ +Keywords: CPAN PyPI distutils eggs package management +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: System :: Archiving :: Packaging +Classifier: Topic :: System :: Systems Administration +Classifier: Topic :: Utilities +Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7 +Description-Content-Type: text/x-rst; charset=UTF-8 + +.. image:: https://img.shields.io/pypi/v/setuptools.svg + :target: https://pypi.org/project/setuptools + +.. image:: https://img.shields.io/readthedocs/setuptools/latest.svg + :target: https://setuptools.readthedocs.io + +.. image:: https://img.shields.io/travis/pypa/setuptools/master.svg?label=Linux%20CI&logo=travis&logoColor=white + :target: https://travis-ci.org/pypa/setuptools + +.. image:: https://img.shields.io/appveyor/ci/pypa/setuptools/master.svg?label=Windows%20CI&logo=appveyor&logoColor=white + :target: https://ci.appveyor.com/project/pypa/setuptools/branch/master + +.. image:: https://img.shields.io/codecov/c/github/pypa/setuptools/master.svg?logo=codecov&logoColor=white + :target: https://codecov.io/gh/pypa/setuptools + +.. image:: https://tidelift.com/badges/github/pypa/setuptools?style=flat + :target: https://tidelift.com/subscription/pkg/pypi-setuptools?utm_source=pypi-setuptools&utm_medium=readme + +.. image:: https://img.shields.io/pypi/pyversions/setuptools.svg + +See the `Installation Instructions +`_ in the Python Packaging +User's Guide for instructions on installing, upgrading, and uninstalling +Setuptools. + +Questions and comments should be directed to the `distutils-sig +mailing list `_. +Bug reports and especially tested patches may be +submitted directly to the `bug tracker +`_. + +To report a security vulnerability, please use the +`Tidelift security contact `_. +Tidelift will coordinate the fix and disclosure. + + +For Enterprise +============== + +Available as part of the Tidelift Subscription. + +Setuptools and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use. + +`Learn more `_. + +Code of Conduct +=============== + +Everyone interacting in the setuptools project's codebases, issue trackers, +chat rooms, and mailing lists is expected to follow the +`PyPA Code of Conduct `_. + + diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/RECORD b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/RECORD new file mode 100644 index 0000000..f6422d7 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/RECORD @@ -0,0 +1,164 @@ +../../../bin/easy_install,sha256=1wu0kPyztuYFpaFt8Bp1NIg-_p5PFosvrPUMGG-_-6c,294 +../../../bin/easy_install-3.9,sha256=1wu0kPyztuYFpaFt8Bp1NIg-_p5PFosvrPUMGG-_-6c,294 +__pycache__/easy_install.cpython-39.pyc,, +easy_install.py,sha256=MDC9vt5AxDsXX5qcKlBz2TnW6Tpuv_AobnfhCJ9X3PM,126 +setuptools-44.1.1.dist-info/AUTHORS.txt,sha256=ilkpJ4nuW3rRgU3fX4EufclaM4Y7RsZu5uOu0oizmNM,8036 +setuptools-44.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +setuptools-44.1.1.dist-info/LICENSE.txt,sha256=gdAS_gPyTUkBTvvgoNNlG9Mv1KFDTig6W1JdeMD2Efg,1090 +setuptools-44.1.1.dist-info/METADATA,sha256=2AxMds4jCrvXAyK2UO21ULfMbAvTyonMZlYm-L9cx7c,3523 +setuptools-44.1.1.dist-info/RECORD,, +setuptools-44.1.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +setuptools-44.1.1.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +setuptools-44.1.1.dist-info/dependency_links.txt,sha256=HlkCFkoK5TbZ5EMLbLKYhLcY_E31kBWD8TqW2EgmatQ,239 +setuptools-44.1.1.dist-info/entry_points.txt,sha256=ZmIqlp-SBdsBS2cuetmU2NdSOs4DG0kxctUR9UJ8Xk0,3150 +setuptools-44.1.1.dist-info/top_level.txt,sha256=2HUXVVwA4Pff1xgTFr3GsTXXKaPaO6vlG6oNJ_4u4Tg,38 +setuptools-44.1.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +setuptools/__init__.py,sha256=0SDEgF1acybGfdxJvyjgeAPKC-3-hoYrLKRw8y4YmLQ,7795 +setuptools/__pycache__/__init__.cpython-39.pyc,, +setuptools/__pycache__/_deprecation_warning.cpython-39.pyc,, +setuptools/__pycache__/_imp.cpython-39.pyc,, +setuptools/__pycache__/archive_util.cpython-39.pyc,, +setuptools/__pycache__/build_meta.cpython-39.pyc,, +setuptools/__pycache__/config.cpython-39.pyc,, +setuptools/__pycache__/dep_util.cpython-39.pyc,, +setuptools/__pycache__/depends.cpython-39.pyc,, +setuptools/__pycache__/dist.cpython-39.pyc,, +setuptools/__pycache__/errors.cpython-39.pyc,, +setuptools/__pycache__/extension.cpython-39.pyc,, +setuptools/__pycache__/glob.cpython-39.pyc,, +setuptools/__pycache__/installer.cpython-39.pyc,, +setuptools/__pycache__/launch.cpython-39.pyc,, +setuptools/__pycache__/lib2to3_ex.cpython-39.pyc,, +setuptools/__pycache__/monkey.cpython-39.pyc,, +setuptools/__pycache__/msvc.cpython-39.pyc,, +setuptools/__pycache__/namespaces.cpython-39.pyc,, +setuptools/__pycache__/package_index.cpython-39.pyc,, +setuptools/__pycache__/py27compat.cpython-39.pyc,, +setuptools/__pycache__/py31compat.cpython-39.pyc,, +setuptools/__pycache__/py33compat.cpython-39.pyc,, +setuptools/__pycache__/py34compat.cpython-39.pyc,, +setuptools/__pycache__/sandbox.cpython-39.pyc,, +setuptools/__pycache__/site-patch.cpython-39.pyc,, +setuptools/__pycache__/ssl_support.cpython-39.pyc,, +setuptools/__pycache__/unicode_utils.cpython-39.pyc,, +setuptools/__pycache__/version.cpython-39.pyc,, +setuptools/__pycache__/wheel.cpython-39.pyc,, +setuptools/__pycache__/windows_support.cpython-39.pyc,, +setuptools/_deprecation_warning.py,sha256=jU9-dtfv6cKmtQJOXN8nP1mm7gONw5kKEtiPtbwnZyI,218 +setuptools/_imp.py,sha256=jloslOkxrTKbobgemfP94YII0nhqiJzE1bRmCTZ1a5I,2223 +setuptools/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +setuptools/_vendor/__pycache__/__init__.cpython-39.pyc,, +setuptools/_vendor/__pycache__/ordered_set.cpython-39.pyc,, +setuptools/_vendor/__pycache__/pyparsing.cpython-39.pyc,, +setuptools/_vendor/__pycache__/six.cpython-39.pyc,, +setuptools/_vendor/ordered_set.py,sha256=dbaCcs27dyN9gnMWGF5nA_BrVn6Q-NrjKYJpV9_fgBs,15130 +setuptools/_vendor/packaging/__about__.py,sha256=CpuMSyh1V7adw8QMjWKkY3LtdqRUkRX4MgJ6nF4stM0,744 +setuptools/_vendor/packaging/__init__.py,sha256=6enbp5XgRfjBjsI9-bn00HjHf5TH21PDMOKkJW8xw-w,562 +setuptools/_vendor/packaging/__pycache__/__about__.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/__init__.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/_compat.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/_structures.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/markers.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/requirements.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/tags.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/utils.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/version.cpython-39.pyc,, +setuptools/_vendor/packaging/_compat.py,sha256=Ugdm-qcneSchW25JrtMIKgUxfEEBcCAz6WrEeXeqz9o,865 +setuptools/_vendor/packaging/_structures.py,sha256=pVd90XcXRGwpZRB_qdFuVEibhCHpX_bL5zYr9-N0mc8,1416 +setuptools/_vendor/packaging/markers.py,sha256=-meFl9Fr9V8rF5Rduzgett5EHK9wBYRUqssAV2pj0lw,8268 +setuptools/_vendor/packaging/requirements.py,sha256=3dwIJekt8RRGCUbgxX8reeAbgmZYjb0wcCRtmH63kxI,4742 +setuptools/_vendor/packaging/specifiers.py,sha256=0ZzQpcUnvrQ6LjR-mQRLzMr8G6hdRv-mY0VSf_amFtI,27778 +setuptools/_vendor/packaging/tags.py,sha256=EPLXhO6GTD7_oiWEO1U0l0PkfR8R_xivpMDHXnsTlts,12933 +setuptools/_vendor/packaging/utils.py,sha256=VaTC0Ei7zO2xl9ARiWmz2YFLFt89PuuhLbAlXMyAGms,1520 +setuptools/_vendor/packaging/version.py,sha256=Npdwnb8OHedj_2L86yiUqscujb7w_i5gmSK1PhOAFzg,11978 +setuptools/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 +setuptools/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 +setuptools/archive_util.py,sha256=kw8Ib_lKjCcnPKNbS7h8HztRVK0d5RacU3r_KRdVnmM,6592 +setuptools/build_meta.py,sha256=MQWILThG6texTPLol6icwM83h8V8TLbg0QCacFRt33k,9887 +setuptools/cli-32.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 +setuptools/cli-64.exe,sha256=KLABu5pyrnokJCv6skjXZ6GsXeyYHGcqOUT3oHI3Xpo,74752 +setuptools/cli.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 +setuptools/command/__init__.py,sha256=QCAuA9whnq8Bnoc0bBaS6Lw_KAUO0DiHYZQXEMNn5hg,568 +setuptools/command/__pycache__/__init__.cpython-39.pyc,, +setuptools/command/__pycache__/alias.cpython-39.pyc,, +setuptools/command/__pycache__/bdist_egg.cpython-39.pyc,, +setuptools/command/__pycache__/bdist_rpm.cpython-39.pyc,, +setuptools/command/__pycache__/bdist_wininst.cpython-39.pyc,, +setuptools/command/__pycache__/build_clib.cpython-39.pyc,, +setuptools/command/__pycache__/build_ext.cpython-39.pyc,, +setuptools/command/__pycache__/build_py.cpython-39.pyc,, +setuptools/command/__pycache__/develop.cpython-39.pyc,, +setuptools/command/__pycache__/dist_info.cpython-39.pyc,, +setuptools/command/__pycache__/easy_install.cpython-39.pyc,, +setuptools/command/__pycache__/egg_info.cpython-39.pyc,, +setuptools/command/__pycache__/install.cpython-39.pyc,, +setuptools/command/__pycache__/install_egg_info.cpython-39.pyc,, +setuptools/command/__pycache__/install_lib.cpython-39.pyc,, +setuptools/command/__pycache__/install_scripts.cpython-39.pyc,, +setuptools/command/__pycache__/py36compat.cpython-39.pyc,, +setuptools/command/__pycache__/register.cpython-39.pyc,, +setuptools/command/__pycache__/rotate.cpython-39.pyc,, +setuptools/command/__pycache__/saveopts.cpython-39.pyc,, +setuptools/command/__pycache__/sdist.cpython-39.pyc,, +setuptools/command/__pycache__/setopt.cpython-39.pyc,, +setuptools/command/__pycache__/test.cpython-39.pyc,, +setuptools/command/__pycache__/upload.cpython-39.pyc,, +setuptools/command/__pycache__/upload_docs.cpython-39.pyc,, +setuptools/command/alias.py,sha256=KjpE0sz_SDIHv3fpZcIQK-sCkJz-SrC6Gmug6b9Nkc8,2426 +setuptools/command/bdist_egg.py,sha256=nnfV8Ah8IRC_Ifv5Loa9FdxL66MVbyDXwy-foP810zM,18185 +setuptools/command/bdist_rpm.py,sha256=B7l0TnzCGb-0nLlm6rS00jWLkojASwVmdhW2w5Qz_Ak,1508 +setuptools/command/bdist_wininst.py,sha256=_6dz3lpB1tY200LxKPLM7qgwTCceOMgaWFF-jW2-pm0,637 +setuptools/command/build_clib.py,sha256=bQ9aBr-5ZSO-9fGsGsDLz0mnnFteHUZnftVLkhvHDq0,4484 +setuptools/command/build_ext.py,sha256=8k4kJcOp_ZMxZ1sZYmle5_OAtNYLXGjrbWOj-IPjvwY,13023 +setuptools/command/build_py.py,sha256=yWyYaaS9F3o9JbIczn064A5g1C5_UiKRDxGaTqYbtLE,9596 +setuptools/command/develop.py,sha256=B3-ImHP30Bxnqx-s_9Dp-fxtHhE245ACE1W5hmKY9xE,8188 +setuptools/command/dist_info.py,sha256=5t6kOfrdgALT-P3ogss6PF9k-Leyesueycuk3dUyZnI,960 +setuptools/command/easy_install.py,sha256=QU5oxbZC1COqfiBk3m39yB__bG4YwDtWoNEC8GKFyHo,89907 +setuptools/command/egg_info.py,sha256=dnFO_LBQFIZHCfX9_ke_Mtc6s78CrKIpqeiqlFASB0w,25582 +setuptools/command/install.py,sha256=8doMxeQEDoK4Eco0mO2WlXXzzp9QnsGJQ7Z7yWkZPG8,4705 +setuptools/command/install_egg_info.py,sha256=4zq_Ad3jE-EffParuyDEnvxU6efB-Xhrzdr8aB6Ln_8,3195 +setuptools/command/install_lib.py,sha256=9zdc-H5h6RPxjySRhOwi30E_WfcVva7gpfhZ5ata60w,5023 +setuptools/command/install_scripts.py,sha256=UD0rEZ6861mTYhIdzcsqKnUl8PozocXWl9VBQ1VTWnc,2439 +setuptools/command/launcher manifest.xml,sha256=xlLbjWrB01tKC0-hlVkOKkiSPbzMml2eOPtJ_ucCnbE,628 +setuptools/command/py36compat.py,sha256=SzjZcOxF7zdFUT47Zv2n7AM3H8koDys_0OpS-n9gIfc,4986 +setuptools/command/register.py,sha256=kk3DxXCb5lXTvqnhfwx2g6q7iwbUmgTyXUCaBooBOUk,468 +setuptools/command/rotate.py,sha256=co5C1EkI7P0GGT6Tqz-T2SIj2LBJTZXYELpmao6d4KQ,2164 +setuptools/command/saveopts.py,sha256=za7QCBcQimKKriWcoCcbhxPjUz30gSB74zuTL47xpP4,658 +setuptools/command/sdist.py,sha256=14kBw_QOZ9L_RQDqgf9DAlEuoj0zC30X5mfDWeiyZwU,8092 +setuptools/command/setopt.py,sha256=NTWDyx-gjDF-txf4dO577s7LOzHVoKR0Mq33rFxaRr8,5085 +setuptools/command/test.py,sha256=MahF7jRBGYwgM-fdPBLyBpfCqR5ZXSGexPVR-afV3Vc,9610 +setuptools/command/upload.py,sha256=XT3YFVfYPAmA5qhGg0euluU98ftxRUW-PzKcODMLxUs,462 +setuptools/command/upload_docs.py,sha256=O137bN9dt_sELevf4vwuwWRkogHf4bPXc-jNRxVQaiw,7315 +setuptools/config.py,sha256=6SB2OY3qcooOJmG_rsK_s0pKBsorBlDpfMJUyzjQIGk,20575 +setuptools/dep_util.py,sha256=fgixvC1R7sH3r13ktyf7N0FALoqEXL1cBarmNpSEoWg,935 +setuptools/depends.py,sha256=qt2RWllArRvhnm8lxsyRpcthEZYp4GHQgREl1q0LkFw,5517 +setuptools/dist.py,sha256=WiypLfe-bt358W15a53L-KoO_35xK55EXPbmuTtgBYo,49885 +setuptools/errors.py,sha256=MVOcv381HNSajDgEUWzOQ4J6B5BHCBMSjHfaWcEwA1o,524 +setuptools/extension.py,sha256=uc6nHI-MxwmNCNPbUiBnybSyqhpJqjbhvOQ-emdvt_E,1729 +setuptools/extern/__init__.py,sha256=4q9gtShB1XFP6CisltsyPqtcfTO6ZM9Lu1QBl3l-qmo,2514 +setuptools/extern/__pycache__/__init__.cpython-39.pyc,, +setuptools/glob.py,sha256=o75cHrOxYsvn854thSxE0x9k8JrKDuhP_rRXlVB00Q4,5084 +setuptools/gui-32.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 +setuptools/gui-64.exe,sha256=aYKMhX1IJLn4ULHgWX0sE0yREUt6B3TEHf_jOw6yNyE,75264 +setuptools/gui.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 +setuptools/installer.py,sha256=TCFRonRo01I79zo-ucf3Ymhj8TenPlmhMijN916aaJs,5337 +setuptools/launch.py,sha256=sd7ejwhBocCDx_wG9rIs0OaZ8HtmmFU8ZC6IR_S0Lvg,787 +setuptools/lib2to3_ex.py,sha256=t5e12hbR2pi9V4ezWDTB4JM-AISUnGOkmcnYHek3xjg,2013 +setuptools/monkey.py,sha256=FGc9fffh7gAxMLFmJs2DW_OYWpBjkdbNS2n14UAK4NA,5264 +setuptools/msvc.py,sha256=8baJ6aYgCA4TRdWQQi185qB9dnU8FaP4wgpbmd7VODs,46751 +setuptools/namespaces.py,sha256=F0Nrbv8KCT2OrO7rwa03om4N4GZKAlnce-rr-cgDQa8,3199 +setuptools/package_index.py,sha256=6pb-B1POtHyLycAbkDETk4fO-Qv8_sY-rjTXhUOoh6k,40605 +setuptools/py27compat.py,sha256=tvmer0Tn-wk_JummCkoM22UIjpjL-AQ8uUiOaqTs8sI,1496 +setuptools/py31compat.py,sha256=h2rtZghOfwoGYd8sQ0-auaKiF3TcL3qX0bX3VessqcE,838 +setuptools/py33compat.py,sha256=SMF9Z8wnGicTOkU1uRNwZ_kz5Z_bj29PUBbqdqeeNsc,1330 +setuptools/py34compat.py,sha256=KYOd6ybRxjBW8NJmYD8t_UyyVmysppFXqHpFLdslGXU,245 +setuptools/sandbox.py,sha256=9UbwfEL5QY436oMI1LtFWohhoZ-UzwHvGyZjUH_qhkw,14276 +setuptools/script (dev).tmpl,sha256=RUzQzCQUaXtwdLtYHWYbIQmOaES5Brqq1FvUA_tu-5I,218 +setuptools/script.tmpl,sha256=WGTt5piezO27c-Dbx6l5Q4T3Ff20A5z7872hv3aAhYY,138 +setuptools/site-patch.py,sha256=OumkIHMuoSenRSW1382kKWI1VAwxNE86E5W8iDd34FY,2302 +setuptools/ssl_support.py,sha256=nLjPUBBw7RTTx6O4RJZ5eAMGgjJG8beiDbkFXDZpLuM,8493 +setuptools/unicode_utils.py,sha256=NOiZ_5hD72A6w-4wVj8awHFM3n51Kmw1Ic_vx15XFqw,996 +setuptools/version.py,sha256=og_cuZQb0QI6ukKZFfZWPlr1HgJBPPn2vO2m_bI9ZTE,144 +setuptools/wheel.py,sha256=zct-SEj5_LoHg6XELt2cVRdulsUENenCdS1ekM7TlZA,8455 +setuptools/windows_support.py,sha256=5GrfqSP2-dLGJoZTq2g6dCKkyQxxa2n5IQiXlJCoYEE,714 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/REQUESTED b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/WHEEL b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/WHEEL new file mode 100644 index 0000000..ef99c6c --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/dependency_links.txt b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/dependency_links.txt new file mode 100644 index 0000000..e87d021 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/dependency_links.txt @@ -0,0 +1,2 @@ +https://files.pythonhosted.org/packages/source/c/certifi/certifi-2016.9.26.tar.gz#md5=baa81e951a29958563689d868ef1064d +https://files.pythonhosted.org/packages/source/w/wincertstore/wincertstore-0.2.zip#md5=ae728f2f007185648d0c7a8679b361e2 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/entry_points.txt b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/entry_points.txt new file mode 100644 index 0000000..0fed3f1 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/entry_points.txt @@ -0,0 +1,68 @@ +[console_scripts] +easy_install = setuptools.command.easy_install:main + +[distutils.commands] +alias = setuptools.command.alias:alias +bdist_egg = setuptools.command.bdist_egg:bdist_egg +bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm +bdist_wininst = setuptools.command.bdist_wininst:bdist_wininst +build_clib = setuptools.command.build_clib:build_clib +build_ext = setuptools.command.build_ext:build_ext +build_py = setuptools.command.build_py:build_py +develop = setuptools.command.develop:develop +dist_info = setuptools.command.dist_info:dist_info +easy_install = setuptools.command.easy_install:easy_install +egg_info = setuptools.command.egg_info:egg_info +install = setuptools.command.install:install +install_egg_info = setuptools.command.install_egg_info:install_egg_info +install_lib = setuptools.command.install_lib:install_lib +install_scripts = setuptools.command.install_scripts:install_scripts +rotate = setuptools.command.rotate:rotate +saveopts = setuptools.command.saveopts:saveopts +sdist = setuptools.command.sdist:sdist +setopt = setuptools.command.setopt:setopt +test = setuptools.command.test:test +upload_docs = setuptools.command.upload_docs:upload_docs + +[distutils.setup_keywords] +convert_2to3_doctests = setuptools.dist:assert_string_list +dependency_links = setuptools.dist:assert_string_list +eager_resources = setuptools.dist:assert_string_list +entry_points = setuptools.dist:check_entry_points +exclude_package_data = setuptools.dist:check_package_data +extras_require = setuptools.dist:check_extras +include_package_data = setuptools.dist:assert_bool +install_requires = setuptools.dist:check_requirements +namespace_packages = setuptools.dist:check_nsp +package_data = setuptools.dist:check_package_data +packages = setuptools.dist:check_packages +python_requires = setuptools.dist:check_specifier +setup_requires = setuptools.dist:check_requirements +test_loader = setuptools.dist:check_importable +test_runner = setuptools.dist:check_importable +test_suite = setuptools.dist:check_test_suite +tests_require = setuptools.dist:check_requirements +use_2to3 = setuptools.dist:assert_bool +use_2to3_exclude_fixers = setuptools.dist:assert_string_list +use_2to3_fixers = setuptools.dist:assert_string_list +zip_safe = setuptools.dist:assert_bool + +[egg_info.writers] +PKG-INFO = setuptools.command.egg_info:write_pkg_info +dependency_links.txt = setuptools.command.egg_info:overwrite_arg +depends.txt = setuptools.command.egg_info:warn_depends_obsolete +eager_resources.txt = setuptools.command.egg_info:overwrite_arg +entry_points.txt = setuptools.command.egg_info:write_entries +namespace_packages.txt = setuptools.command.egg_info:overwrite_arg +requires.txt = setuptools.command.egg_info:write_requirements +top_level.txt = setuptools.command.egg_info:write_toplevel_names + +[setuptools.finalize_distribution_options] +2to3_doctests = setuptools.dist:Distribution._finalize_2to3_doctests +features = setuptools.dist:Distribution._finalize_feature_opts +keywords = setuptools.dist:Distribution._finalize_setup_keywords +parent_finalize = setuptools.dist:_Distribution.finalize_options + +[setuptools.installation] +eggsecutable = setuptools.command.easy_install:bootstrap + diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/top_level.txt b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/top_level.txt new file mode 100644 index 0000000..4577c6a --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/top_level.txt @@ -0,0 +1,3 @@ +easy_install +pkg_resources +setuptools diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/zip-safe b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools-44.1.1.dist-info/zip-safe @@ -0,0 +1 @@ + diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__init__.py new file mode 100644 index 0000000..9d8ae1e --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__init__.py @@ -0,0 +1,245 @@ +"""Extensions to the 'distutils' for large or complex distributions""" + +import os +import sys +import functools +import distutils.core +import distutils.filelist +import re +from distutils.errors import DistutilsOptionError +from distutils.util import convert_path +from fnmatch import fnmatchcase + +from ._deprecation_warning import SetuptoolsDeprecationWarning + +from setuptools.extern.six import PY3, string_types +from setuptools.extern.six.moves import filter, map + +import setuptools.version +from setuptools.extension import Extension +from setuptools.dist import Distribution, Feature +from setuptools.depends import Require +from . import monkey + +__metaclass__ = type + + +__all__ = [ + 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', + 'SetuptoolsDeprecationWarning', + 'find_packages' +] + +if PY3: + __all__.append('find_namespace_packages') + +__version__ = setuptools.version.__version__ + +bootstrap_install_from = None + +# If we run 2to3 on .py files, should we also convert docstrings? +# Default: yes; assume that we can detect doctests reliably +run_2to3_on_doctests = True +# Standard package names for fixer packages +lib2to3_fixer_packages = ['lib2to3.fixes'] + + +class PackageFinder: + """ + Generate a list of all Python packages found within a directory + """ + + @classmethod + def find(cls, where='.', exclude=(), include=('*',)): + """Return a list all Python packages found within directory 'where' + + 'where' is the root directory which will be searched for packages. It + should be supplied as a "cross-platform" (i.e. URL-style) path; it will + be converted to the appropriate local path syntax. + + 'exclude' is a sequence of package names to exclude; '*' can be used + as a wildcard in the names, such that 'foo.*' will exclude all + subpackages of 'foo' (but not 'foo' itself). + + 'include' is a sequence of package names to include. If it's + specified, only the named packages will be included. If it's not + specified, all found packages will be included. 'include' can contain + shell style wildcard patterns just like 'exclude'. + """ + + return list(cls._find_packages_iter( + convert_path(where), + cls._build_filter('ez_setup', '*__pycache__', *exclude), + cls._build_filter(*include))) + + @classmethod + def _find_packages_iter(cls, where, exclude, include): + """ + All the packages found in 'where' that pass the 'include' filter, but + not the 'exclude' filter. + """ + for root, dirs, files in os.walk(where, followlinks=True): + # Copy dirs to iterate over it, then empty dirs. + all_dirs = dirs[:] + dirs[:] = [] + + for dir in all_dirs: + full_path = os.path.join(root, dir) + rel_path = os.path.relpath(full_path, where) + package = rel_path.replace(os.path.sep, '.') + + # Skip directory trees that are not valid packages + if ('.' in dir or not cls._looks_like_package(full_path)): + continue + + # Should this package be included? + if include(package) and not exclude(package): + yield package + + # Keep searching subdirectories, as there may be more packages + # down there, even if the parent was excluded. + dirs.append(dir) + + @staticmethod + def _looks_like_package(path): + """Does a directory look like a package?""" + return os.path.isfile(os.path.join(path, '__init__.py')) + + @staticmethod + def _build_filter(*patterns): + """ + Given a list of patterns, return a callable that will be true only if + the input matches at least one of the patterns. + """ + return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns) + + +class PEP420PackageFinder(PackageFinder): + @staticmethod + def _looks_like_package(path): + return True + + +find_packages = PackageFinder.find + +if PY3: + find_namespace_packages = PEP420PackageFinder.find + + +def _install_setup_requires(attrs): + # Note: do not use `setuptools.Distribution` directly, as + # our PEP 517 backend patch `distutils.core.Distribution`. + class MinimalDistribution(distutils.core.Distribution): + """ + A minimal version of a distribution for supporting the + fetch_build_eggs interface. + """ + def __init__(self, attrs): + _incl = 'dependency_links', 'setup_requires' + filtered = { + k: attrs[k] + for k in set(_incl) & set(attrs) + } + distutils.core.Distribution.__init__(self, filtered) + + def finalize_options(self): + """ + Disable finalize_options to avoid building the working set. + Ref #2158. + """ + + dist = MinimalDistribution(attrs) + + # Honor setup.cfg's options. + dist.parse_config_files(ignore_option_errors=True) + if dist.setup_requires: + dist.fetch_build_eggs(dist.setup_requires) + + +def setup(**attrs): + # Make sure we have any requirements needed to interpret 'attrs'. + _install_setup_requires(attrs) + return distutils.core.setup(**attrs) + +setup.__doc__ = distutils.core.setup.__doc__ + + +_Command = monkey.get_unpatched(distutils.core.Command) + + +class Command(_Command): + __doc__ = _Command.__doc__ + + command_consumes_arguments = False + + def __init__(self, dist, **kw): + """ + Construct the command for dist, updating + vars(self) with any keyword parameters. + """ + _Command.__init__(self, dist) + vars(self).update(kw) + + def _ensure_stringlike(self, option, what, default=None): + val = getattr(self, option) + if val is None: + setattr(self, option, default) + return default + elif not isinstance(val, string_types): + raise DistutilsOptionError("'%s' must be a %s (got `%s`)" + % (option, what, val)) + return val + + def ensure_string_list(self, option): + r"""Ensure that 'option' is a list of strings. If 'option' is + currently a string, we split it either on /,\s*/ or /\s+/, so + "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become + ["foo", "bar", "baz"]. + """ + val = getattr(self, option) + if val is None: + return + elif isinstance(val, string_types): + setattr(self, option, re.split(r',\s*|\s+', val)) + else: + if isinstance(val, list): + ok = all(isinstance(v, string_types) for v in val) + else: + ok = False + if not ok: + raise DistutilsOptionError( + "'%s' must be a list of strings (got %r)" + % (option, val)) + + def reinitialize_command(self, command, reinit_subcommands=0, **kw): + cmd = _Command.reinitialize_command(self, command, reinit_subcommands) + vars(cmd).update(kw) + return cmd + + +def _find_all_simple(path): + """ + Find all files under 'path' + """ + results = ( + os.path.join(base, file) + for base, dirs, files in os.walk(path, followlinks=True) + for file in files + ) + return filter(os.path.isfile, results) + + +def findall(dir=os.curdir): + """ + Find all files under 'dir' and return the list of full filenames. + Unless dir is '.', return full filenames with dir prepended. + """ + files = _find_all_simple(dir) + if dir == os.curdir: + make_rel = functools.partial(os.path.relpath, start=dir) + files = map(make_rel, files) + return list(files) + + +# Apply monkey patches +monkey.patch_all() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..93ceff92fbba0a596854f75b057eb18544924b17 GIT binary patch literal 8662 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 K_N0-2kh5>{u%{jX literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/_imp.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/_imp.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9923ba704a9579c5f0b589932ee50517335746da GIT binary patch literal 1950 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 Ca?)i0 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/build_meta.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/build_meta.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3396a5b8e807b6bb5104e6c3051f362aca8363f GIT binary patch literal 8667 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%0Dv%i`+#Ba7>JXoex)3$A7)U1$ zAZ9-TpuF=WkQ}*lbXnNs=5+MQXzX3|(B73&7ezT;+W>N6gTqT|RK1UG-ulU%)!XWb zaXYkYB;Y3*x1xGoABNnZm^gb6g?)+A)q_8i?lUIbqgk!am(DC!XJP-Q@Z6ezy=<1n H;LrXa`k%~t literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/config.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/config.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2448ed0e9376e7faeeb432c14e2612412de14968 GIT binary patch literal 17973 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 Bu7v;q literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/dep_util.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/dep_util.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3cfd90a6ad1645f70ea9369bffdc93b27013aede GIT binary patch literal 883 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 DB1vC$ literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/dist.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/dist.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04ade4244f8725ecb45fb8b179ed6155783fa86d GIT binary patch literal 42507 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 M*iTGICDZxjFAr)A3;+NC literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/extension.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/extension.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..48dfa347915c978e08783d13ed764a444108cfd5 GIT binary patch literal 2029 zcmaJ?OOG2x5bo|7+hec2SrQZhi9|ypA}h%_f&(A{iWCSELW`6{ikQo&ce-tlcV2Y& z?5-{EX>*0&u#33xGx!@VZk%%G#EGi$V-pe4R#m@hs=u!Ksx1bC9)UJJ{agIeCgd-i zyxM%2JOnXIP?AWRk!aP^h&FQ;c}?%H`&QGltetnF4kgl)eir22s0-tkY`-8;PxYc5 z)m7fCKO3CUX!lzpJ2H4dWT1A>yl4RPuI$0Qrv@;;BI#2y+<6HI$o`NzFBjEI3KJL) zCd$TjQ3;z&l}ylN)6gOSc?4oU1|{h!SzNbdNhF(4>HW-Rl#=H}`cH{ZESuk>1b;u0 zf;|ARaA7N#slMkgb!s?vEogAysE790K7pKwr41Htb#%!z#|}Yw+XLPB{jgt4*>DwrxS+wv*w}-uk$1d1Fa4kTjwCj%RB56v) zbt<84Dl*5ka-OLVoR3wlk?Z;zsG+alf)1A9#!+t-27C|nO*Fw`zD&Nm8L#gV1Aur9 zHMV7pUk}07V8xMkoB6ay-==$X@zE>n_@9sWhixP!k}!_(!O2TmXE^T1@lUnL);paz zmSqC(5b{vJkLnU*Giq3hFgS>TKMoR5p9O7=YyT;FBj S3h4UB`mFB-SA5WW@B9mju@(0K literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/glob.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/glob.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e8189f1f084b08f9f1c263143d8c419b1ebb5d8c GIT binary patch literal 3787 zcmeHK&2Jn@74NF<>1mJ0j_u7l$!=I{YvmPf|BtWZOz{J`hFcDdS*4b#>?kdl; zJ<~m@Du0aCBO$U#96;I&MS9&@B_;~p)n)w_=dK;c(lK0pKb3NbSuJ_}bA)Z7uDoEbc4O>E&BnY1R>YHtnT$ zxGa908`~R-SS0yiDDrKwNpm*Ew$A(F@z8ejOgvcr=5npJ+Ksc0G9t~A-kwz7sfni8 z9Hy!#-Q-OXXHqClB!zv{f`S2Vy>lP(z`b^>PE1 zu|x0&X-_7xmN=2<#qR6v%p?K3sCUPxLmEqdeM%50X7?(tRaT zETi|-T`YEXz@;Wuz%hE`Rk7Icm5(y%mON5A7r7RFcuL3=>)BkV}{PB!O?gc zteiUCwZY4P9H4!83NI0PfljZ%7b5n2YBI<$>ISK(oY z%95wHWX3^rOr~gvpzw7x>{d9rMCFVV?p!Bj5Uj z9J2<*thlj&#`O0K?`IzKvIQrr6#Psky(eD5&98yG%!Y*z+-0^}aB%zw-m}^$C<6NS z`DV6gqyHd39IsG#yT1Mc`vbA)r!bT7T*<jYeS> z*xD#8D%kOD!~njT?0)y0K~Z z<4&5C)t)*;hA_zb2FXNE!(wHHqV)c_yQj(GV}7L!cJef9MCaU9#aEP4%4iG8(sAst z3?Mb-G_BK4vo_w~X-Yigo^x)cwO7#0dmtX0gG&Q)tzTy$IO1nnjn9%im}7Mwg2NaO zc>r#fIqfb0fRIAFxWw@>n8Gu+kUW@$vGq;Mcl_f(vJ*D)vXI_J-qEb(#}$IXi2vNn z76Z?Q!!-t%GOq(PeF9Uic(!^>&SfV^F)#UgS^3_R)klvSQ)MkRX@+u=C914!4XrYo zQd=1!`P0cml_j}Uur(}Ag6dD6Jk&Y|GpS2uh|-KC)$sKj^ksEYO3Dfu?cajo8sfkkvU$6-!SqchglW&13n7Muy82Y_}bx^#sn@;9Cim;%wA`B*@ z9auqM!N-k?JD;8huU{u}mBxU)Xr>MVt>NQ{FT&57MlR?}KBShQ znfoB*KLl;vrFbTB$NLq(;R1GC2wWJV6gcqTBIq~xx<(NojU1+@+InLCiIFuG6@8P) zB}Eq@J47=i_Z$T4Op`RB6<-R0w1!_3C|!$7Mr46fq7R)!DN&d!6f?a^B>VlT0p5rP2WPN-y%Y=)Nd2{ z29et!WknGb$Ic`d>boFtF#%D(L&VvLoL#cvWn0nYU!WP9ei4ckv=Q992n)JJkE(Z` zHa~p&tYIkIPxuQaC7hDqSJBKJ5Gwl4oQsH1ByL0~%W5`w#pB}X?E$&3aCv&va^B^) zcG6YJZrcTA85$Mqq+3p(8v;CLu}@iX_qxlc!|x66ccjZ038*?8;YHF5Y7;6>)ut+S zs`f$wsO}I+Jc z?da0vZ1+Bxv-n2gL$;&BX9GaU+>LddAW`9tOSer!8$SK?-m{~CC<=o^n8QlV)f%aB`#n3LZsCK{$IVsW1BbH{ z6w1nY+NERD;$NVRYkp2{!_j>9B^1cxuK}3L$c;we+ VYYWjk(M&WKMbUhX)qM2Te*xxJb>#p6 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/installer.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/installer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ee044743c788f56de34fcafd495a27d6e99a760 GIT binary patch literal 4134 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/monkey.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/monkey.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04c96468c219fd91dc592fc4a49ebca931523d2d GIT binary patch literal 4702 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 B^D+Pc literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/msvc.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/msvc.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..802158ea019c887b1c101e49aadfb962a4f51abf GIT binary patch literal 39690 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/namespaces.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/namespaces.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..067a3c411c4c31fb2f30626ebec52a9ca0bedddd GIT binary patch literal 3700 zcmai1O>Y~=8Q$4lQcLQ?isB@wW2D>I2DyPuHb@G$Xe=0Yku--2tz)Dp6=SjH48@iA zD>Eb8A}I7ApWAbR9;l;#P49EhsQ0BqclT5;LL%=3OQ+1zY9c*dvy zN&d3oIRB!L)yK!j0~GZL6?ZtxoB_3N#&UPyvbxV3cf_<#0g8HzN;m_? zoq@|4c6GV;${G0eK7&TR!=TB7!5VK30^a897;o_nzKOQYxA--*>tcg%^LJi3XKb*^ zcc90+ruB89bdqI4PTF@1RXscGReC&R*zw|N;w3vpD2Bo>&K#U!Tw zwenb3$6A?YQdOeh(ghaAPm570>8i{%EG!@%AjVl*2(!lJNi2^G<7cVT#xJqVv|mW< zL*puH8efTQWIQY~!6?l{k>tX7v|YnaF>LhOkvAazhm-!e%tc>hSz2m+RE`T(7JVg$ zeJQF^^^+GuVZvRWXjEw~3YB64bP^I>{oZp?Jnv`e(|&cL$7S(Z?^k^VRqkG((N{tr zSGp`S)h9g^288NWCuS$DSrRY1uR$e6dO0j$K7Q9(n{Cj~ZMx`jH`wInf?T~f1zh47 z;YUViIrcleXy=H{z@3>l=M)2z7f>n!K0hRVj6-PSkFwPbz_?RFhldM8)|?h4*O$)R9D{n8+UPh276~ z!(T*`+ZBdOFa!qFJ1Wznd#5YQQb&;S$(=47NhG7m=k*RC9%f&NO$r{yaXk{p-Ogf8 z?^vfHPuc{4y=Lki8L_dg4Oj!37dLm1HN~DtZz{(c~eimWQRZNd7OKEd0IS zTdg1CDlW8zkb5~{-L+y4oAKOns7KicM-x6 zf^=}^ypNdw0ficW->}{f?AM01qn7cMmZkv*nhDde!9?D|-UugkM9_JanYIL=I@Pcx z^UlgZoP(UH@yUoxvxX=NtYsSyj75bQ<UF!^&MQAnA6J-qYT&6J1&XWAE08h4+Fn%bSoUe@c~&*XvBKAwVd9#5$SEs{V zAot;tv{@mDjh+Wp)nn;L<}T@&HAVLd$HO zyU4sf?r|S2{uh7{O|$)5@myqOwK)7Gs!_=IP#%&r%0o0#Y?#;Fv}A~`$b&Z!m6RQP z3<7a@XuZDt7@sTWvPU8y4pA<0fg4wMw=O!iew6mUczz`PsP|{aZi*!J*;_ZI%Q!;0 z*!1SxH?5PH{iq?oz+`!!sy(Vm>H0>Ona%Q+9$<8YVr@BKfhVaaTDQraX^|(PJfhC! zObek#+Prq~A-F!zaeK(Jg)Dk1eTne@T&UWez>6ku!kab~poPg({5!e_@%G;BMk@#} ZbTYvgHBI*jH=FncV0hqec!9Td@L%k$x77du literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/package_index.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/package_index.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..92949cf9c9d5a00a361a9b9c43bfdae53137c504 GIT binary patch literal 33138 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 V$xIqPr|gEIhX==!I5Q_1{Xg^agsuPp literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py27compat.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py27compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b2e682cc3dadd5b8c3073727dfd3ffaeadfacfd GIT binary patch literal 1813 zcma)6Pj4GV6rY)0+v~NR*hyM}D6p3jECm|{i3o%$q%>&)ZDS=tC@ZAZ#xu4z-ha%D z+c;WZpl3cq$}Qi86DKrRPCdhk1LDoZY0~tOUyng^UrB{z9Q$9mxxxz zB-_@1e1|!_$EsfpB6xIZ9rR7VnY8>CM&F}! z$3|>v`Wr_2Gg&PA%P=?M^)&ZghRIGaV94m)N$;MSV$QcUJ}aw zC`yN3=nc)DF`IUb3kY2qG8usN1yPmc(uuOb-~#aq#QkU59c2mYvN(=1DNnLdDzdaI zc)!b8o{4VwoCz@agoYAWl(1ApU@&AU;h|yUGO${#BJDZj(5p)aT<@y zuOnbpdK{&b(>?~()zGpgb1T|MfesMY*JJ!Z5PW*et#ZDK!{nHT5AK24UqFa20DGnV zv~5)zL@5oDj80;vYQ3XibMHxS_wm+4RfWa&{+_?})QAUr-|cU1wTWtJR0cddV`-2b zpRm3(N1OX-TYO2!&?n(5z}^5!r>gTd2RH#imlcJwnvsI=K|#);D`90xa&8qC6dbY9 z57x|{m4KILm6C4fXC4aQveSUR+tCc0md>Aa~Kv_$RHcLfMwi zHoln%>BZ5Qd8<*9cWxa0N zy#?TT_qi9P-hI(7tCGl}_mq`qxw0SxZ|QA~-nWl}hr9b*n}>V*N2<1)=*HaQJmYOw zmFM7>pm#??!NjFdww@FoXhDutSxg3l=v3KY%#=NbxXO-F=xyC3H>yYnTm=#udqiAp zV;A3p*~JdA@e(m9y>TgT^}0moxIntsO>MOae-C`|JHSBxK+7L$b}O|0zX5dFBG}mX zEl^wyEo(Bjugg)Q69_cK1^E^4qhFx5;byG@y?a&GZQF!awKxl3SE(hY0^SN!vI6Su zIw5`V+gaTO-IqW@*B!!3m}^ZNT5?5If`DfIAmD9KDJPFZ35X_s>-tIPuv5u+$~8!) zMU~Y%T8I0X3ds_GG1g5Qz`GHIq8~-@l1lE^cp^Dtfd~h1S;18y-0BPikjaL>ue}?P zuQ4@}ei@*JFAw`b7oqqFm~A_7opsBpl(AE)WBXrHYT5+9gI91JJ9ve-O~?8VtD~k6 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py31compat.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py31compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65475183bad551c1e479c7658c68c934788f3f80 GIT binary patch literal 1255 zcmZ`(OK;pZ5GE{I0)D82gnrw<*KT zW8|Amb<8ixLfhc-df7S;`O}kJw}#MatNmL~;Jx!9ckR|s z?b^RkDvsgqh(edh-ynwvC=9!1ibZ}VPFc;a`Oo|nrxU|Y*c-l>C4+2r14Blcoz@nH zX>)F9GZTXhU{8ni90Oj4H_Y#$!$10BG8a_DbEuZJ;tUzIpJUz&D1~7#|rTkxma|L_S7ka}?QY?8F%ksZ?%^-c5uW5~nw>B$!~ATv3}K1|`NihT!VhRTJu z>#Y{OuHc`EVM*bNN_roI3ggS>f*f*J73d3LmVsO$=fZI5p-;5_Q^KhPiY>)J1C@(i4b=&^NeTWPsKem8UO$Q literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py33compat.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py33compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ade4d1dc9f689088b9377688ff0d38ad7c94bf7a GIT binary patch literal 1470 zcmZuxPj4Gl5PyGm?X|ORlM=O5Ahar#f~D3*wTN| zoS6{0SQKm!xFxV+*slhZHoXYZaSmcMpYGEg;+#P&0G&%TIX?C2Br5PG&=ap5eFyOMg zyDooFEnJW!d70ZJc>~LC`k`lU{;SWyl~YE+>*`?X9uPumeg$U9IgGz1Q#xfAY)LI& z%PYEMf-O0aSM!=36a5Q-!|#%%U;EaZ`p3Th5iNq>A$Jitz#S#wZ<9Nu26@>6TkAuz zY0A75$y4N^>0@DILi)n?$NYWC7$TFQaC6)ZtWSHrhdD$I(NLP+T?)QM-if z3AVa$3<>j@7dmqQL^{-({G=T_77Y*`u08L1+y>1=zzE-@A@ium0{C@VM1j*T4XMXHkpFi#niTteAM=&z zOeTrzCdo{Rd4Y16Bq#HU z0c)J5^ALB}gLb4%vm!MHyTe`td{TvMCbBNFJq8zRwZ4aSy^GP^X9v%}_^P>#u65cp kz8=6QYm^@0A{j&ldIp#o03OmV1I|1a@*DR;9s(MF0}(rQF#rGn literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py34compat.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/py34compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7b164f1a8a4f5257b17736c7a2be86386517f80 GIT binary patch literal 510 zcmYjNJx{|h5IrZM6#AixkspB6ff}hSNC<%t14|c>5M3%aIog!Oj%>Fm2sVBQjQl09 zOzf~QaZV8GS@-Vj_wH<;=ybM$Z2tTuzA1kA&AK&db4qTm2@*(H24i?^R~Z|_4al7c zFevvJ_;m|1I3ONj5iX)}MEoxC8|A3xlOPFSU>w!Dgk3>D`lQYLG4;TPI8qjGjx#@Irf>0Oo8z`=mr)4lzgso~skYGO%mLSbhnv?`Hl&I;54^}8wJWHp%DD7Oy;oyjyl(dD2@5Kxa zH)xlIRVp(i86L(eFN7TwrR&x2n%rrXPyCzO{!0M?FztuiZ@8^AFO;^_-*x}f!P2Ig yYh6~D$RAZju6t&!PNz$Y6;*w64K}HDN%>zu_aqtTcV`Mb{t1mB};N*z@}A6w&IPG#c*dxF1eT9 z%#z}IS=6CY%V`p)XwoZbLAq@k^$6OaY0>mbiX27SqAk$0z|;kbv`CS^TA=+aK&<|L z-^`vQT>$~Q zS}r>4IbE)eoFQj3XUf^iS#nO~5^_%Fl5$SvQgTk`(sCZi4d85)GUdVCpw2PP(olIg zH(VacjmWiL+Ljyj^!e>;J6vmBS8MXz&hnU{=~{VQ%3V_K&Q0iAWe9!8J#Bu^9xXS~ zNPBy8`>tt~U6$tUU;eg^XE3Us+xL=IF-~aSJ-GuIFHyR;Z0BrwU$Qh>zAty5uFYz0 z>PFGw$F`eO1prAlF0g@J$U@56abuyG^bR%hjm6U9OJ2 zPjh#;J8x?4PA|J^<{rZJm^+T^@l_-Du=L&K?v}ns-3fQkO)Ym!TKBs9q;*oR_Ph7U z)p7TLdoTK&aBcTKoKL#zy^5L|I8?sWA=IC`O|yh2b_%k7r9@?x=Ca)M&D5)P<(h0oV( z1(R^ZzZA|S)$=&~52JAP6*JJ9TGL!L-k4ain%0`WuB{}lf#fXB(pF6n%;-tYKYBt4 zL)TuyxoNmYT~kjr^%Wy9nu#Wea@AZ(24*wa)SCvMat$ECYD{Kq{4OmAbJdD{$}W~` zC9mvN0s+&m&e+}!uP{?Ac~QsEP}5VP#YRlss@A+pXerNe!&ISKuA!eA2H4qDnC3$j zr|gBP*-~}dDfwZtR4wpqm8-57CV@52DdSvF#aa+r1+?DQ)C8XY!Q%0`YS}yPl}g2G z5X@KSDt@(c+*gI;%BxlVmLDvbG!!&pw2vBlv=tq=*Xp`D)a+_Mtu-c^`ioepYg$w9^goTY?7cpL zr>|(Y^(hdj=`RC!j+$M>1(04Vg$dtT^jtw%RP4d~!vVJD+3^Hn8bYBNBbdO5Zs=)4 z*|;XO?H{Mpp2BHdbU?xs2&@(Z+jU2P?YWMCRr@eN)=>L#3ay$G%-z=2y|~yMOm=uL z?)s#Af+-*p`x~ )jg3P$7u(2C%EU#wQG23(R?o*bdCR)fjcnHg<7cNdv1m13*)# z{#l{==c<(jZy6*J6z1%}E7ye1S#gWXUMdE2HnHp!gd>jHAhNmwuP#hw6X9@eVK%QopmkO7{4i5nK6R4Z;RIp2>@0W~-4D~P7lx_$jab#euJ>(< zv*GHZr&Q7P@_gt5@DMF;V$?|DPjL6}X1E(@;qGz4ok$T--Wo8tuIpN3tVNH~rn9Xw z)Twtbtr;3sF!QVz6qejDQJBMg0DCe3#d*P|U?*yIf6je@;EJ9$(t0LZXi{hoE#g`; zah%2BlZHHv8XDSJ&zYX(8m=iCB;i_E%0xK+LZwzLER;NFy5wEFQSfRMu#HQyH0LT< zsJMx1iA8~I;}SZRYB1+1yZwY6%sGKwsMbrajeGXAXGi0@k>o3o&s#qNNQ|Dx;ZLDx z>;kSpee1-j-UR+;jBDUrOACzU_qUWb%mlM+t$riAcol!^MiP?yiq@vk z*9Csc=5wVbXW0kzL0wgB$9C)Gn&;X_V(7AVuw3&nAD2^|w4b5KF4zU9a=3dEN895q zDW^sXE>`SKQD@J9JcDS`e7~Y}$m;4OPE!!<$>_ylf`ItpKpTVMj*d*7jAg1k6h>&?3O02`EFeQ1bi4f_e<^adAYHk~H*P`j9cCH}-A{?Ieeu$|l2fK2L3v&xe_O z9tx&jVtpu|zg~Ar@tssY?^X+J_Nm|sWe;l4l{a=lK?S5JNCo&jK}n*3{I`q<4Fz2G z{74&Tarj42bQ5eut}rDnHv#h|;U?V_&Pg{7;vEP_+Q_>Ck*yjZj;Pi?U#$e*jlh1+ zsX$q&h&GpsrIJn2j>Ybf^-f>JXpw6`TPw$;|o{ljfvigOtw1}ICAU9IuCiJjY`w- zVMSkoFelSAjdh5lywNmKnzYhx8&g-amaK!UQkcw(#tY4SFpV2eVGKoyrrv`hG=k}V za6uLj%|Sl@3OYn21wC$=BYM(o?A{2q^zG3+CLT=S5TJ!P!Q)MsmW#R?r4<$EfiVw| z=dD%aWn+alS7J@U!DxDfEpLtvRGy#tywP-iLyyANX8R zDJvQS>PZ%7SP%#5{VbkkA)L}FglEq31`c@*cqWlH(}Rkw1sv@k=Rkda5QjgHg8F>T zSl3>M24B_Q*tMeFij59e-`diZr>t9|!(P*7U<*J!q}fX2e?<=xl&_Gt+FEiQkxahzfrri*$BN?w+4}2)|?x!M7o$4V$B8#MOipV;IqN#moKa3sy zmIfj;n)(_f=DO~qMziNSbS1=#(a3le7}ZdB{^S(+IRmMu0-uHr^tCa00_I576|t%A z$EeYIMqGZHru2=PI`b=hCs)c6g`N3f<6dGU7P0>1>By)*GueIuv?I1(D#ju$``WUQ zK$xu8XtIYR`2sYyYKJ9q)er9q)eq9q)d3%ey;HYM%nnb>F8h%bIYIX`O@L=-`Ww znH^L|fiQI+3WOG_#flIq4Ti3BS(U@ zJ|YZfa3<=Or-FKV0MFkq&^(9)vX8Ff^lQvqxT@Y#z!Y z5M#g?7{wxm)-)m-VWLcz7Cty-Q<#F|Nd>imK6;kwn_OrSSKBkXn!^=oqWz<|GI4a# zLuB`?8Y^ISGI6Y34d;OtJzVz6@K<5#%ygu`|8HZ9O}qs%0DDjmehcML(xh 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/site-patch.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/site-patch.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c661a45086ad24c37d1d0c158f22a6a7500efbb1 GIT binary patch literal 1540 zcmYjRPiq@T6rY)0?XLbbt<&8aI}r&Yad?3;uq~N8ngnM zKnJDfoemZ&R)e9kxA^qaQ*qfXb8i+^UA1WKjqo*j?G&}5UNl~zY|}+*b@qq#z~}&- ziUX999i(fvD)A3QxCfpPRo8S~H?CcbUV(Mdx(0k!yODNoUsS8qo8#}XTBAM_AOR4IlYG%407Y-<9wHVaR!Yw#+wexs3#PTIQp2oXT2j&>>Df(Wlkv0Ah! zD%PO8?Pc7vng_=~>ERY$N}F z>;}6)FM!G|9zj13I|WuqLq{pvf_#q2kL1*atnhp5+ruW9MiXZ9=n+HuJI00h)1Q&B zKbOB}gE6170ZY?_D|N!hndI3(ig+Mc&gCGwU=jfLX{3N9QO zG&vgNGd1Sf!~SOjTfqH1iYL*C$$@0*ELWVTATA9m9{2N^sqLnTR573Cdp$_yPat&p zQ5YU^uKK$vkE2xXfp7yd^)O_kQIbg}l<)xEyJH+VlZJ3j0m znu^TRL>b>UK(gHUV2+d$#3d<)FMi4u@G1IR^df?&N6DeW%j)du?lL@vdoTk=;TQ} z^rfOUt6^n2v#$1U#{@UqV?3J%6XIj5_N0P!nTk91QlU)7!qg`jzsSO}RO9iK!UPSb zLz2;9b@_4_L31*8QGyK44axFy6PB!AhF;FVu8;f<7{UR38h8_Xq(K_EjT^+?39f-2 zh*%;Z-vzDJ5ll#%bU+)B4tRJLPnx8KUF-t70a~!&hSLC9^x+Lr0k+>;UhE+3K*I2Y Y-0Z%JGQnVXIhegNMY{>XR{{3$e>N1Cy8r+H literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/ssl_support.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/ssl_support.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bb7e2cfb135d9d525fb5756723c901640f6cec5e GIT binary patch literal 6908 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 JZ0Eev{{RuQx%2=4 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/unicode_utils.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/unicode_utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b94ef03fe9a1de478900e9b0810ae3cc7f45af4f GIT binary patch literal 1209 zcmZ8h&u`N(6txS zy}GA8iaE>J$m@BOaF6@nNYCdD9-wdVB_5&=INc+i<}d6f-3~21BhOOmW{c*=A><9j ze1NiKMl3yIUzvVry>p+_8M$D4WcqkU&KsOv&^fub&*6O@)Yg5XR()cZCS6M0cR&=| z!a5${b$ed-?arUZ*!DNJJ7L+9Mk-?yl?v@*ESpxG*+V-iM0snhWSVoq6PuJxmFrQG z$*Cvs%u?zew!xJJD^N_h%Ll^O1-}mdV`OqkO1Lu41FpSc@Vz zadIjQ95!$XlpG0VBpe1p2@O-cc_P$FoXO8|F|os3J>Ps08wuYcNxvimVPYffxUhMi znRxNw!?Bf_*(@ey(>-;BdxXQ*tU?jm#>Z$2dIb_ty#nh$WcV;NAr%=t3~rEd#{ubp zzaYgUPUmz+IqkDKo3S18X?^ZZ;c?!Wc^7n_Fu=b@Kt?cme@VvivjcMcYzx9cXUCf! zv?8=!WyV@Wc9>Ww5e+0Fj~tYdG*JyXU$0!d@4CCu=@82*kHlFaQY&~=u_4tUI?eSL zQ#op+GSY2HyMQWwbps=0-^7&n2g3GcCNQ=FxPwdV)()t0bwTM)#dJ-quWwd$85`2W{%JHVs(_7Vdxn?bcG4eV5IRuZrOb zCet=BB{S+Ut?;Ci=n_v?SzD+`V9BPj9cvXW^57a0scar4QGcvbi}XseNasirCAuA^ z9n)74?^ZcoN6gB=SnWVrgUkN`wyd5wBv1-Zv25If31bKdAw9qtxCiL;ZK&Se>ona& rg$b={K3wiq090FU+~KN6S4f60M>!v7;+6YH826tFfnM7W+u_<@9UmrF literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/version.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/version.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a9ca06b30cea6cea9199bb9df9e54fa8918174f GIT binary patch literal 354 zcmYjNy-vh13{HAQ_XCwW@eVi8Ai;u!5DO~{1LBsd*H~??Z4$+4k3-@ecmx=ErL0Ws zOiZ}wB(UYrcJ#%6MUpHSN&Wm)ypaDGlm9ZKFAW$cWfDd(oc3976`t#-k27{wAYO`TfIC8iEXOf0h->GfFZ5G z=Tf0}YTbKfbeIm{a10Lfd>`g{nBP2>U`N6`b8~9&3*UpNO$P$nRvGU%rq*b*KvxO} z)}Sc1)Tx6LS$G1~fgVeX3N$!+64?NH5UpAZyYsctXW4~7MO<5yO;G`gzb(Xmn#}IP W?6NbmZ{dp5C^#N%7DYVeNBjrS0BQ;V literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/wheel.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..36fe842dbd7ec2bb4afb0da464403b532e93ab5c GIT binary patch literal 7493 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_deprecation_warning.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_deprecation_warning.py new file mode 100644 index 0000000..086b64d --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_deprecation_warning.py @@ -0,0 +1,7 @@ +class SetuptoolsDeprecationWarning(Warning): + """ + Base class for warning deprecations in ``setuptools`` + + This class is not derived from ``DeprecationWarning``, and as such is + visible by default. + """ diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_imp.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_imp.py new file mode 100644 index 0000000..a3cce9b --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_imp.py @@ -0,0 +1,73 @@ +""" +Re-implementation of find_module and get_frozen_object +from the deprecated imp module. +""" + +import os +import importlib.util +import importlib.machinery + +from .py34compat import module_from_spec + + +PY_SOURCE = 1 +PY_COMPILED = 2 +C_EXTENSION = 3 +C_BUILTIN = 6 +PY_FROZEN = 7 + + +def find_module(module, paths=None): + """Just like 'imp.find_module()', but with package support""" + spec = importlib.util.find_spec(module, paths) + if spec is None: + raise ImportError("Can't find %s" % module) + if not spec.has_location and hasattr(spec, 'submodule_search_locations'): + spec = importlib.util.spec_from_loader('__init__.py', spec.loader) + + kind = -1 + file = None + static = isinstance(spec.loader, type) + if spec.origin == 'frozen' or static and issubclass( + spec.loader, importlib.machinery.FrozenImporter): + kind = PY_FROZEN + path = None # imp compabilty + suffix = mode = '' # imp compability + elif spec.origin == 'built-in' or static and issubclass( + spec.loader, importlib.machinery.BuiltinImporter): + kind = C_BUILTIN + path = None # imp compabilty + suffix = mode = '' # imp compability + elif spec.has_location: + path = spec.origin + suffix = os.path.splitext(path)[1] + mode = 'r' if suffix in importlib.machinery.SOURCE_SUFFIXES else 'rb' + + if suffix in importlib.machinery.SOURCE_SUFFIXES: + kind = PY_SOURCE + elif suffix in importlib.machinery.BYTECODE_SUFFIXES: + kind = PY_COMPILED + elif suffix in importlib.machinery.EXTENSION_SUFFIXES: + kind = C_EXTENSION + + if kind in {PY_SOURCE, PY_COMPILED}: + file = open(path, mode) + else: + path = None + suffix = mode = '' + + return file, path, (suffix, mode, kind) + + +def get_frozen_object(module, paths=None): + spec = importlib.util.find_spec(module, paths) + if not spec: + raise ImportError("Can't find %s" % module) + return spec.loader.get_code(module) + + +def get_module(module, paths, info): + spec = importlib.util.find_spec(module, paths) + if not spec: + raise ImportError("Can't find %s" % module) + return module_from_spec(spec) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8fadc5b5dcad16322c9fff0613cd3ec4068236a5 GIT binary patch literal 218 zcmYk0F%H5o3`J9k0U>b^2I_$c2_a6v!U3YtSZyGUqc|<dvYgN9lJ^xjd@oD<-4WuD8w#s(4eZ2?raGG%85naHGm&S|B3nwJwF@q5 TUB=-t-LzyokK6IFmsEWLT7W)f literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4e9261c8e9e01ac22015920417dc31f259179b09 GIT binary patch literal 16412 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/pyparsing.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/pyparsing.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72897ced5cfbfd049ad3c503b1d34f497ae1ee29 GIT binary patch literal 201371 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

%y&tX`In3M=Ib{v3eo`K)v{m<<{dUD1S3#!bC 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/six.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/__pycache__/six.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54569cd377ba5fb1c6d356b37876deb5aaed0dc8 GIT binary patch literal 24501 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 OrderedSet([1, 1, 2, 3, 2]) + OrderedSet([1, 2, 3]) + """ + + def __init__(self, iterable=None): + self.items = [] + self.map = {} + if iterable is not None: + self |= iterable + + def __len__(self): + """ + Returns the number of unique elements in the ordered set + + Example: + >>> len(OrderedSet([])) + 0 + >>> len(OrderedSet([1, 2])) + 2 + """ + return len(self.items) + + def __getitem__(self, index): + """ + Get the item at a given index. + + If `index` is a slice, you will get back that slice of items, as a + new OrderedSet. + + If `index` is a list or a similar iterable, you'll get a list of + items corresponding to those indices. This is similar to NumPy's + "fancy indexing". The result is not an OrderedSet because you may ask + for duplicate indices, and the number of elements returned should be + the number of elements asked for. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset[1] + 2 + """ + if isinstance(index, slice) and index == SLICE_ALL: + return self.copy() + elif is_iterable(index): + return [self.items[i] for i in index] + elif hasattr(index, "__index__") or isinstance(index, slice): + result = self.items[index] + if isinstance(result, list): + return self.__class__(result) + else: + return result + else: + raise TypeError("Don't know how to index an OrderedSet by %r" % index) + + def copy(self): + """ + Return a shallow copy of this object. + + Example: + >>> this = OrderedSet([1, 2, 3]) + >>> other = this.copy() + >>> this == other + True + >>> this is other + False + """ + return self.__class__(self) + + def __getstate__(self): + if len(self) == 0: + # The state can't be an empty list. + # We need to return a truthy value, or else __setstate__ won't be run. + # + # This could have been done more gracefully by always putting the state + # in a tuple, but this way is backwards- and forwards- compatible with + # previous versions of OrderedSet. + return (None,) + else: + return list(self) + + def __setstate__(self, state): + if state == (None,): + self.__init__([]) + else: + self.__init__(state) + + def __contains__(self, key): + """ + Test if the item is in this ordered set + + Example: + >>> 1 in OrderedSet([1, 3, 2]) + True + >>> 5 in OrderedSet([1, 3, 2]) + False + """ + return key in self.map + + def add(self, key): + """ + Add `key` as an item to this OrderedSet, then return its index. + + If `key` is already in the OrderedSet, return the index it already + had. + + Example: + >>> oset = OrderedSet() + >>> oset.append(3) + 0 + >>> print(oset) + OrderedSet([3]) + """ + if key not in self.map: + self.map[key] = len(self.items) + self.items.append(key) + return self.map[key] + + append = add + + def update(self, sequence): + """ + Update the set with the given iterable sequence, then return the index + of the last element inserted. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.update([3, 1, 5, 1, 4]) + 4 + >>> print(oset) + OrderedSet([1, 2, 3, 5, 4]) + """ + item_index = None + try: + for item in sequence: + item_index = self.add(item) + except TypeError: + raise ValueError( + "Argument needs to be an iterable, got %s" % type(sequence) + ) + return item_index + + def index(self, key): + """ + Get the index of a given entry, raising an IndexError if it's not + present. + + `key` can be an iterable of entries that is not a string, in which case + this returns a list of indices. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.index(2) + 1 + """ + if is_iterable(key): + return [self.index(subkey) for subkey in key] + return self.map[key] + + # Provide some compatibility with pd.Index + get_loc = index + get_indexer = index + + def pop(self): + """ + Remove and return the last element from the set. + + Raises KeyError if the set is empty. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.pop() + 3 + """ + if not self.items: + raise KeyError("Set is empty") + + elem = self.items[-1] + del self.items[-1] + del self.map[elem] + return elem + + def discard(self, key): + """ + Remove an element. Do not raise an exception if absent. + + The MutableSet mixin uses this to implement the .remove() method, which + *does* raise an error when asked to remove a non-existent item. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.discard(2) + >>> print(oset) + OrderedSet([1, 3]) + >>> oset.discard(2) + >>> print(oset) + OrderedSet([1, 3]) + """ + if key in self: + i = self.map[key] + del self.items[i] + del self.map[key] + for k, v in self.map.items(): + if v >= i: + self.map[k] = v - 1 + + def clear(self): + """ + Remove all items from this OrderedSet. + """ + del self.items[:] + self.map.clear() + + def __iter__(self): + """ + Example: + >>> list(iter(OrderedSet([1, 2, 3]))) + [1, 2, 3] + """ + return iter(self.items) + + def __reversed__(self): + """ + Example: + >>> list(reversed(OrderedSet([1, 2, 3]))) + [3, 2, 1] + """ + return reversed(self.items) + + def __repr__(self): + if not self: + return "%s()" % (self.__class__.__name__,) + return "%s(%r)" % (self.__class__.__name__, list(self)) + + def __eq__(self, other): + """ + Returns true if the containers have the same items. If `other` is a + Sequence, then order is checked, otherwise it is ignored. + + Example: + >>> oset = OrderedSet([1, 3, 2]) + >>> oset == [1, 3, 2] + True + >>> oset == [1, 2, 3] + False + >>> oset == [2, 3] + False + >>> oset == OrderedSet([3, 2, 1]) + False + """ + # In Python 2 deque is not a Sequence, so treat it as one for + # consistent behavior with Python 3. + if isinstance(other, (Sequence, deque)): + # Check that this OrderedSet contains the same elements, in the + # same order, as the other object. + return list(self) == list(other) + try: + other_as_set = set(other) + except TypeError: + # If `other` can't be converted into a set, it's not equal. + return False + else: + return set(self) == other_as_set + + def union(self, *sets): + """ + Combines all unique items. + Each items order is defined by its first appearance. + + Example: + >>> oset = OrderedSet.union(OrderedSet([3, 1, 4, 1, 5]), [1, 3], [2, 0]) + >>> print(oset) + OrderedSet([3, 1, 4, 5, 2, 0]) + >>> oset.union([8, 9]) + OrderedSet([3, 1, 4, 5, 2, 0, 8, 9]) + >>> oset | {10} + OrderedSet([3, 1, 4, 5, 2, 0, 10]) + """ + cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet + containers = map(list, it.chain([self], sets)) + items = it.chain.from_iterable(containers) + return cls(items) + + def __and__(self, other): + # the parent implementation of this is backwards + return self.intersection(other) + + def intersection(self, *sets): + """ + Returns elements in common between all sets. Order is defined only + by the first set. + + Example: + >>> oset = OrderedSet.intersection(OrderedSet([0, 1, 2, 3]), [1, 2, 3]) + >>> print(oset) + OrderedSet([1, 2, 3]) + >>> oset.intersection([2, 4, 5], [1, 2, 3, 4]) + OrderedSet([2]) + >>> oset.intersection() + OrderedSet([1, 2, 3]) + """ + cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet + if sets: + common = set.intersection(*map(set, sets)) + items = (item for item in self if item in common) + else: + items = self + return cls(items) + + def difference(self, *sets): + """ + Returns all elements that are in this set but not the others. + + Example: + >>> OrderedSet([1, 2, 3]).difference(OrderedSet([2])) + OrderedSet([1, 3]) + >>> OrderedSet([1, 2, 3]).difference(OrderedSet([2]), OrderedSet([3])) + OrderedSet([1]) + >>> OrderedSet([1, 2, 3]) - OrderedSet([2]) + OrderedSet([1, 3]) + >>> OrderedSet([1, 2, 3]).difference() + OrderedSet([1, 2, 3]) + """ + cls = self.__class__ + if sets: + other = set.union(*map(set, sets)) + items = (item for item in self if item not in other) + else: + items = self + return cls(items) + + def issubset(self, other): + """ + Report whether another set contains this set. + + Example: + >>> OrderedSet([1, 2, 3]).issubset({1, 2}) + False + >>> OrderedSet([1, 2, 3]).issubset({1, 2, 3, 4}) + True + >>> OrderedSet([1, 2, 3]).issubset({1, 4, 3, 5}) + False + """ + if len(self) > len(other): # Fast check for obvious cases + return False + return all(item in other for item in self) + + def issuperset(self, other): + """ + Report whether this set contains another set. + + Example: + >>> OrderedSet([1, 2]).issuperset([1, 2, 3]) + False + >>> OrderedSet([1, 2, 3, 4]).issuperset({1, 2, 3}) + True + >>> OrderedSet([1, 4, 3, 5]).issuperset({1, 2, 3}) + False + """ + if len(self) < len(other): # Fast check for obvious cases + return False + return all(item in self for item in other) + + def symmetric_difference(self, other): + """ + Return the symmetric difference of two OrderedSets as a new set. + That is, the new set will contain all elements that are in exactly + one of the sets. + + Their order will be preserved, with elements from `self` preceding + elements from `other`. + + Example: + >>> this = OrderedSet([1, 4, 3, 5, 7]) + >>> other = OrderedSet([9, 7, 1, 3, 2]) + >>> this.symmetric_difference(other) + OrderedSet([4, 5, 9, 2]) + """ + cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet + diff1 = cls(self).difference(other) + diff2 = cls(other).difference(self) + return diff1.union(diff2) + + def _update_items(self, items): + """ + Replace the 'items' list of this OrderedSet with a new one, updating + self.map accordingly. + """ + self.items = items + self.map = {item: idx for (idx, item) in enumerate(items)} + + def difference_update(self, *sets): + """ + Update this OrderedSet to remove items from one or more other sets. + + Example: + >>> this = OrderedSet([1, 2, 3]) + >>> this.difference_update(OrderedSet([2, 4])) + >>> print(this) + OrderedSet([1, 3]) + + >>> this = OrderedSet([1, 2, 3, 4, 5]) + >>> this.difference_update(OrderedSet([2, 4]), OrderedSet([1, 4, 6])) + >>> print(this) + OrderedSet([3, 5]) + """ + items_to_remove = set() + for other in sets: + items_to_remove |= set(other) + self._update_items([item for item in self.items if item not in items_to_remove]) + + def intersection_update(self, other): + """ + Update this OrderedSet to keep only items in another set, preserving + their order in this set. + + Example: + >>> this = OrderedSet([1, 4, 3, 5, 7]) + >>> other = OrderedSet([9, 7, 1, 3, 2]) + >>> this.intersection_update(other) + >>> print(this) + OrderedSet([1, 3, 7]) + """ + other = set(other) + self._update_items([item for item in self.items if item in other]) + + def symmetric_difference_update(self, other): + """ + Update this OrderedSet to remove items from another set, then + add items from the other set that were not present in this set. + + Example: + >>> this = OrderedSet([1, 4, 3, 5, 7]) + >>> other = OrderedSet([9, 7, 1, 3, 2]) + >>> this.symmetric_difference_update(other) + >>> print(this) + OrderedSet([4, 5, 9, 2]) + """ + items_to_add = [item for item in other if item not in self] + items_to_remove = set(other) + self._update_items( + [item for item in self.items if item not in items_to_remove] + items_to_add + ) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__about__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__about__.py new file mode 100644 index 0000000..dc95138 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__about__.py @@ -0,0 +1,27 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +__all__ = [ + "__title__", + "__summary__", + "__uri__", + "__version__", + "__author__", + "__email__", + "__license__", + "__copyright__", +] + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "19.2" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD or Apache License, Version 2.0" +__copyright__ = "Copyright 2014-2019 %s" % __author__ diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__init__.py new file mode 100644 index 0000000..a0cf67d --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__init__.py @@ -0,0 +1,26 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +from .__about__ import ( + __author__, + __copyright__, + __email__, + __license__, + __summary__, + __title__, + __uri__, + __version__, +) + +__all__ = [ + "__title__", + "__summary__", + "__uri__", + "__version__", + "__author__", + "__email__", + "__license__", + "__copyright__", +] diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9fd08ba870d690eb75740deee9668f928306cf5 GIT binary patch literal 742 zcmYk4%Z}496o!*trs)kv2+i7z#G(=t&lEOA2n|e^2q9Hs;f>|SZenok$d{r<;stmN zcDz!yY+%od6~|MJ23z^$bM*Vf=eOB>K1pCyU;nUQy(IY=gZ~HQl56;ZxirNPQ$ zb}ww)4Z(y`7JOwatYN39nN&xOl7-MNmYGvpnC4(*S@|eySn-*aQkU)djj;j+FO~FC zIJ7eseKM@(}h zb!?OerchzDw{jc2v93Mkx6*5OE6t^8&);s=2>$*Cs#XHMJ0AWS`grUVE%VFv?B=cu zw7k4}aRFGNr|$h?9&OkKA1t(M<3-wj!~hU|V+uU6!@;Eq_>tJt zxQ_Vy4OgZXSSTfp_n%Cqozd9Y0$b4-huIh5KybmC2gn*6hkL=L(859r=X;^|SjjC| z7Hxf=udtJ#y|WiP;X~t%Q4UiOb7Sv~#c=ek32z|eA)aElgZ67cjJFVtt@{)orS%Yy? zh0FWh*Ap*=DKp&=CG{czD+yiJQjm2jRU`?-m z(u5M5(+l91XIY943GIAEB!A*4M~gb|6=husR@67@G&^ewY4VX{3VP&1Q9E1xeFXzG{Ev)?D~>!@c=8=eIl=)K0ShDhHi-(z#4I m1e-XZScS-!KjQ}uV7$R0&eLsf-npQP)$eJ*M0ioZZ2tk(TcWH0 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/_compat.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/_compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab3d4d699fd3ff23ed060c159a7e12be328975d0 GIT binary patch literal 1042 zcmah{J8K(35Z=d0IxDgqh)Kw!P?~@W>maTI#sm^bX99shu36T%E9>mL+sp2rjEr5` zVEv4w^k3RGmHSkwGIKJHTxDS9=C$9vPHt}Y3DE4~x0IZaUudio1LHlg`wBu4MGI2W zl$I=IB~Lj;A1k6X($R58k>^D56P9-Gtq821?%9tzp3-!q>gqmzRY!HNNcu>zFJ#=i z1#B|rVM`u5Q#4+SysVA&Ay)Z3ce$y;u(o;S#k8q15B9+=Hg*dglZ@i)J3>bnxCiXs zfcQkN$u*raMHRb>6v2wLczCH)c52dkymBRM*hPLHxeIyXAa z{R}*%_Of+M+RO~V9}t#CaxXw=l2S!dwq88tibJXB>@^~ae|UR^$zt_&ZUACQ&*_q!^Gk%I2RDEjcviR&RkGBf?`OFaIDiXO-LTME=@G(P+{~Y4GBc%4 zbW!BS`(rb!oT(CLv&8D!xI~_62MIe0ma(JqQdf9{_6EIPII-8&kMMK(aD6S;g||C=r<{Yw0KTBJ_l)^r;Z9a5%gvp=aa& z?q_oM>HsE>L5H!02z?<+qnZNsfe_ytS*#-VG2ph7TioAD+X5|Y+^_s4m~8_wwc8ll z@*00aX&0hBd;4n4LgW{1-@A;(V`C@4uUDJy=?DkWS@aG9$?ec#y1w4 zwm84V|Hxui;BMiYxD5Vm)d%_dFT6pHx%xIy)*S-k=YfdEwkfw<%Xr(CS<+D*3a#v5#>uUf$= z960bt@|X6?i907w%y?Ny+ufufaOCmFjQx1V<7X4DuC@r2;kz&4hdLpja4=tLFxY{r zpMl_n(}av@pN^cqGjjVbB`*kfxci=PSJb9%zb@)i(yzm8jn`qeZf8B=!K}xNJ@c!Q#<4RVMR!d=Tq6mD$=@#nQ07iHr=4BU~|G92o3C)vrMa(x;sC z9ZtFPp7dSr@*1>&&pl}Cyup2FJ>KLkXd8Tmx1sgDsE1h%w^j|X`02lD!VqE6g0U4CmBHrP$Q}qx zuwegGsAo>^x!ru`D0CsKr)DVBNj#6S#4xr776sb+oRg?qj-@)VJl}caN6%iY^$9Tq zW2h>{0Np8!6JdM{Vce%v=M_;H7zktw9)Q#)l#$4qut5@P4VO}ZFWxY=S%HtbYJ7~0 zAq9S$d_RG@0P|I75M`L z>6Nt^dou}>T%(Y!)jEpvDDd*tB@~xYTt#sW#SIicNGR`N)>@vz7pl*J@Tu<}|5<$m zs$&J8;ttfm$hQiwWO3-fQ|(c6yNF)yR|(nPBnJfc5UIz3lOlMi4H0hCNcIKcim1JU0aOx(Q zl~NME{M)!k1tp=rx79#a+?(J(8TcS#jwwtsg@3{_FWuc2k;%`A_GLhs|0rkGC%8uA M--k`NbKQgb4L4o?LjV8( literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/markers.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/markers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ca134b7a2a47361cb37767a069ce8bee94a542e GIT binary patch literal 8963 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..512f786f1c556025f834ec23723ea81de80fedb9 GIT binary patch literal 4055 zcmZ`*OLH5?5#HHdEEXULf)q`Pq-?JqmIa9fDBH3mOO^>ykj1GbESV z2RyToC74X5LOWGSm2de0lV1ipbI`=Lu4z=GB-A3}l1O*;$Z!pUGCee1Q~hV$4E!6R z6=mIQWV?2hb8}JN%_}<-g9rXu_R{Cf&(s%AF$Gry9-Ef$udsz|QO%?whQ@%&oVey*;k&64znF zw6II|&hBgOIp7ET{CVJuef|RQLw)`o;7fh}BJjg~{$1cl`urtUpr^ohnK^8Lm3Ikq z#$>m+5=DxzN&{43PW>?%9R-|w25;_L`3cJKA>|D*I^CUmDlS%ue3x@ z(}^DqItkuxfd32Z2Kavm+70kV+?(v?-bZwbp7~zeCq!d8b`#e5CTMQ4TcCOCgl23P zM$orGH^#<5=N#$Yb#JrVYz%hsF}nq`e5`hKhgFaGPuMi@SJm!5VR!CoU^~aMYz|gp z17Bmcy}R@*t^sm-j-H2{o@eur(|c53)yfxsL0py%IpjYUN!Ur57ewuZr_!du(?A4C zEQ@U(#HqL5iCZc38)Z`th!kWStEmr`xn8FpQ#q9IU?YhAaE(1n?MR6Q`J39t5afC8B0 zC?ulNe$K~WVNmuo0o6^jiRvGahX>@*0l9QQ$_HfnfZRGDb6sP`t4I^K*3CTpo%865 zG&($#7NCdw;y&a#zm){>szRHzeY)khAn-EhasOLSK$cqu%yIZ3k9nMjCa?r=>swme zrUa0#H>6f3ybRKx3`v9}p(N>X5cwIgs-W3=UvcX;|dp$_KYu>exW|KBR^z+knCuJP>QqZagD`fz`9(8MJmFCPqQe6PVJ zWzr1%XQ)N9@NZEYmX(tOCr`@XRUL5rlP9E-SI9rqYy<$TlX|CDSKx5LVF^;V#wfMfNrTX(VqV2$C-mRntC41&J z**3N^*r-0PVFH1-_Vr!zNAjiiwMN1E_ePxW{m*K%nC$Gf=4IjE=Kn}@dpYD_4s+Yw z%2VTs&i@M1fo*diL18~J_|Gtxi5}xiXv6;ow4i8S{EWOniwvwrc|uF%U=};JC;-f} z(?O6F`9G2F4ee{Oz5!4JO))Kj3@&frhk+a6zaouwHEx6=?yW|5s+Up5dBPn(bdr5CNTj(QgseN<&xr#$b5!=br4u5spWP{+0vy$U`(UA2U#d6OP7rHK~-q!8XFjHgcktZ*s#n$gHm0e+G|3$gE^UFXc5I(`sTpwcoP z!^My2hvUGpI&uq17Ku8hIpnZp@&P0TB!fsWfRZe_=U(?Hf@hT|dCEiu4ivmj_z({G z7zbo~_od*&C{ov7{^%wU{1i&@%2cOV=D+a64y$89>eY)uU$lb23t0+F7t*5eYE6Z- zYl|zN)fx|$q%At_HfI84i+7u~`OoWX(rzAd*5XR7S#L~z2s5kE}uR_umK5Z;F>+?0>iy&Nu89jJje(=HUaeuM? zX>I;%IdG_7Zq#Mru(MQad@TpP!|v)zeO?wJBP&>LYwF#9Y^=1U{sVlq4l$^$E#oU( zJ;~+Bp_f|Yp4XQZVME@D{xEL&o_C_O^Bb71n?R(MJl zMs*v`^J#Jh%49(=kx`>$m2}{be_&C9vkrgeQ@~@MNtwZ%koHaY_1-p?6`^I=w&%p;?$uXOSNNK@^-m1B$wI; zb!RAv^fE~!rIwMzP0|)k(FB#yqK$x}EzqD%(ICiw(4RZ~u|QD&P@q7HB30VB-*@J* zv%9l4T{tOFl+;|_nYnZCIp>~x?sv~USC!GxqK2R4&3~(Wsjg}N#GB+#4mW3Uxj#l? zYqnn38v4B6Fy@U$WPHtU7P(EL!NIA28hjGe6y zH%8`18l&^0jj{PLUHhbF=j{9~&CWa9Zf54kabK{9a6jY}9dl*7GjY?v^Bs6zw1@G0 z*x7;mN!*XvqqrY+CUL*h9<#UI(&l&J`MA9u&$r9--A?|_ls$1*pWkEeuqRPsuf5aW zg})D=+=~QG~#FLka#maJY~{M+qQEh`;vuOuoF;`byW}(-g-5e9*PQ0H*?MhZc6HrbZZ$tV z^RZdChO(=b>Xpipv9X57|YzD>}uM zVS6~fW1ZXWQG4u`j#@|L%L#j%Judg7_6SsPhd+9*;yQ7+R;dWl5A(d9#^sW3TgNBH z##_>F?EV)a9MyC!Z`rY+km%u6<+x7Mt58|3)*{~2Tq~~Ls@JYKR%>C!sd_WkMZAlv z3Uy?`>8j)!O0yCtQAf>lo%&*+JS1XHRN{ z^GsM`OT3?t366NLSj!c6*~0KxbD;K6@WCv{9|tt69U!NdV2lM;SS~-9pm5=muK?FI`e+%;js z4!;|BEU+b=Tk7Mkr>8LJjwuHn>N@BT{6klwf2C_G^?K{NV_OUBqL^`2vFYmVwp67Y zMiWsBk0qGe)7@o>Qd{abJ0|CX^Bki-dSpS%4bB0+SFvw5`Qj9lVOkZ&+>%oK!rk z)vT|FWv(yRs>^X@G!E~HG*eSx{88bKUBxFxZFEPA_P&>fYmI5 z;9ELCvfu@PWI+l5$$}98l85aPz|n%B0&RXs(112y1WuU1^I>Ns0It9bqsR+*MScu< zfv?DKbGEIF+j|IRd1vpnAHbK}?F05c`$4olVIQ>j+YcePL$Ko^f3o~+lX%v~91$Y{ zU+W%YgcrP?#^s(z($-eAJ9=Bct8Zr78F#-2IC>|;`%m7q^FS=$8PWxG0BDv$CUKu% z0Svut8{G$KW<*B!cO116Je+#{_yM)4rcv3(wv!Om^y`n|!RwE2mQI&)iW7i3#)M|m zAHp=oRY$ojL(0!UIFYr@u-1OYi4)7^SMhbgc&6~qm|^^vksHW(@I@EnG|6OM80TQN z^%bg({uVplnA^yK^4A~REExf@lug>?CWG9@%fOE68~X+bUvT7L64-^F5O5PX`5tVH z;hV&1YGBK>EK7-&2X*@Zv{%5V!u?#(wC?FQ4fXiOSX;Ye$k5SW)~=p2H7~P1qhk)! zHP6gxuRuP>wdOd874^7jxaU0c0!h!d^_A=uEKb$OQRTgyU&J!B>3WrB)lpodtB)|@ zO2;3YYkAK$R_hK{Ri0x9T&92_F`X;;LKc^rUepbJ464pw)7W@mfV5M=-!F<|3BK2<55YYALc1X={9yhH6|LTZGDdh`$pdY)OVy@Z8fl5cgoOXF6o!B zzV|#O+Kh#AWV~D`xBzXVwc0z@M$7mpF8M{Y7b*F{bg?Ik_d&SWKvNjh9#8j-MFaY? z%Y$jYsc*uhgp!0EJdILnhzYw*aeRb!K^^9U9=os&{5q=YV3{qhi<>CpQdSz&rJ!#- zoKA7~NAEs7IjPtXvItnwfZWpukIoX_-^LZ;tMt(sb;J8W-Bg4^P)&s+xvgQ;!{`EwQR;s8IGenG7s=|GA=aJl>~6o{1nKq`O9(tV&g zCgn-g(>5@{0yk2;n*bXjP=WTZ80wL>;XXoF37%(A!n}*;_?zXxzGuvx#}vwmQxU5A zqct}H9~8M&RJ>q_>}Re=XcnIR0WOzwo@NyEoLS5kb<-R$c}61WVu>S?T3E&9-a=vn zXDw-)KvlvV&_mk*YRJ^|O-u@(&@P|f%z+`TodY7vgB`t{U({<_JNw7_Tj+{*9;{yi z>zD8@gVelZvaGIM1uO-I%e{o@=c)xP_rI|NHAzC{xqPbYgigW@n{T#@X z$9}G|x(Xj$sUQYV9f)7#*K1DQc5HvUI35!cb$#Q?brB|fsq}r?k$vfv>p|4^=eS&E zG$1k4m^2G|(U>rEy77*oo9`Hz5!2KQ*#hlR`otA3G7LdaveEz$nCw|>sHf0^dV&en zDQ%e%Xo9FnAzo;76hjo~5q|q=CKeOYonT7TMiw29;>Blhxzk7rhG`Uwg`q+Qzr*;= z6tae1%tRNKAb3;Uq4*Wmqw6P+yR*35Ye=HS2OY(Zc_(WdPG&be@4Gd4({s4;=d`;9 zmK(Al;bMdfk#Fa)@CX(n#c&}q940NyFwWA-u zkEDk(OpWPTNMj!_&itE zT+ga3wAPR|;fcnpqtpBr^%kJtl0^j4w2%esAyaT@1Y|o+mV#TO)*M(9gwY7Z zf;wA`21t^+YTl!iVOS;TL_=JQbyokKp1NICbj2aRApzT&GXn*H7NpPY<4qI_O7`4=@n1 zPdEC>B+$=CF;vtinDkh3j_!ZP6{4IX0P)5{J*qv^gNnMWcm^NGpp0G&PBgI5Sn+j0 zye_6R@+rZS*W%LDgM&&vj!$}s^2cJ>DZ>31(q|yi^o{)~v;_!Nif);-7;P`G{VJ1g z$@mj75pgg7D~d&g92`hUTzt#KM0i3CBxWimCRU+9&wi31X?h?@Js)kEuxtdM1`_r_ zOjuH(1KR#QLEDjmwDo_tW%6QlH;}weC&nW9j|5eNJ25W4Wn!>;4c2c1iP@PdtN%>U z^Pw$CX|A-rXEMi9Ogu*1XYvi@_<63|YIS5@dgjG*&tG`PFFyOpx#wSe=IN&{Jfn`F z$zcBH@K+9#MJ7v3mYLL;tT5>e3(3iBegQB39#`N(G|Z8Gn7iZO`?(?D6VC1Ot5~{g zjbPvbZ3bm#5H=G}$-kUjD zZ&fRG_w-EoC7dinvOCT#T0hIDTo7MnlZuH5Zk0J{acWS_K&O!*F6d)f#l=2NQ`gTB z?#|+JzmMd927d^BzFn9{$Uy*p;6)uqp8K-&sE!~n-dN;Ek(WRM<8`r@@&$XT-j+q6y4bt0Mr40r~{p{*s_i%?{4Vy`BUv4 z^o09U2?R9|HBFy+GOn|Oc`gDM)ogf+YTmjPAvAyhZczz30jhA^YGu{Io+@0X!REsC zTD_i9ncdwVW`Up$~Xerzfw;2jiJi(MZGd!aO7=bh$%4fK z_szm^1%Y>ZJ0#2(|0~@UbQj4mE&7g4KJ7%BTLw3!rw$>El z4LTcQ9m*B}3W1pFYgpe{6dpF>)@7ToTUs696n#5=<|O*-RLKH%eV$u1fq;Td>XfeN z<0OfYqe@=|6ayN@&mrsO5V`ik)T8K^6g=8je^e*y3Q!^B%RM96Py&keL~y{Zgv;pY zNPD_@?Epnq*zRg(uqIA7Tg{RHmqF?Xb+FOh%9gGd!_!qaTRRjXSZs;42;~W`7$ReH zcMR+-R}jR2SGKc=9YClw0wgT#tEbe|84@8HW=G>wrz!hz+-mD)oCE}&j5Q9rx%1Q4 z;lgOJg-7iTZi{_Hr1kijUwnKvHKUj35w#IOEW>XbQrG= zA^Je}tkY_bK27{R#4U<}->~4T$I6#xF85Q*chi;jLc7{l)pn)6x{Mn*Q`@MJ*R`5+ zy<3O)1%KYHMq#D1f($;etWtmb;5>Sp_zQkoSoIAO0!!kpne(miCo0+Se8F$8E?2p8y5^a^zK8lyl&<0Jh}smE)z=yRBU!o#X8*G1EIb}otyakf6eYBSd;88$qw~4 z8;`>??=rZdZ?r{eqr1ENwlaX80=Sb{v>1H30ni8lXa!!e1&jxTvn(PM38N`}h_?Q*6-P z)Pa2?HBG&Zk*O2(d z&OEDL;?tLze2&R0Oy-%qio_qPsD&CL#?*SLaNqd+DRqgjE;D(JNtwy7GpQiCpTTmh z%c(_A4BaD7<8m3sfmi^I+v;}^dT(cLAz%Xz75y$QTeHnC8;lTOM3kNVsD{59c3rT` zCT3$J$Aj)$Y!U#u>ek0+X64y%MWWCZ@uq&r;p^cxQW^H3O_A}6r9r%hnvh6r? zqA%Zm2S4|XnZtqLD9lpMH&b2gMmi zVksMW@pSvSz;O1`y(5LRYxD+j%UT;Y;aoHIoSyqRHUYD_pBe9%#ey+~?ZAx(-<7?t zj?SPecD8gh-BE2L5W9N8lYL`4-4I2Aon_l#H{;&$GU)zzZ^70OwgpAtTa;y(8+>n< zj7@}gHK$Mu-eEV|SjoG~ojR!++zdc>s#|FH?Vm%$h;u7oBUSoRqB9_ywS{`Es@_Bq z#T^SjQ+Jw-ZL7pPrhZnYt2B?j_%Xjhp)nLi%M^`bW;{ER9XH3ZznH@=>c&)xuw)rJ zSWdE~!3_=YaMz$xikG*f2X50UX%+vTBve9irGAfe(9elj|9vT~4&EeSFG&w^Zyml( z^wLfJO0-3Qkb~Hj+1oC?x8F~+doZQl*smS9===CiZ#~`z_$Hc2l|7xtKS;Fwp_I0_ z;OUQ>KZ*JR)}c;RAM~mOG#D$odjdfYx;nw|pA`s)<@ooCp-!+2gFf$N=FVS4)UF7N zyZ8Rc0>DHxMpJp9&-+K@fqkx-++#O$Bl@InW>fnxmgQh6(g1g{VQ!rbFqe@a%J~#V z=OaedZ=(s=88YgRF_Hu3G6buNfi3DAOsY(J^px)Xe;~gyUXuKp#enOF-lG=>Gft~c zvTq{(^KK{t=Hfj;ILKv)V?19+$Z`sOi5<9jhWlx(Vu+DUAucZ1HQ!LHV$FIHH;4~G zY!Kp8$C;C`LmftprVINI*EBVUzc5+qEKDTkz`Htg(dwGE zA~Ubdw=(mtqbaq)L|)MJsjnircphaRP#9;noL?uI=fEX*HB+!^6pztzsDl%uOL`SVof^2kenD?27=(crRLIVAh_gm*LD;) zrhb|mMsUeqTnD2dlko2p{_Za@^kg@p-C5Jd{@12MkJmInUgWeZh0h-DQZ3G>SzIE? zv&bNTNjAUH%4@sd%IMH3{p3R!5<^DgkJ+8XJ7~LA;gJtaIlR?8{kB+1qP!xz>v3K z2jVyQrY(rlHVH6nEx?n(H<<2B;L6@N1`sAN<`MvhZFWi!mj-30w425xT9;b7%Z4R7 zUv?kwWmfvPPndw!8OICKDr>krGL;HH=5ucN+4sAL?bh`7$| z)%VJER6lAczOC{_@+X6vv$$N^$arUSe|Vw<%MG4D#mSQ3L`gP0QIZP-x$ zm{<^4*ERW3xZIhQVM6N{oTbI+Mlc#JfnaO>CKpV!3nwmA-^9>Z zzZk^H%iC=9_7%K6jtiJOgJTmoTp~wI3SrPUw#Sq0v-Y1whZg z-!QH+Xn`FBI6I3!_YB{dIqvIjPjC9glU(_5*>w73q*WWGq)g(IAxVXfzPYa-Ee)w} zp#>bxaG+lm+ZJ0ZVf+#xfGu>@+Q8vxyw1s?7FVW7%#?&DSowvUTFMOrF@xPve<*&@ zL$m}pevB$86J=%+F_Z;N2AC-IU74bpm?+VwG5x8Mly0SUjgdp@$rf}bI-1rF7Q~!W zzk)A$kJGo=g05MInfG{I`mP=pqPo1{qQ6HWGZNy_ONij$YL$)Q1E%ITTO zAes*=>M?o7(+vkbM6`GY?1zD=EIcK1j>=|~agb^S{|N=6!9RyJ19N(i!@FGbWcU`~ zCVZLm5eKjU3*16ZN|Z4R-m-O3;qW<+ zXP!rFj5vs+9gr5{AQZOE-5Jb15{;7syXsGwoMG}8Or$$G6#U{#JjnixQY{sMVJ;`s zUoq((6FggwHp}J96uyN5Jlw-y)5z%)#w2pQMzHz^415PGxn6CM&$}QG)h6zl^SDXr znMdRq99-(C#~y*SXyFq*_N0fUK}WiwCf&>TO5jm6AWNY@79xh-eAdmW9AWavWq{fO zE(N(68#|KyfgzN7aOs0)DGs6hKB-M3nTF=`TO>L4C^~yW#z*>?BxV^nCaD^5AC=3u zNdaq0F$GfKeVPKFXQI{Mc6q9jfxqRiBpU8D2tkRymg7E}0l83~zE!Hbmv)vXQ3Y4S zNClP~!xWKnv}4f^Ip!rMn^P!E_6Q-siq>PW;Zu@{C&gf^@8QGmpqc==9_iAv#OgBL zT+75pg~o*6Tu-&tZ1^q8N#-wh zZLF4Hl7V2d7=G0P~;gfp-xNU8uc)&tq6b zMU{g`iBnZ@GkyfZBx2vi_4^7OM1k|i*1raa(bc^?ZOB7QxPn7UFKp&8ALP8Omy_;$ z&C9oQm>cpNXB6-EN!iH{01eL*a3yb2z$`$h+TdXVrH@ z+K|V*0^lylAKn7?PpKG)j6A4=NPLt3ze?f+09oxgnF5DF?-{0Gi=q&m9|FR9p5KTY z;j_$%>?IM|vzZ@J_J@&yyA*yXIN8N<$b(A-^hVJzGdOEYzmz^=jF{u}PjydLsfU#& zdYwv7uzlj+#5twE;cfhXBB;OR?cXu!@fdMXDvJpzPH@p-g;3-KSz$4px7rz=P1;>3 z;ulfOa1V`#r;_#xa49{=|0im34gdKN{tp#}Z#Bi?t2mC;Atp4u!2+A>K}<)%u2XP^ zInS3AT%h!#{-XJR&1b{%!Bgj+{tQCI{9N$=+{k~$AV;EP!6eba!6Hf=ZNJYC-(>Q2 zCW5XyJr?uo7fuHMyVYq@>OO*G5(oI?*BI9)Gvm3b6XRddGUJaGiun5lZ5)TOh6@w_ E4I_=~wg3PC literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/tags.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/tags.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54c03b59e32e7ebda0deb4ebe134f250abf581a4 GIT binary patch literal 10854 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 Bj&lG2 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/utils.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__pycache__/utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..01810314a7f482371bc1502cd39f671833fa4190 GIT binary patch literal 1489 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 K+{wI=8~%R{>}Pra literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_compat.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_compat.py new file mode 100644 index 0000000..25da473 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_compat.py @@ -0,0 +1,31 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import sys + + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +# flake8: noqa + +if PY3: + string_types = (str,) +else: + string_types = (basestring,) + + +def with_metaclass(meta, *bases): + """ + Create a base class with a metaclass. + """ + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + + return type.__new__(metaclass, "temporary_class", (), {}) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_structures.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_structures.py new file mode 100644 index 0000000..68dcca6 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_structures.py @@ -0,0 +1,68 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + + +class Infinity(object): + def __repr__(self): + return "Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return False + + def __le__(self, other): + return False + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return True + + def __ge__(self, other): + return True + + def __neg__(self): + return NegativeInfinity + + +Infinity = Infinity() + + +class NegativeInfinity(object): + def __repr__(self): + return "-Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return True + + def __le__(self, other): + return True + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return False + + def __ge__(self, other): + return False + + def __neg__(self): + return Infinity + + +NegativeInfinity = NegativeInfinity() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/markers.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/markers.py new file mode 100644 index 0000000..4bdfdb2 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/markers.py @@ -0,0 +1,296 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import operator +import os +import platform +import sys + +from setuptools.extern.pyparsing import ParseException, ParseResults, stringStart, stringEnd +from setuptools.extern.pyparsing import ZeroOrMore, Group, Forward, QuotedString +from setuptools.extern.pyparsing import Literal as L # noqa + +from ._compat import string_types +from .specifiers import Specifier, InvalidSpecifier + + +__all__ = [ + "InvalidMarker", + "UndefinedComparison", + "UndefinedEnvironmentName", + "Marker", + "default_environment", +] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +class Node(object): + def __init__(self, value): + self.value = value + + def __str__(self): + return str(self.value) + + def __repr__(self): + return "<{0}({1!r})>".format(self.__class__.__name__, str(self)) + + def serialize(self): + raise NotImplementedError + + +class Variable(Node): + def serialize(self): + return str(self) + + +class Value(Node): + def serialize(self): + return '"{0}"'.format(self) + + +class Op(Node): + def serialize(self): + return str(self) + + +VARIABLE = ( + L("implementation_version") + | L("platform_python_implementation") + | L("implementation_name") + | L("python_full_version") + | L("platform_release") + | L("platform_version") + | L("platform_machine") + | L("platform_system") + | L("python_version") + | L("sys_platform") + | L("os_name") + | L("os.name") + | L("sys.platform") # PEP-345 + | L("platform.version") # PEP-345 + | L("platform.machine") # PEP-345 + | L("platform.python_implementation") # PEP-345 + | L("python_implementation") # PEP-345 + | L("extra") # undocumented setuptools legacy +) +ALIASES = { + "os.name": "os_name", + "sys.platform": "sys_platform", + "platform.version": "platform_version", + "platform.machine": "platform_machine", + "platform.python_implementation": "platform_python_implementation", + "python_implementation": "platform_python_implementation", +} +VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) + +VERSION_CMP = ( + L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<") +) + +MARKER_OP = VERSION_CMP | L("not in") | L("in") +MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) + +MARKER_VALUE = QuotedString("'") | QuotedString('"') +MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) + +BOOLOP = L("and") | L("or") + +MARKER_VAR = VARIABLE | MARKER_VALUE + +MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) +MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) + +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() + +MARKER_EXPR = Forward() +MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) +MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) + +MARKER = stringStart + MARKER_EXPR + stringEnd + + +def _coerce_parse_result(results): + if isinstance(results, ParseResults): + return [_coerce_parse_result(i) for i in results] + else: + return results + + +def _format_marker(marker, first=True): + assert isinstance(marker, (list, tuple, string_types)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if ( + isinstance(marker, list) + and len(marker) == 1 + and isinstance(marker[0], (list, tuple)) + ): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs, op, rhs): + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs) + + oper = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison( + "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs) + ) + + return oper(lhs, rhs) + + +_undefined = object() + + +def _get_env(environment, name): + value = environment.get(name, _undefined) + + if value is _undefined: + raise UndefinedEnvironmentName( + "{0!r} does not exist in evaluation environment.".format(name) + ) + + return value + + +def _evaluate_markers(markers, environment): + groups = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, string_types)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + lhs_value = _get_env(environment, lhs.value) + rhs_value = rhs.value + else: + lhs_value = lhs.value + rhs_value = _get_env(environment, rhs.value) + + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info): + version = "{0.major}.{0.minor}.{0.micro}".format(info) + kind = info.releaselevel + if kind != "final": + version += kind[0] + str(info.serial) + return version + + +def default_environment(): + if hasattr(sys, "implementation"): + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + iver = "0" + implementation_name = "" + + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": ".".join(platform.python_version_tuple()[:2]), + "sys_platform": sys.platform, + } + + +class Marker(object): + def __init__(self, marker): + try: + self._markers = _coerce_parse_result(MARKER.parseString(marker)) + except ParseException as e: + err_str = "Invalid marker: {0!r}, parse error at {1!r}".format( + marker, marker[e.loc : e.loc + 8] + ) + raise InvalidMarker(err_str) + + def __str__(self): + return _format_marker(self._markers) + + def __repr__(self): + return "".format(str(self)) + + def evaluate(self, environment=None): + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = default_environment() + if environment is not None: + current_environment.update(environment) + + return _evaluate_markers(self._markers, current_environment) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/requirements.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/requirements.py new file mode 100644 index 0000000..8a0c2cb --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/requirements.py @@ -0,0 +1,138 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import string +import re + +from setuptools.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException +from setuptools.extern.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine +from setuptools.extern.pyparsing import Literal as L # noqa +from setuptools.extern.six.moves.urllib import parse as urlparse + +from .markers import MARKER_EXPR, Marker +from .specifiers import LegacySpecifier, Specifier, SpecifierSet + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +ALPHANUM = Word(string.ascii_letters + string.digits) + +LBRACKET = L("[").suppress() +RBRACKET = L("]").suppress() +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() +COMMA = L(",").suppress() +SEMICOLON = L(";").suppress() +AT = L("@").suppress() + +PUNCTUATION = Word("-_.") +IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM) +IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END)) + +NAME = IDENTIFIER("name") +EXTRA = IDENTIFIER + +URI = Regex(r"[^ ]+")("url") +URL = AT + URI + +EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA) +EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras") + +VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE) +VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE) + +VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY +VERSION_MANY = Combine( + VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), joinString=",", adjacent=False +)("_raw_spec") +_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY)) +_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or "") + +VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier") +VERSION_SPEC.setParseAction(lambda s, l, t: t[1]) + +MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") +MARKER_EXPR.setParseAction( + lambda s, l, t: Marker(s[t._original_start : t._original_end]) +) +MARKER_SEPARATOR = SEMICOLON +MARKER = MARKER_SEPARATOR + MARKER_EXPR + +VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) +URL_AND_MARKER = URL + Optional(MARKER) + +NAMED_REQUIREMENT = NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER) + +REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd +# setuptools.extern.pyparsing isn't thread safe during initialization, so we do it eagerly, see +# issue #104 +REQUIREMENT.parseString("x[]") + + +class Requirement(object): + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string): + try: + req = REQUIREMENT.parseString(requirement_string) + except ParseException as e: + raise InvalidRequirement( + 'Parse error at "{0!r}": {1}'.format( + requirement_string[e.loc : e.loc + 8], e.msg + ) + ) + + self.name = req.name + if req.url: + parsed_url = urlparse.urlparse(req.url) + if parsed_url.scheme == "file": + if urlparse.urlunparse(parsed_url) != req.url: + raise InvalidRequirement("Invalid URL given") + elif not (parsed_url.scheme and parsed_url.netloc) or ( + not parsed_url.scheme and not parsed_url.netloc + ): + raise InvalidRequirement("Invalid URL: {0}".format(req.url)) + self.url = req.url + else: + self.url = None + self.extras = set(req.extras.asList() if req.extras else []) + self.specifier = SpecifierSet(req.specifier) + self.marker = req.marker if req.marker else None + + def __str__(self): + parts = [self.name] + + if self.extras: + parts.append("[{0}]".format(",".join(sorted(self.extras)))) + + if self.specifier: + parts.append(str(self.specifier)) + + if self.url: + parts.append("@ {0}".format(self.url)) + if self.marker: + parts.append(" ") + + if self.marker: + parts.append("; {0}".format(self.marker)) + + return "".join(parts) + + def __repr__(self): + return "".format(str(self)) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/specifiers.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/specifiers.py new file mode 100644 index 0000000..743576a --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/specifiers.py @@ -0,0 +1,749 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import abc +import functools +import itertools +import re + +from ._compat import string_types, with_metaclass +from .version import Version, LegacyVersion, parse + + +class InvalidSpecifier(ValueError): + """ + An invalid specifier was found, users should refer to PEP 440. + """ + + +class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): + @abc.abstractmethod + def __str__(self): + """ + Returns the str representation of this Specifier like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self): + """ + Returns a hash value for this Specifier like object. + """ + + @abc.abstractmethod + def __eq__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are equal. + """ + + @abc.abstractmethod + def __ne__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are not equal. + """ + + @abc.abstractproperty + def prereleases(self): + """ + Returns whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @prereleases.setter + def prereleases(self, value): + """ + Sets whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @abc.abstractmethod + def contains(self, item, prereleases=None): + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter(self, iterable, prereleases=None): + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class _IndividualSpecifier(BaseSpecifier): + + _operators = {} + + def __init__(self, spec="", prereleases=None): + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec)) + + self._spec = (match.group("operator").strip(), match.group("version").strip()) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<{0}({1!r}{2})>".format(self.__class__.__name__, str(self), pre) + + def __str__(self): + return "{0}{1}".format(*self._spec) + + def __hash__(self): + return hash(self._spec) + + def __eq__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec == other._spec + + def __ne__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec != other._spec + + def _get_operator(self, op): + return getattr(self, "_compare_{0}".format(self._operators[op])) + + def _coerce_version(self, version): + if not isinstance(version, (LegacyVersion, Version)): + version = parse(version) + return version + + @property + def operator(self): + return self._spec[0] + + @property + def version(self): + return self._spec[1] + + @property + def prereleases(self): + return self._prereleases + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version or LegacyVersion, this allows us to have + # a shortcut for ``"2.0" in Specifier(">=2") + item = self._coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + return self._get_operator(self.operator)(item, self.version) + + def filter(self, iterable, prereleases=None): + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = self._coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later incase nothing + # else matches this specifier. + if parsed_version.is_prerelease and not ( + prereleases or self.prereleases + ): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the beginning. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +class LegacySpecifier(_IndividualSpecifier): + + _regex_str = r""" + (?P(==|!=|<=|>=|<|>)) + \s* + (?P + [^,;\s)]* # Since this is a "legacy" specifier, and the version + # string can be just about anything, we match everything + # except for whitespace, a semi-colon for marker support, + # a closing paren since versions can be enclosed in + # them, and a comma since it's a version separator. + ) + """ + + _regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + } + + def _coerce_version(self, version): + if not isinstance(version, LegacyVersion): + version = LegacyVersion(str(version)) + return version + + def _compare_equal(self, prospective, spec): + return prospective == self._coerce_version(spec) + + def _compare_not_equal(self, prospective, spec): + return prospective != self._coerce_version(spec) + + def _compare_less_than_equal(self, prospective, spec): + return prospective <= self._coerce_version(spec) + + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= self._coerce_version(spec) + + def _compare_less_than(self, prospective, spec): + return prospective < self._coerce_version(spec) + + def _compare_greater_than(self, prospective, spec): + return prospective > self._coerce_version(spec) + + +def _require_version_compare(fn): + @functools.wraps(fn) + def wrapped(self, prospective, spec): + if not isinstance(prospective, Version): + return False + return fn(self, prospective, spec) + + return wrapped + + +class Specifier(_IndividualSpecifier): + + _regex_str = r""" + (?P(~=|==|!=|<=|>=|<|>|===)) + (?P + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s]* # We just match everything, except for whitespace + # since we are only testing for strict identity. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + + # You cannot use a wild card and a dev or local version + # together so group them with a | and make them optional. + (?: + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + | + \.\* # Wild card syntax of .* + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + @_require_version_compare + def _compare_compatible(self, prospective, spec): + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore post and dev releases and we want to treat the pre-release as + # it's own separate segment. + prefix = ".".join( + list( + itertools.takewhile( + lambda x: (not x.startswith("post") and not x.startswith("dev")), + _version_split(spec), + ) + )[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return self._get_operator(">=")(prospective, spec) and self._get_operator("==")( + prospective, prefix + ) + + @_require_version_compare + def _compare_equal(self, prospective, spec): + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + prospective = Version(prospective.public) + # Split the spec out by dots, and pretend that there is an implicit + # dot in between a release segment and a pre-release segment. + spec = _version_split(spec[:-2]) # Remove the trailing .* + + # Split the prospective version out by dots, and pretend that there + # is an implicit dot in between a release segment and a pre-release + # segment. + prospective = _version_split(str(prospective)) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + prospective = prospective[: len(spec)] + + # Pad out our two sides with zeros so that they both equal the same + # length. + spec, prospective = _pad_version(spec, prospective) + else: + # Convert our spec string into a Version + spec = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec.local: + prospective = Version(prospective.public) + + return prospective == spec + + @_require_version_compare + def _compare_not_equal(self, prospective, spec): + return not self._compare_equal(prospective, spec) + + @_require_version_compare + def _compare_less_than_equal(self, prospective, spec): + return prospective <= Version(spec) + + @_require_version_compare + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= Version(spec) + + @_require_version_compare + def _compare_less_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + @_require_version_compare + def _compare_greater_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is technically greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective, spec): + return str(prospective).lower() == str(spec).lower() + + @property + def prereleases(self): + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "==="]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if parse(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version): + result = [] + for item in version.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _pad_version(left, right): + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]) :]) + right_split.append(right[len(right_split[0]) :]) + + # Insert our padding + left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0]))) + right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0]))) + + return (list(itertools.chain(*left_split)), list(itertools.chain(*right_split))) + + +class SpecifierSet(BaseSpecifier): + def __init__(self, specifiers="", prereleases=None): + # Split on , to break each indidivual specifier into it's own item, and + # strip each item to remove leading/trailing whitespace. + specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Parsed each individual specifier, attempting first to make it a + # Specifier and falling back to a LegacySpecifier. + parsed = set() + for specifier in specifiers: + try: + parsed.add(Specifier(specifier)) + except InvalidSpecifier: + parsed.add(LegacySpecifier(specifier)) + + # Turn our parsed specifiers into a frozen set and save them for later. + self._specs = frozenset(parsed) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "".format(str(self), pre) + + def __str__(self): + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self): + return hash(self._specs) + + def __and__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __ne__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs != other._specs + + def __len__(self): + return len(self._specs) + + def __iter__(self): + return iter(self._specs) + + @property + def prereleases(self): + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Ensure that our item is a Version or LegacyVersion instance. + if not isinstance(item, (LegacyVersion, Version)): + item = parse(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all(s.contains(item, prereleases=prereleases) for s in self._specs) + + def filter(self, iterable, prereleases=None): + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iterable + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases, and which will filter out LegacyVersion in general. + else: + filtered = [] + found_prereleases = [] + + for item in iterable: + # Ensure that we some kind of Version class for this item. + if not isinstance(item, (LegacyVersion, Version)): + parsed_version = parse(item) + else: + parsed_version = item + + # Filter out any item which is parsed as a LegacyVersion + if isinstance(parsed_version, LegacyVersion): + continue + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return found_prereleases + + return filtered diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/tags.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/tags.py new file mode 100644 index 0000000..ec9942f --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/tags.py @@ -0,0 +1,404 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import + +import distutils.util + +try: + from importlib.machinery import EXTENSION_SUFFIXES +except ImportError: # pragma: no cover + import imp + + EXTENSION_SUFFIXES = [x[0] for x in imp.get_suffixes()] + del imp +import platform +import re +import sys +import sysconfig +import warnings + + +INTERPRETER_SHORT_NAMES = { + "python": "py", # Generic. + "cpython": "cp", + "pypy": "pp", + "ironpython": "ip", + "jython": "jy", +} + + +_32_BIT_INTERPRETER = sys.maxsize <= 2 ** 32 + + +class Tag(object): + + __slots__ = ["_interpreter", "_abi", "_platform"] + + def __init__(self, interpreter, abi, platform): + self._interpreter = interpreter.lower() + self._abi = abi.lower() + self._platform = platform.lower() + + @property + def interpreter(self): + return self._interpreter + + @property + def abi(self): + return self._abi + + @property + def platform(self): + return self._platform + + def __eq__(self, other): + return ( + (self.platform == other.platform) + and (self.abi == other.abi) + and (self.interpreter == other.interpreter) + ) + + def __hash__(self): + return hash((self._interpreter, self._abi, self._platform)) + + def __str__(self): + return "{}-{}-{}".format(self._interpreter, self._abi, self._platform) + + def __repr__(self): + return "<{self} @ {self_id}>".format(self=self, self_id=id(self)) + + +def parse_tag(tag): + tags = set() + interpreters, abis, platforms = tag.split("-") + for interpreter in interpreters.split("."): + for abi in abis.split("."): + for platform_ in platforms.split("."): + tags.add(Tag(interpreter, abi, platform_)) + return frozenset(tags) + + +def _normalize_string(string): + return string.replace(".", "_").replace("-", "_") + + +def _cpython_interpreter(py_version): + # TODO: Is using py_version_nodot for interpreter version critical? + return "cp{major}{minor}".format(major=py_version[0], minor=py_version[1]) + + +def _cpython_abis(py_version): + abis = [] + version = "{}{}".format(*py_version[:2]) + debug = pymalloc = ucs4 = "" + with_debug = sysconfig.get_config_var("Py_DEBUG") + has_refcount = hasattr(sys, "gettotalrefcount") + # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled + # extension modules is the best option. + # https://github.com/pypa/pip/issues/3383#issuecomment-173267692 + has_ext = "_d.pyd" in EXTENSION_SUFFIXES + if with_debug or (with_debug is None and (has_refcount or has_ext)): + debug = "d" + if py_version < (3, 8): + with_pymalloc = sysconfig.get_config_var("WITH_PYMALLOC") + if with_pymalloc or with_pymalloc is None: + pymalloc = "m" + if py_version < (3, 3): + unicode_size = sysconfig.get_config_var("Py_UNICODE_SIZE") + if unicode_size == 4 or ( + unicode_size is None and sys.maxunicode == 0x10FFFF + ): + ucs4 = "u" + elif debug: + # Debug builds can also load "normal" extension modules. + # We can also assume no UCS-4 or pymalloc requirement. + abis.append("cp{version}".format(version=version)) + abis.insert( + 0, + "cp{version}{debug}{pymalloc}{ucs4}".format( + version=version, debug=debug, pymalloc=pymalloc, ucs4=ucs4 + ), + ) + return abis + + +def _cpython_tags(py_version, interpreter, abis, platforms): + for abi in abis: + for platform_ in platforms: + yield Tag(interpreter, abi, platform_) + for tag in (Tag(interpreter, "abi3", platform_) for platform_ in platforms): + yield tag + for tag in (Tag(interpreter, "none", platform_) for platform_ in platforms): + yield tag + # PEP 384 was first implemented in Python 3.2. + for minor_version in range(py_version[1] - 1, 1, -1): + for platform_ in platforms: + interpreter = "cp{major}{minor}".format( + major=py_version[0], minor=minor_version + ) + yield Tag(interpreter, "abi3", platform_) + + +def _pypy_interpreter(): + return "pp{py_major}{pypy_major}{pypy_minor}".format( + py_major=sys.version_info[0], + pypy_major=sys.pypy_version_info.major, + pypy_minor=sys.pypy_version_info.minor, + ) + + +def _generic_abi(): + abi = sysconfig.get_config_var("SOABI") + if abi: + return _normalize_string(abi) + else: + return "none" + + +def _pypy_tags(py_version, interpreter, abi, platforms): + for tag in (Tag(interpreter, abi, platform) for platform in platforms): + yield tag + for tag in (Tag(interpreter, "none", platform) for platform in platforms): + yield tag + + +def _generic_tags(interpreter, py_version, abi, platforms): + for tag in (Tag(interpreter, abi, platform) for platform in platforms): + yield tag + if abi != "none": + tags = (Tag(interpreter, "none", platform_) for platform_ in platforms) + for tag in tags: + yield tag + + +def _py_interpreter_range(py_version): + """ + Yield Python versions in descending order. + + After the latest version, the major-only version will be yielded, and then + all following versions up to 'end'. + """ + yield "py{major}{minor}".format(major=py_version[0], minor=py_version[1]) + yield "py{major}".format(major=py_version[0]) + for minor in range(py_version[1] - 1, -1, -1): + yield "py{major}{minor}".format(major=py_version[0], minor=minor) + + +def _independent_tags(interpreter, py_version, platforms): + """ + Return the sequence of tags that are consistent across implementations. + + The tags consist of: + - py*-none- + - -none-any + - py*-none-any + """ + for version in _py_interpreter_range(py_version): + for platform_ in platforms: + yield Tag(version, "none", platform_) + yield Tag(interpreter, "none", "any") + for version in _py_interpreter_range(py_version): + yield Tag(version, "none", "any") + + +def _mac_arch(arch, is_32bit=_32_BIT_INTERPRETER): + if not is_32bit: + return arch + + if arch.startswith("ppc"): + return "ppc" + + return "i386" + + +def _mac_binary_formats(version, cpu_arch): + formats = [cpu_arch] + if cpu_arch == "x86_64": + if version < (10, 4): + return [] + formats.extend(["intel", "fat64", "fat32"]) + + elif cpu_arch == "i386": + if version < (10, 4): + return [] + formats.extend(["intel", "fat32", "fat"]) + + elif cpu_arch == "ppc64": + # TODO: Need to care about 32-bit PPC for ppc64 through 10.2? + if version > (10, 5) or version < (10, 4): + return [] + formats.append("fat64") + + elif cpu_arch == "ppc": + if version > (10, 6): + return [] + formats.extend(["fat32", "fat"]) + + formats.append("universal") + return formats + + +def _mac_platforms(version=None, arch=None): + version_str, _, cpu_arch = platform.mac_ver() + if version is None: + version = tuple(map(int, version_str.split(".")[:2])) + if arch is None: + arch = _mac_arch(cpu_arch) + platforms = [] + for minor_version in range(version[1], -1, -1): + compat_version = version[0], minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + platforms.append( + "macosx_{major}_{minor}_{binary_format}".format( + major=compat_version[0], + minor=compat_version[1], + binary_format=binary_format, + ) + ) + return platforms + + +# From PEP 513. +def _is_manylinux_compatible(name, glibc_version): + # Check for presence of _manylinux module. + try: + import _manylinux + + return bool(getattr(_manylinux, name + "_compatible")) + except (ImportError, AttributeError): + # Fall through to heuristic check below. + pass + + return _have_compatible_glibc(*glibc_version) + + +def _glibc_version_string(): + # Returns glibc version string, or None if not using glibc. + import ctypes + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + process_namespace = ctypes.CDLL(None) + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +# Separated out from have_compatible_glibc for easier unit testing. +def _check_glibc_version(version_str, required_major, minimum_minor): + # Parse string and check against requested version. + # + # We use a regexp instead of str.split because we want to discard any + # random junk that might come after the minor version -- this might happen + # in patched/forked versions of glibc (e.g. Linaro's version of glibc + # uses version strings like "2.20-2014.11"). See gh-3588. + m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str) + if not m: + warnings.warn( + "Expected glibc version with 2 components major.minor," + " got: %s" % version_str, + RuntimeWarning, + ) + return False + return ( + int(m.group("major")) == required_major + and int(m.group("minor")) >= minimum_minor + ) + + +def _have_compatible_glibc(required_major, minimum_minor): + version_str = _glibc_version_string() + if version_str is None: + return False + return _check_glibc_version(version_str, required_major, minimum_minor) + + +def _linux_platforms(is_32bit=_32_BIT_INTERPRETER): + linux = _normalize_string(distutils.util.get_platform()) + if linux == "linux_x86_64" and is_32bit: + linux = "linux_i686" + manylinux_support = ( + ("manylinux2014", (2, 17)), # CentOS 7 w/ glibc 2.17 (PEP 599) + ("manylinux2010", (2, 12)), # CentOS 6 w/ glibc 2.12 (PEP 571) + ("manylinux1", (2, 5)), # CentOS 5 w/ glibc 2.5 (PEP 513) + ) + manylinux_support_iter = iter(manylinux_support) + for name, glibc_version in manylinux_support_iter: + if _is_manylinux_compatible(name, glibc_version): + platforms = [linux.replace("linux", name)] + break + else: + platforms = [] + # Support for a later manylinux implies support for an earlier version. + platforms += [linux.replace("linux", name) for name, _ in manylinux_support_iter] + platforms.append(linux) + return platforms + + +def _generic_platforms(): + platform = _normalize_string(distutils.util.get_platform()) + return [platform] + + +def _interpreter_name(): + name = platform.python_implementation().lower() + return INTERPRETER_SHORT_NAMES.get(name) or name + + +def _generic_interpreter(name, py_version): + version = sysconfig.get_config_var("py_version_nodot") + if not version: + version = "".join(map(str, py_version[:2])) + return "{name}{version}".format(name=name, version=version) + + +def sys_tags(): + """ + Returns the sequence of tag triples for the running interpreter. + + The order of the sequence corresponds to priority order for the + interpreter, from most to least important. + """ + py_version = sys.version_info[:2] + interpreter_name = _interpreter_name() + if platform.system() == "Darwin": + platforms = _mac_platforms() + elif platform.system() == "Linux": + platforms = _linux_platforms() + else: + platforms = _generic_platforms() + + if interpreter_name == "cp": + interpreter = _cpython_interpreter(py_version) + abis = _cpython_abis(py_version) + for tag in _cpython_tags(py_version, interpreter, abis, platforms): + yield tag + elif interpreter_name == "pp": + interpreter = _pypy_interpreter() + abi = _generic_abi() + for tag in _pypy_tags(py_version, interpreter, abi, platforms): + yield tag + else: + interpreter = _generic_interpreter(interpreter_name, py_version) + abi = _generic_abi() + for tag in _generic_tags(interpreter, py_version, abi, platforms): + yield tag + for tag in _independent_tags(interpreter, py_version, platforms): + yield tag diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/utils.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/utils.py new file mode 100644 index 0000000..8841878 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/utils.py @@ -0,0 +1,57 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import re + +from .version import InvalidVersion, Version + + +_canonicalize_regex = re.compile(r"[-_.]+") + + +def canonicalize_name(name): + # This is taken from PEP 503. + return _canonicalize_regex.sub("-", name).lower() + + +def canonicalize_version(version): + """ + This is very similar to Version.__str__, but has one subtle differences + with the way it handles the release segment. + """ + + try: + version = Version(version) + except InvalidVersion: + # Legacy versions cannot be normalized + return version + + parts = [] + + # Epoch + if version.epoch != 0: + parts.append("{0}!".format(version.epoch)) + + # Release segment + # NB: This strips trailing '.0's to normalize + parts.append(re.sub(r"(\.0)+$", "", ".".join(str(x) for x in version.release))) + + # Pre-release + if version.pre is not None: + parts.append("".join(str(x) for x in version.pre)) + + # Post-release + if version.post is not None: + parts.append(".post{0}".format(version.post)) + + # Development release + if version.dev is not None: + parts.append(".dev{0}".format(version.dev)) + + # Local version segment + if version.local is not None: + parts.append("+{0}".format(version.local)) + + return "".join(parts) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/version.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/version.py new file mode 100644 index 0000000..95157a1 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/packaging/version.py @@ -0,0 +1,420 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import collections +import itertools +import re + +from ._structures import Infinity + + +__all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"] + + +_Version = collections.namedtuple( + "_Version", ["epoch", "release", "dev", "pre", "post", "local"] +) + + +def parse(version): + """ + Parse the given version string and return either a :class:`Version` object + or a :class:`LegacyVersion` object depending on if the given version is + a valid PEP 440 version or a legacy version. + """ + try: + return Version(version) + except InvalidVersion: + return LegacyVersion(version) + + +class InvalidVersion(ValueError): + """ + An invalid version was found, users should refer to PEP 440. + """ + + +class _BaseVersion(object): + def __hash__(self): + return hash(self._key) + + def __lt__(self, other): + return self._compare(other, lambda s, o: s < o) + + def __le__(self, other): + return self._compare(other, lambda s, o: s <= o) + + def __eq__(self, other): + return self._compare(other, lambda s, o: s == o) + + def __ge__(self, other): + return self._compare(other, lambda s, o: s >= o) + + def __gt__(self, other): + return self._compare(other, lambda s, o: s > o) + + def __ne__(self, other): + return self._compare(other, lambda s, o: s != o) + + def _compare(self, other, method): + if not isinstance(other, _BaseVersion): + return NotImplemented + + return method(self._key, other._key) + + +class LegacyVersion(_BaseVersion): + def __init__(self, version): + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + def __str__(self): + return self._version + + def __repr__(self): + return "".format(repr(str(self))) + + @property + def public(self): + return self._version + + @property + def base_version(self): + return self._version + + @property + def epoch(self): + return -1 + + @property + def release(self): + return None + + @property + def pre(self): + return None + + @property + def post(self): + return None + + @property + def dev(self): + return None + + @property + def local(self): + return None + + @property + def is_prerelease(self): + return False + + @property + def is_postrelease(self): + return False + + @property + def is_devrelease(self): + return False + + +_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE) + +_legacy_version_replacement_map = { + "pre": "c", + "preview": "c", + "-": "final-", + "rc": "c", + "dev": "@", +} + + +def _parse_version_parts(s): + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version): + # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # it's adoption of the packaging library. + parts = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + parts = tuple(parts) + + return epoch, parts + + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +VERSION_PATTERN = r""" + v? + (?: + (?:(?P[0-9]+)!)? # epoch + (?P[0-9]+(?:\.[0-9]+)*) # release segment + (?P

                                          # pre-release
+            [-_\.]?
+            (?P(a|b|c|rc|alpha|beta|pre|preview))
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+        (?P                                         # post release
+            (?:-(?P[0-9]+))
+            |
+            (?:
+                [-_\.]?
+                (?Ppost|rev|r)
+                [-_\.]?
+                (?P[0-9]+)?
+            )
+        )?
+        (?P                                          # dev release
+            [-_\.]?
+            (?Pdev)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+    )
+    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
+"""
+
+
+class Version(_BaseVersion):
+
+    _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
+
+    def __init__(self, version):
+        # Validate the version and parse it into pieces
+        match = self._regex.search(version)
+        if not match:
+            raise InvalidVersion("Invalid version: '{0}'".format(version))
+
+        # Store the parsed out pieces of the version
+        self._version = _Version(
+            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
+            release=tuple(int(i) for i in match.group("release").split(".")),
+            pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
+            post=_parse_letter_version(
+                match.group("post_l"), match.group("post_n1") or match.group("post_n2")
+            ),
+            dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
+            local=_parse_local_version(match.group("local")),
+        )
+
+        # Generate a key which will be used for sorting
+        self._key = _cmpkey(
+            self._version.epoch,
+            self._version.release,
+            self._version.pre,
+            self._version.post,
+            self._version.dev,
+            self._version.local,
+        )
+
+    def __repr__(self):
+        return "".format(repr(str(self)))
+
+    def __str__(self):
+        parts = []
+
+        # Epoch
+        if self.epoch != 0:
+            parts.append("{0}!".format(self.epoch))
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self.release))
+
+        # Pre-release
+        if self.pre is not None:
+            parts.append("".join(str(x) for x in self.pre))
+
+        # Post-release
+        if self.post is not None:
+            parts.append(".post{0}".format(self.post))
+
+        # Development release
+        if self.dev is not None:
+            parts.append(".dev{0}".format(self.dev))
+
+        # Local version segment
+        if self.local is not None:
+            parts.append("+{0}".format(self.local))
+
+        return "".join(parts)
+
+    @property
+    def epoch(self):
+        return self._version.epoch
+
+    @property
+    def release(self):
+        return self._version.release
+
+    @property
+    def pre(self):
+        return self._version.pre
+
+    @property
+    def post(self):
+        return self._version.post[1] if self._version.post else None
+
+    @property
+    def dev(self):
+        return self._version.dev[1] if self._version.dev else None
+
+    @property
+    def local(self):
+        if self._version.local:
+            return ".".join(str(x) for x in self._version.local)
+        else:
+            return None
+
+    @property
+    def public(self):
+        return str(self).split("+", 1)[0]
+
+    @property
+    def base_version(self):
+        parts = []
+
+        # Epoch
+        if self.epoch != 0:
+            parts.append("{0}!".format(self.epoch))
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self.release))
+
+        return "".join(parts)
+
+    @property
+    def is_prerelease(self):
+        return self.dev is not None or self.pre is not None
+
+    @property
+    def is_postrelease(self):
+        return self.post is not None
+
+    @property
+    def is_devrelease(self):
+        return self.dev is not None
+
+
+def _parse_letter_version(letter, number):
+    if letter:
+        # We consider there to be an implicit 0 in a pre-release if there is
+        # not a numeral associated with it.
+        if number is None:
+            number = 0
+
+        # We normalize any letters to their lower case form
+        letter = letter.lower()
+
+        # We consider some words to be alternate spellings of other words and
+        # in those cases we want to normalize the spellings to our preferred
+        # spelling.
+        if letter == "alpha":
+            letter = "a"
+        elif letter == "beta":
+            letter = "b"
+        elif letter in ["c", "pre", "preview"]:
+            letter = "rc"
+        elif letter in ["rev", "r"]:
+            letter = "post"
+
+        return letter, int(number)
+    if not letter and number:
+        # We assume if we are given a number, but we are not given a letter
+        # then this is using the implicit post release syntax (e.g. 1.0-1)
+        letter = "post"
+
+        return letter, int(number)
+
+
+_local_version_separators = re.compile(r"[\._-]")
+
+
+def _parse_local_version(local):
+    """
+    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
+    """
+    if local is not None:
+        return tuple(
+            part.lower() if not part.isdigit() else int(part)
+            for part in _local_version_separators.split(local)
+        )
+
+
+def _cmpkey(epoch, release, pre, post, dev, local):
+    # When we compare a release version, we want to compare it with all of the
+    # trailing zeros removed. So we'll use a reverse the list, drop all the now
+    # leading zeros until we come to something non zero, then take the rest
+    # re-reverse it back into the correct order and make it a tuple and use
+    # that for our sorting key.
+    release = tuple(
+        reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
+    )
+
+    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
+    # We'll do this by abusing the pre segment, but we _only_ want to do this
+    # if there is not a pre or a post segment. If we have one of those then
+    # the normal sorting rules will handle this case correctly.
+    if pre is None and post is None and dev is not None:
+        pre = -Infinity
+    # Versions without a pre-release (except as noted above) should sort after
+    # those with one.
+    elif pre is None:
+        pre = Infinity
+
+    # Versions without a post segment should sort before those with one.
+    if post is None:
+        post = -Infinity
+
+    # Versions without a development segment should sort after those with one.
+    if dev is None:
+        dev = Infinity
+
+    if local is None:
+        # Versions without a local segment should sort before those with one.
+        local = -Infinity
+    else:
+        # Versions with a local segment need that segment parsed to implement
+        # the sorting rules in PEP440.
+        # - Alpha numeric segments sort before numeric segments
+        # - Alpha numeric segments sort lexicographically
+        # - Numeric segments sort numerically
+        # - Shorter versions sort before longer versions when the prefixes
+        #   match exactly
+        local = tuple((i, "") if isinstance(i, int) else (-Infinity, i) for i in local)
+
+    return epoch, release, pre, post, dev, local
diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/pyparsing.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/pyparsing.py
new file mode 100644
index 0000000..cf75e1e
--- /dev/null
+++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/pyparsing.py
@@ -0,0 +1,5742 @@
+# module pyparsing.py
+#
+# Copyright (c) 2003-2018  Paul T. McGuire
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__doc__ = \
+"""
+pyparsing module - Classes and methods to define and execute parsing grammars
+=============================================================================
+
+The pyparsing module is an alternative approach to creating and executing simple grammars,
+vs. the traditional lex/yacc approach, or the use of regular expressions.  With pyparsing, you
+don't need to learn a new syntax for defining grammars or matching expressions - the parsing module
+provides a library of classes that you use to construct the grammar directly in Python.
+
+Here is a program to parse "Hello, World!" (or any greeting of the form 
+C{", !"}), built up using L{Word}, L{Literal}, and L{And} elements 
+(L{'+'} operator gives L{And} expressions, strings are auto-converted to
+L{Literal} expressions)::
+
+    from pyparsing import Word, alphas
+
+    # define grammar of a greeting
+    greet = Word(alphas) + "," + Word(alphas) + "!"
+
+    hello = "Hello, World!"
+    print (hello, "->", greet.parseString(hello))
+
+The program outputs the following::
+
+    Hello, World! -> ['Hello', ',', 'World', '!']
+
+The Python representation of the grammar is quite readable, owing to the self-explanatory
+class names, and the use of '+', '|' and '^' operators.
+
+The L{ParseResults} object returned from L{ParserElement.parseString} can be accessed as a nested list, a dictionary, or an
+object with named attributes.
+
+The pyparsing module handles some of the problems that are typically vexing when writing text parsers:
+ - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello  ,  World  !", etc.)
+ - quoted strings
+ - embedded comments
+
+
+Getting Started -
+-----------------
+Visit the classes L{ParserElement} and L{ParseResults} to see the base classes that most other pyparsing
+classes inherit from. Use the docstrings for examples of how to:
+ - construct literal match expressions from L{Literal} and L{CaselessLiteral} classes
+ - construct character word-group expressions using the L{Word} class
+ - see how to create repetitive expressions using L{ZeroOrMore} and L{OneOrMore} classes
+ - use L{'+'}, L{'|'}, L{'^'}, and L{'&'} operators to combine simple expressions into more complex ones
+ - associate names with your parsed results using L{ParserElement.setResultsName}
+ - find some helpful expression short-cuts like L{delimitedList} and L{oneOf}
+ - find more useful common expressions in the L{pyparsing_common} namespace class
+"""
+
+__version__ = "2.2.1"
+__versionTime__ = "18 Sep 2018 00:49 UTC"
+__author__ = "Paul McGuire "
+
+import string
+from weakref import ref as wkref
+import copy
+import sys
+import warnings
+import re
+import sre_constants
+import collections
+import pprint
+import traceback
+import types
+from datetime import datetime
+
+try:
+    from _thread import RLock
+except ImportError:
+    from threading import RLock
+
+try:
+    # Python 3
+    from collections.abc import Iterable
+    from collections.abc import MutableMapping
+except ImportError:
+    # Python 2.7
+    from collections import Iterable
+    from collections import MutableMapping
+
+try:
+    from collections import OrderedDict as _OrderedDict
+except ImportError:
+    try:
+        from ordereddict import OrderedDict as _OrderedDict
+    except ImportError:
+        _OrderedDict = None
+
+#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) )
+
+__all__ = [
+'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty',
+'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal',
+'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or',
+'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException',
+'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException',
+'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', 
+'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore',
+'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col',
+'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString',
+'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums',
+'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno',
+'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral',
+'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables',
+'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', 
+'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd',
+'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute',
+'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass',
+'CloseMatch', 'tokenMap', 'pyparsing_common',
+]
+
+system_version = tuple(sys.version_info)[:3]
+PY_3 = system_version[0] == 3
+if PY_3:
+    _MAX_INT = sys.maxsize
+    basestring = str
+    unichr = chr
+    _ustr = str
+
+    # build list of single arg builtins, that can be used as parse actions
+    singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max]
+
+else:
+    _MAX_INT = sys.maxint
+    range = xrange
+
+    def _ustr(obj):
+        """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries
+           str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It
+           then < returns the unicode object | encodes it with the default encoding | ... >.
+        """
+        if isinstance(obj,unicode):
+            return obj
+
+        try:
+            # If this works, then _ustr(obj) has the same behaviour as str(obj), so
+            # it won't break any existing code.
+            return str(obj)
+
+        except UnicodeEncodeError:
+            # Else encode it
+            ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace')
+            xmlcharref = Regex(r'&#\d+;')
+            xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:])
+            return xmlcharref.transformString(ret)
+
+    # build list of single arg builtins, tolerant of Python version, that can be used as parse actions
+    singleArgBuiltins = []
+    import __builtin__
+    for fname in "sum len sorted reversed list tuple set any all min max".split():
+        try:
+            singleArgBuiltins.append(getattr(__builtin__,fname))
+        except AttributeError:
+            continue
+            
+_generatorType = type((y for y in range(1)))
+ 
+def _xml_escape(data):
+    """Escape &, <, >, ", ', etc. in a string of data."""
+
+    # ampersand must be replaced first
+    from_symbols = '&><"\''
+    to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split())
+    for from_,to_ in zip(from_symbols, to_symbols):
+        data = data.replace(from_, to_)
+    return data
+
+class _Constants(object):
+    pass
+
+alphas     = string.ascii_uppercase + string.ascii_lowercase
+nums       = "0123456789"
+hexnums    = nums + "ABCDEFabcdef"
+alphanums  = alphas + nums
+_bslash    = chr(92)
+printables = "".join(c for c in string.printable if c not in string.whitespace)
+
+class ParseBaseException(Exception):
+    """base exception class for all parsing runtime exceptions"""
+    # Performance tuning: we construct a *lot* of these, so keep this
+    # constructor as small and fast as possible
+    def __init__( self, pstr, loc=0, msg=None, elem=None ):
+        self.loc = loc
+        if msg is None:
+            self.msg = pstr
+            self.pstr = ""
+        else:
+            self.msg = msg
+            self.pstr = pstr
+        self.parserElement = elem
+        self.args = (pstr, loc, msg)
+
+    @classmethod
+    def _from_exception(cls, pe):
+        """
+        internal factory method to simplify creating one type of ParseException 
+        from another - avoids having __init__ signature conflicts among subclasses
+        """
+        return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement)
+
+    def __getattr__( self, aname ):
+        """supported attributes by name are:
+            - lineno - returns the line number of the exception text
+            - col - returns the column number of the exception text
+            - line - returns the line containing the exception text
+        """
+        if( aname == "lineno" ):
+            return lineno( self.loc, self.pstr )
+        elif( aname in ("col", "column") ):
+            return col( self.loc, self.pstr )
+        elif( aname == "line" ):
+            return line( self.loc, self.pstr )
+        else:
+            raise AttributeError(aname)
+
+    def __str__( self ):
+        return "%s (at char %d), (line:%d, col:%d)" % \
+                ( self.msg, self.loc, self.lineno, self.column )
+    def __repr__( self ):
+        return _ustr(self)
+    def markInputline( self, markerString = ">!<" ):
+        """Extracts the exception line from the input string, and marks
+           the location of the exception with a special symbol.
+        """
+        line_str = self.line
+        line_column = self.column - 1
+        if markerString:
+            line_str = "".join((line_str[:line_column],
+                                markerString, line_str[line_column:]))
+        return line_str.strip()
+    def __dir__(self):
+        return "lineno col line".split() + dir(type(self))
+
+class ParseException(ParseBaseException):
+    """
+    Exception thrown when parse expressions don't match class;
+    supported attributes by name are:
+     - lineno - returns the line number of the exception text
+     - col - returns the column number of the exception text
+     - line - returns the line containing the exception text
+        
+    Example::
+        try:
+            Word(nums).setName("integer").parseString("ABC")
+        except ParseException as pe:
+            print(pe)
+            print("column: {}".format(pe.col))
+            
+    prints::
+       Expected integer (at char 0), (line:1, col:1)
+        column: 1
+    """
+    pass
+
+class ParseFatalException(ParseBaseException):
+    """user-throwable exception thrown when inconsistent parse content
+       is found; stops all parsing immediately"""
+    pass
+
+class ParseSyntaxException(ParseFatalException):
+    """just like L{ParseFatalException}, but thrown internally when an
+       L{ErrorStop} ('-' operator) indicates that parsing is to stop 
+       immediately because an unbacktrackable syntax error has been found"""
+    pass
+
+#~ class ReparseException(ParseBaseException):
+    #~ """Experimental class - parse actions can raise this exception to cause
+       #~ pyparsing to reparse the input string:
+        #~ - with a modified input string, and/or
+        #~ - with a modified start location
+       #~ Set the values of the ReparseException in the constructor, and raise the
+       #~ exception in a parse action to cause pyparsing to use the new string/location.
+       #~ Setting the values as None causes no change to be made.
+       #~ """
+    #~ def __init_( self, newstring, restartLoc ):
+        #~ self.newParseText = newstring
+        #~ self.reparseLoc = restartLoc
+
+class RecursiveGrammarException(Exception):
+    """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive"""
+    def __init__( self, parseElementList ):
+        self.parseElementTrace = parseElementList
+
+    def __str__( self ):
+        return "RecursiveGrammarException: %s" % self.parseElementTrace
+
+class _ParseResultsWithOffset(object):
+    def __init__(self,p1,p2):
+        self.tup = (p1,p2)
+    def __getitem__(self,i):
+        return self.tup[i]
+    def __repr__(self):
+        return repr(self.tup[0])
+    def setOffset(self,i):
+        self.tup = (self.tup[0],i)
+
+class ParseResults(object):
+    """
+    Structured parse results, to provide multiple means of access to the parsed data:
+       - as a list (C{len(results)})
+       - by list index (C{results[0], results[1]}, etc.)
+       - by attribute (C{results.} - see L{ParserElement.setResultsName})
+
+    Example::
+        integer = Word(nums)
+        date_str = (integer.setResultsName("year") + '/' 
+                        + integer.setResultsName("month") + '/' 
+                        + integer.setResultsName("day"))
+        # equivalent form:
+        # date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
+
+        # parseString returns a ParseResults object
+        result = date_str.parseString("1999/12/31")
+
+        def test(s, fn=repr):
+            print("%s -> %s" % (s, fn(eval(s))))
+        test("list(result)")
+        test("result[0]")
+        test("result['month']")
+        test("result.day")
+        test("'month' in result")
+        test("'minutes' in result")
+        test("result.dump()", str)
+    prints::
+        list(result) -> ['1999', '/', '12', '/', '31']
+        result[0] -> '1999'
+        result['month'] -> '12'
+        result.day -> '31'
+        'month' in result -> True
+        'minutes' in result -> False
+        result.dump() -> ['1999', '/', '12', '/', '31']
+        - day: 31
+        - month: 12
+        - year: 1999
+    """
+    def __new__(cls, toklist=None, name=None, asList=True, modal=True ):
+        if isinstance(toklist, cls):
+            return toklist
+        retobj = object.__new__(cls)
+        retobj.__doinit = True
+        return retobj
+
+    # Performance tuning: we construct a *lot* of these, so keep this
+    # constructor as small and fast as possible
+    def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ):
+        if self.__doinit:
+            self.__doinit = False
+            self.__name = None
+            self.__parent = None
+            self.__accumNames = {}
+            self.__asList = asList
+            self.__modal = modal
+            if toklist is None:
+                toklist = []
+            if isinstance(toklist, list):
+                self.__toklist = toklist[:]
+            elif isinstance(toklist, _generatorType):
+                self.__toklist = list(toklist)
+            else:
+                self.__toklist = [toklist]
+            self.__tokdict = dict()
+
+        if name is not None and name:
+            if not modal:
+                self.__accumNames[name] = 0
+            if isinstance(name,int):
+                name = _ustr(name) # will always return a str, but use _ustr for consistency
+            self.__name = name
+            if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])):
+                if isinstance(toklist,basestring):
+                    toklist = [ toklist ]
+                if asList:
+                    if isinstance(toklist,ParseResults):
+                        self[name] = _ParseResultsWithOffset(toklist.copy(),0)
+                    else:
+                        self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0)
+                    self[name].__name = name
+                else:
+                    try:
+                        self[name] = toklist[0]
+                    except (KeyError,TypeError,IndexError):
+                        self[name] = toklist
+
+    def __getitem__( self, i ):
+        if isinstance( i, (int,slice) ):
+            return self.__toklist[i]
+        else:
+            if i not in self.__accumNames:
+                return self.__tokdict[i][-1][0]
+            else:
+                return ParseResults([ v[0] for v in self.__tokdict[i] ])
+
+    def __setitem__( self, k, v, isinstance=isinstance ):
+        if isinstance(v,_ParseResultsWithOffset):
+            self.__tokdict[k] = self.__tokdict.get(k,list()) + [v]
+            sub = v[0]
+        elif isinstance(k,(int,slice)):
+            self.__toklist[k] = v
+            sub = v
+        else:
+            self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)]
+            sub = v
+        if isinstance(sub,ParseResults):
+            sub.__parent = wkref(self)
+
+    def __delitem__( self, i ):
+        if isinstance(i,(int,slice)):
+            mylen = len( self.__toklist )
+            del self.__toklist[i]
+
+            # convert int to slice
+            if isinstance(i, int):
+                if i < 0:
+                    i += mylen
+                i = slice(i, i+1)
+            # get removed indices
+            removed = list(range(*i.indices(mylen)))
+            removed.reverse()
+            # fixup indices in token dictionary
+            for name,occurrences in self.__tokdict.items():
+                for j in removed:
+                    for k, (value, position) in enumerate(occurrences):
+                        occurrences[k] = _ParseResultsWithOffset(value, position - (position > j))
+        else:
+            del self.__tokdict[i]
+
+    def __contains__( self, k ):
+        return k in self.__tokdict
+
+    def __len__( self ): return len( self.__toklist )
+    def __bool__(self): return ( not not self.__toklist )
+    __nonzero__ = __bool__
+    def __iter__( self ): return iter( self.__toklist )
+    def __reversed__( self ): return iter( self.__toklist[::-1] )
+    def _iterkeys( self ):
+        if hasattr(self.__tokdict, "iterkeys"):
+            return self.__tokdict.iterkeys()
+        else:
+            return iter(self.__tokdict)
+
+    def _itervalues( self ):
+        return (self[k] for k in self._iterkeys())
+            
+    def _iteritems( self ):
+        return ((k, self[k]) for k in self._iterkeys())
+
+    if PY_3:
+        keys = _iterkeys       
+        """Returns an iterator of all named result keys (Python 3.x only)."""
+
+        values = _itervalues
+        """Returns an iterator of all named result values (Python 3.x only)."""
+
+        items = _iteritems
+        """Returns an iterator of all named result key-value tuples (Python 3.x only)."""
+
+    else:
+        iterkeys = _iterkeys
+        """Returns an iterator of all named result keys (Python 2.x only)."""
+
+        itervalues = _itervalues
+        """Returns an iterator of all named result values (Python 2.x only)."""
+
+        iteritems = _iteritems
+        """Returns an iterator of all named result key-value tuples (Python 2.x only)."""
+
+        def keys( self ):
+            """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x)."""
+            return list(self.iterkeys())
+
+        def values( self ):
+            """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x)."""
+            return list(self.itervalues())
+                
+        def items( self ):
+            """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x)."""
+            return list(self.iteritems())
+
+    def haskeys( self ):
+        """Since keys() returns an iterator, this method is helpful in bypassing
+           code that looks for the existence of any defined results names."""
+        return bool(self.__tokdict)
+        
+    def pop( self, *args, **kwargs):
+        """
+        Removes and returns item at specified index (default=C{last}).
+        Supports both C{list} and C{dict} semantics for C{pop()}. If passed no
+        argument or an integer argument, it will use C{list} semantics
+        and pop tokens from the list of parsed tokens. If passed a 
+        non-integer argument (most likely a string), it will use C{dict}
+        semantics and pop the corresponding value from any defined 
+        results names. A second default return value argument is 
+        supported, just as in C{dict.pop()}.
+
+        Example::
+            def remove_first(tokens):
+                tokens.pop(0)
+            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']
+            print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321']
+
+            label = Word(alphas)
+            patt = label("LABEL") + OneOrMore(Word(nums))
+            print(patt.parseString("AAB 123 321").dump())
+
+            # Use pop() in a parse action to remove named result (note that corresponding value is not
+            # removed from list form of results)
+            def remove_LABEL(tokens):
+                tokens.pop("LABEL")
+                return tokens
+            patt.addParseAction(remove_LABEL)
+            print(patt.parseString("AAB 123 321").dump())
+        prints::
+            ['AAB', '123', '321']
+            - LABEL: AAB
+
+            ['AAB', '123', '321']
+        """
+        if not args:
+            args = [-1]
+        for k,v in kwargs.items():
+            if k == 'default':
+                args = (args[0], v)
+            else:
+                raise TypeError("pop() got an unexpected keyword argument '%s'" % k)
+        if (isinstance(args[0], int) or 
+                        len(args) == 1 or 
+                        args[0] in self):
+            index = args[0]
+            ret = self[index]
+            del self[index]
+            return ret
+        else:
+            defaultvalue = args[1]
+            return defaultvalue
+
+    def get(self, key, defaultValue=None):
+        """
+        Returns named result matching the given key, or if there is no
+        such name, then returns the given C{defaultValue} or C{None} if no
+        C{defaultValue} is specified.
+
+        Similar to C{dict.get()}.
+        
+        Example::
+            integer = Word(nums)
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           
+
+            result = date_str.parseString("1999/12/31")
+            print(result.get("year")) # -> '1999'
+            print(result.get("hour", "not specified")) # -> 'not specified'
+            print(result.get("hour")) # -> None
+        """
+        if key in self:
+            return self[key]
+        else:
+            return defaultValue
+
+    def insert( self, index, insStr ):
+        """
+        Inserts new element at location index in the list of parsed tokens.
+        
+        Similar to C{list.insert()}.
+
+        Example::
+            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']
+
+            # use a parse action to insert the parse location in the front of the parsed results
+            def insert_locn(locn, tokens):
+                tokens.insert(0, locn)
+            print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321']
+        """
+        self.__toklist.insert(index, insStr)
+        # fixup indices in token dictionary
+        for name,occurrences in self.__tokdict.items():
+            for k, (value, position) in enumerate(occurrences):
+                occurrences[k] = _ParseResultsWithOffset(value, position + (position > index))
+
+    def append( self, item ):
+        """
+        Add single element to end of ParseResults list of elements.
+
+        Example::
+            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']
+            
+            # use a parse action to compute the sum of the parsed integers, and add it to the end
+            def append_sum(tokens):
+                tokens.append(sum(map(int, tokens)))
+            print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444]
+        """
+        self.__toklist.append(item)
+
+    def extend( self, itemseq ):
+        """
+        Add sequence of elements to end of ParseResults list of elements.
+
+        Example::
+            patt = OneOrMore(Word(alphas))
+            
+            # use a parse action to append the reverse of the matched strings, to make a palindrome
+            def make_palindrome(tokens):
+                tokens.extend(reversed([t[::-1] for t in tokens]))
+                return ''.join(tokens)
+            print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl'
+        """
+        if isinstance(itemseq, ParseResults):
+            self += itemseq
+        else:
+            self.__toklist.extend(itemseq)
+
+    def clear( self ):
+        """
+        Clear all elements and results names.
+        """
+        del self.__toklist[:]
+        self.__tokdict.clear()
+
+    def __getattr__( self, name ):
+        try:
+            return self[name]
+        except KeyError:
+            return ""
+            
+        if name in self.__tokdict:
+            if name not in self.__accumNames:
+                return self.__tokdict[name][-1][0]
+            else:
+                return ParseResults([ v[0] for v in self.__tokdict[name] ])
+        else:
+            return ""
+
+    def __add__( self, other ):
+        ret = self.copy()
+        ret += other
+        return ret
+
+    def __iadd__( self, other ):
+        if other.__tokdict:
+            offset = len(self.__toklist)
+            addoffset = lambda a: offset if a<0 else a+offset
+            otheritems = other.__tokdict.items()
+            otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) )
+                                for (k,vlist) in otheritems for v in vlist]
+            for k,v in otherdictitems:
+                self[k] = v
+                if isinstance(v[0],ParseResults):
+                    v[0].__parent = wkref(self)
+            
+        self.__toklist += other.__toklist
+        self.__accumNames.update( other.__accumNames )
+        return self
+
+    def __radd__(self, other):
+        if isinstance(other,int) and other == 0:
+            # useful for merging many ParseResults using sum() builtin
+            return self.copy()
+        else:
+            # this may raise a TypeError - so be it
+            return other + self
+        
+    def __repr__( self ):
+        return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) )
+
+    def __str__( self ):
+        return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']'
+
+    def _asStringList( self, sep='' ):
+        out = []
+        for item in self.__toklist:
+            if out and sep:
+                out.append(sep)
+            if isinstance( item, ParseResults ):
+                out += item._asStringList()
+            else:
+                out.append( _ustr(item) )
+        return out
+
+    def asList( self ):
+        """
+        Returns the parse results as a nested list of matching tokens, all converted to strings.
+
+        Example::
+            patt = OneOrMore(Word(alphas))
+            result = patt.parseString("sldkj lsdkj sldkj")
+            # even though the result prints in string-like form, it is actually a pyparsing ParseResults
+            print(type(result), result) # ->  ['sldkj', 'lsdkj', 'sldkj']
+            
+            # Use asList() to create an actual list
+            result_list = result.asList()
+            print(type(result_list), result_list) # ->  ['sldkj', 'lsdkj', 'sldkj']
+        """
+        return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist]
+
+    def asDict( self ):
+        """
+        Returns the named parse results as a nested dictionary.
+
+        Example::
+            integer = Word(nums)
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
+            
+            result = date_str.parseString('12/31/1999')
+            print(type(result), repr(result)) # ->  (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]})
+            
+            result_dict = result.asDict()
+            print(type(result_dict), repr(result_dict)) # ->  {'day': '1999', 'year': '12', 'month': '31'}
+
+            # even though a ParseResults supports dict-like access, sometime you just need to have a dict
+            import json
+            print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable
+            print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"}
+        """
+        if PY_3:
+            item_fn = self.items
+        else:
+            item_fn = self.iteritems
+            
+        def toItem(obj):
+            if isinstance(obj, ParseResults):
+                if obj.haskeys():
+                    return obj.asDict()
+                else:
+                    return [toItem(v) for v in obj]
+            else:
+                return obj
+                
+        return dict((k,toItem(v)) for k,v in item_fn())
+
+    def copy( self ):
+        """
+        Returns a new copy of a C{ParseResults} object.
+        """
+        ret = ParseResults( self.__toklist )
+        ret.__tokdict = self.__tokdict.copy()
+        ret.__parent = self.__parent
+        ret.__accumNames.update( self.__accumNames )
+        ret.__name = self.__name
+        return ret
+
+    def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ):
+        """
+        (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names.
+        """
+        nl = "\n"
+        out = []
+        namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items()
+                                                            for v in vlist)
+        nextLevelIndent = indent + "  "
+
+        # collapse out indents if formatting is not desired
+        if not formatted:
+            indent = ""
+            nextLevelIndent = ""
+            nl = ""
+
+        selfTag = None
+        if doctag is not None:
+            selfTag = doctag
+        else:
+            if self.__name:
+                selfTag = self.__name
+
+        if not selfTag:
+            if namedItemsOnly:
+                return ""
+            else:
+                selfTag = "ITEM"
+
+        out += [ nl, indent, "<", selfTag, ">" ]
+
+        for i,res in enumerate(self.__toklist):
+            if isinstance(res,ParseResults):
+                if i in namedItems:
+                    out += [ res.asXML(namedItems[i],
+                                        namedItemsOnly and doctag is None,
+                                        nextLevelIndent,
+                                        formatted)]
+                else:
+                    out += [ res.asXML(None,
+                                        namedItemsOnly and doctag is None,
+                                        nextLevelIndent,
+                                        formatted)]
+            else:
+                # individual token, see if there is a name for it
+                resTag = None
+                if i in namedItems:
+                    resTag = namedItems[i]
+                if not resTag:
+                    if namedItemsOnly:
+                        continue
+                    else:
+                        resTag = "ITEM"
+                xmlBodyText = _xml_escape(_ustr(res))
+                out += [ nl, nextLevelIndent, "<", resTag, ">",
+                                                xmlBodyText,
+                                                "" ]
+
+        out += [ nl, indent, "" ]
+        return "".join(out)
+
+    def __lookup(self,sub):
+        for k,vlist in self.__tokdict.items():
+            for v,loc in vlist:
+                if sub is v:
+                    return k
+        return None
+
+    def getName(self):
+        r"""
+        Returns the results name for this token expression. Useful when several 
+        different expressions might match at a particular location.
+
+        Example::
+            integer = Word(nums)
+            ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d")
+            house_number_expr = Suppress('#') + Word(nums, alphanums)
+            user_data = (Group(house_number_expr)("house_number") 
+                        | Group(ssn_expr)("ssn")
+                        | Group(integer)("age"))
+            user_info = OneOrMore(user_data)
+            
+            result = user_info.parseString("22 111-22-3333 #221B")
+            for item in result:
+                print(item.getName(), ':', item[0])
+        prints::
+            age : 22
+            ssn : 111-22-3333
+            house_number : 221B
+        """
+        if self.__name:
+            return self.__name
+        elif self.__parent:
+            par = self.__parent()
+            if par:
+                return par.__lookup(self)
+            else:
+                return None
+        elif (len(self) == 1 and
+               len(self.__tokdict) == 1 and
+               next(iter(self.__tokdict.values()))[0][1] in (0,-1)):
+            return next(iter(self.__tokdict.keys()))
+        else:
+            return None
+
+    def dump(self, indent='', depth=0, full=True):
+        """
+        Diagnostic method for listing out the contents of a C{ParseResults}.
+        Accepts an optional C{indent} argument so that this string can be embedded
+        in a nested display of other data.
+
+        Example::
+            integer = Word(nums)
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
+            
+            result = date_str.parseString('12/31/1999')
+            print(result.dump())
+        prints::
+            ['12', '/', '31', '/', '1999']
+            - day: 1999
+            - month: 31
+            - year: 12
+        """
+        out = []
+        NL = '\n'
+        out.append( indent+_ustr(self.asList()) )
+        if full:
+            if self.haskeys():
+                items = sorted((str(k), v) for k,v in self.items())
+                for k,v in items:
+                    if out:
+                        out.append(NL)
+                    out.append( "%s%s- %s: " % (indent,('  '*depth), k) )
+                    if isinstance(v,ParseResults):
+                        if v:
+                            out.append( v.dump(indent,depth+1) )
+                        else:
+                            out.append(_ustr(v))
+                    else:
+                        out.append(repr(v))
+            elif any(isinstance(vv,ParseResults) for vv in self):
+                v = self
+                for i,vv in enumerate(v):
+                    if isinstance(vv,ParseResults):
+                        out.append("\n%s%s[%d]:\n%s%s%s" % (indent,('  '*(depth)),i,indent,('  '*(depth+1)),vv.dump(indent,depth+1) ))
+                    else:
+                        out.append("\n%s%s[%d]:\n%s%s%s" % (indent,('  '*(depth)),i,indent,('  '*(depth+1)),_ustr(vv)))
+            
+        return "".join(out)
+
+    def pprint(self, *args, **kwargs):
+        """
+        Pretty-printer for parsed results as a list, using the C{pprint} module.
+        Accepts additional positional or keyword args as defined for the 
+        C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint})
+
+        Example::
+            ident = Word(alphas, alphanums)
+            num = Word(nums)
+            func = Forward()
+            term = ident | num | Group('(' + func + ')')
+            func <<= ident + Group(Optional(delimitedList(term)))
+            result = func.parseString("fna a,b,(fnb c,d,200),100")
+            result.pprint(width=40)
+        prints::
+            ['fna',
+             ['a',
+              'b',
+              ['(', 'fnb', ['c', 'd', '200'], ')'],
+              '100']]
+        """
+        pprint.pprint(self.asList(), *args, **kwargs)
+
+    # add support for pickle protocol
+    def __getstate__(self):
+        return ( self.__toklist,
+                 ( self.__tokdict.copy(),
+                   self.__parent is not None and self.__parent() or None,
+                   self.__accumNames,
+                   self.__name ) )
+
+    def __setstate__(self,state):
+        self.__toklist = state[0]
+        (self.__tokdict,
+         par,
+         inAccumNames,
+         self.__name) = state[1]
+        self.__accumNames = {}
+        self.__accumNames.update(inAccumNames)
+        if par is not None:
+            self.__parent = wkref(par)
+        else:
+            self.__parent = None
+
+    def __getnewargs__(self):
+        return self.__toklist, self.__name, self.__asList, self.__modal
+
+    def __dir__(self):
+        return (dir(type(self)) + list(self.keys()))
+
+MutableMapping.register(ParseResults)
+
+def col (loc,strg):
+    """Returns current column within a string, counting newlines as line separators.
+   The first column is number 1.
+
+   Note: the default parsing behavior is to expand tabs in the input string
+   before starting the parsing process.  See L{I{ParserElement.parseString}} for more information
+   on parsing strings containing C{}s, and suggested methods to maintain a
+   consistent view of the parsed string, the parse location, and line and column
+   positions within the parsed string.
+   """
+    s = strg
+    return 1 if 0} for more information
+   on parsing strings containing C{}s, and suggested methods to maintain a
+   consistent view of the parsed string, the parse location, and line and column
+   positions within the parsed string.
+   """
+    return strg.count("\n",0,loc) + 1
+
+def line( loc, strg ):
+    """Returns the line of text containing loc within a string, counting newlines as line separators.
+       """
+    lastCR = strg.rfind("\n", 0, loc)
+    nextCR = strg.find("\n", loc)
+    if nextCR >= 0:
+        return strg[lastCR+1:nextCR]
+    else:
+        return strg[lastCR+1:]
+
+def _defaultStartDebugAction( instring, loc, expr ):
+    print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )))
+
+def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ):
+    print ("Matched " + _ustr(expr) + " -> " + str(toks.asList()))
+
+def _defaultExceptionDebugAction( instring, loc, expr, exc ):
+    print ("Exception raised:" + _ustr(exc))
+
+def nullDebugAction(*args):
+    """'Do-nothing' debug action, to suppress debugging output during parsing."""
+    pass
+
+# Only works on Python 3.x - nonlocal is toxic to Python 2 installs
+#~ 'decorator to trim function calls to match the arity of the target'
+#~ def _trim_arity(func, maxargs=3):
+    #~ if func in singleArgBuiltins:
+        #~ return lambda s,l,t: func(t)
+    #~ limit = 0
+    #~ foundArity = False
+    #~ def wrapper(*args):
+        #~ nonlocal limit,foundArity
+        #~ while 1:
+            #~ try:
+                #~ ret = func(*args[limit:])
+                #~ foundArity = True
+                #~ return ret
+            #~ except TypeError:
+                #~ if limit == maxargs or foundArity:
+                    #~ raise
+                #~ limit += 1
+                #~ continue
+    #~ return wrapper
+
+# this version is Python 2.x-3.x cross-compatible
+'decorator to trim function calls to match the arity of the target'
+def _trim_arity(func, maxargs=2):
+    if func in singleArgBuiltins:
+        return lambda s,l,t: func(t)
+    limit = [0]
+    foundArity = [False]
+    
+    # traceback return data structure changed in Py3.5 - normalize back to plain tuples
+    if system_version[:2] >= (3,5):
+        def extract_stack(limit=0):
+            # special handling for Python 3.5.0 - extra deep call stack by 1
+            offset = -3 if system_version == (3,5,0) else -2
+            frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset]
+            return [frame_summary[:2]]
+        def extract_tb(tb, limit=0):
+            frames = traceback.extract_tb(tb, limit=limit)
+            frame_summary = frames[-1]
+            return [frame_summary[:2]]
+    else:
+        extract_stack = traceback.extract_stack
+        extract_tb = traceback.extract_tb
+    
+    # synthesize what would be returned by traceback.extract_stack at the call to 
+    # user's parse action 'func', so that we don't incur call penalty at parse time
+    
+    LINE_DIFF = 6
+    # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND 
+    # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!!
+    this_line = extract_stack(limit=2)[-1]
+    pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF)
+
+    def wrapper(*args):
+        while 1:
+            try:
+                ret = func(*args[limit[0]:])
+                foundArity[0] = True
+                return ret
+            except TypeError:
+                # re-raise TypeErrors if they did not come from our arity testing
+                if foundArity[0]:
+                    raise
+                else:
+                    try:
+                        tb = sys.exc_info()[-1]
+                        if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth:
+                            raise
+                    finally:
+                        del tb
+
+                if limit[0] <= maxargs:
+                    limit[0] += 1
+                    continue
+                raise
+
+    # copy func name to wrapper for sensible debug output
+    func_name = ""
+    try:
+        func_name = getattr(func, '__name__', 
+                            getattr(func, '__class__').__name__)
+    except Exception:
+        func_name = str(func)
+    wrapper.__name__ = func_name
+
+    return wrapper
+
+class ParserElement(object):
+    """Abstract base level parser element class."""
+    DEFAULT_WHITE_CHARS = " \n\t\r"
+    verbose_stacktrace = False
+
+    @staticmethod
+    def setDefaultWhitespaceChars( chars ):
+        r"""
+        Overrides the default whitespace chars
+
+        Example::
+            # default whitespace chars are space,  and newline
+            OneOrMore(Word(alphas)).parseString("abc def\nghi jkl")  # -> ['abc', 'def', 'ghi', 'jkl']
+            
+            # change to just treat newline as significant
+            ParserElement.setDefaultWhitespaceChars(" \t")
+            OneOrMore(Word(alphas)).parseString("abc def\nghi jkl")  # -> ['abc', 'def']
+        """
+        ParserElement.DEFAULT_WHITE_CHARS = chars
+
+    @staticmethod
+    def inlineLiteralsUsing(cls):
+        """
+        Set class to be used for inclusion of string literals into a parser.
+        
+        Example::
+            # default literal class used is Literal
+            integer = Word(nums)
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           
+
+            date_str.parseString("1999/12/31")  # -> ['1999', '/', '12', '/', '31']
+
+
+            # change to Suppress
+            ParserElement.inlineLiteralsUsing(Suppress)
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           
+
+            date_str.parseString("1999/12/31")  # -> ['1999', '12', '31']
+        """
+        ParserElement._literalStringClass = cls
+
+    def __init__( self, savelist=False ):
+        self.parseAction = list()
+        self.failAction = None
+        #~ self.name = ""  # don't define self.name, let subclasses try/except upcall
+        self.strRepr = None
+        self.resultsName = None
+        self.saveAsList = savelist
+        self.skipWhitespace = True
+        self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
+        self.copyDefaultWhiteChars = True
+        self.mayReturnEmpty = False # used when checking for left-recursion
+        self.keepTabs = False
+        self.ignoreExprs = list()
+        self.debug = False
+        self.streamlined = False
+        self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index
+        self.errmsg = ""
+        self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all)
+        self.debugActions = ( None, None, None ) #custom debug actions
+        self.re = None
+        self.callPreparse = True # used to avoid redundant calls to preParse
+        self.callDuringTry = False
+
+    def copy( self ):
+        """
+        Make a copy of this C{ParserElement}.  Useful for defining different parse actions
+        for the same parsing pattern, using copies of the original parse element.
+        
+        Example::
+            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
+            integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K")
+            integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M")
+            
+            print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M"))
+        prints::
+            [5120, 100, 655360, 268435456]
+        Equivalent form of C{expr.copy()} is just C{expr()}::
+            integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M")
+        """
+        cpy = copy.copy( self )
+        cpy.parseAction = self.parseAction[:]
+        cpy.ignoreExprs = self.ignoreExprs[:]
+        if self.copyDefaultWhiteChars:
+            cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
+        return cpy
+
+    def setName( self, name ):
+        """
+        Define name for this expression, makes debugging and exception messages clearer.
+        
+        Example::
+            Word(nums).parseString("ABC")  # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1)
+            Word(nums).setName("integer").parseString("ABC")  # -> Exception: Expected integer (at char 0), (line:1, col:1)
+        """
+        self.name = name
+        self.errmsg = "Expected " + self.name
+        if hasattr(self,"exception"):
+            self.exception.msg = self.errmsg
+        return self
+
+    def setResultsName( self, name, listAllMatches=False ):
+        """
+        Define name for referencing matching tokens as a nested attribute
+        of the returned parse results.
+        NOTE: this returns a *copy* of the original C{ParserElement} object;
+        this is so that the client can define a basic element, such as an
+        integer, and reference it in multiple places with different names.
+
+        You can also set results names using the abbreviated syntax,
+        C{expr("name")} in place of C{expr.setResultsName("name")} - 
+        see L{I{__call__}<__call__>}.
+
+        Example::
+            date_str = (integer.setResultsName("year") + '/' 
+                        + integer.setResultsName("month") + '/' 
+                        + integer.setResultsName("day"))
+
+            # equivalent form:
+            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
+        """
+        newself = self.copy()
+        if name.endswith("*"):
+            name = name[:-1]
+            listAllMatches=True
+        newself.resultsName = name
+        newself.modalResults = not listAllMatches
+        return newself
+
+    def setBreak(self,breakFlag = True):
+        """Method to invoke the Python pdb debugger when this element is
+           about to be parsed. Set C{breakFlag} to True to enable, False to
+           disable.
+        """
+        if breakFlag:
+            _parseMethod = self._parse
+            def breaker(instring, loc, doActions=True, callPreParse=True):
+                import pdb
+                pdb.set_trace()
+                return _parseMethod( instring, loc, doActions, callPreParse )
+            breaker._originalParseMethod = _parseMethod
+            self._parse = breaker
+        else:
+            if hasattr(self._parse,"_originalParseMethod"):
+                self._parse = self._parse._originalParseMethod
+        return self
+
+    def setParseAction( self, *fns, **kwargs ):
+        """
+        Define one or more actions to perform when successfully matching parse element definition.
+        Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)},
+        C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where:
+         - s   = the original string being parsed (see note below)
+         - loc = the location of the matching substring
+         - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object
+        If the functions in fns modify the tokens, they can return them as the return
+        value from fn, and the modified list of tokens will replace the original.
+        Otherwise, fn does not need to return any value.
+
+        Optional keyword arguments:
+         - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing
+
+        Note: the default parsing behavior is to expand tabs in the input string
+        before starting the parsing process.  See L{I{parseString}} for more information
+        on parsing strings containing C{}s, and suggested methods to maintain a
+        consistent view of the parsed string, the parse location, and line and column
+        positions within the parsed string.
+        
+        Example::
+            integer = Word(nums)
+            date_str = integer + '/' + integer + '/' + integer
+
+            date_str.parseString("1999/12/31")  # -> ['1999', '/', '12', '/', '31']
+
+            # use parse action to convert to ints at parse time
+            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
+            date_str = integer + '/' + integer + '/' + integer
+
+            # note that integer fields are now ints, not strings
+            date_str.parseString("1999/12/31")  # -> [1999, '/', 12, '/', 31]
+        """
+        self.parseAction = list(map(_trim_arity, list(fns)))
+        self.callDuringTry = kwargs.get("callDuringTry", False)
+        return self
+
+    def addParseAction( self, *fns, **kwargs ):
+        """
+        Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}}.
+        
+        See examples in L{I{copy}}.
+        """
+        self.parseAction += list(map(_trim_arity, list(fns)))
+        self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False)
+        return self
+
+    def addCondition(self, *fns, **kwargs):
+        """Add a boolean predicate function to expression's list of parse actions. See 
+        L{I{setParseAction}} for function call signatures. Unlike C{setParseAction}, 
+        functions passed to C{addCondition} need to return boolean success/fail of the condition.
+
+        Optional keyword arguments:
+         - message = define a custom message to be used in the raised exception
+         - fatal   = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException
+         
+        Example::
+            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
+            year_int = integer.copy()
+            year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later")
+            date_str = year_int + '/' + integer + '/' + integer
+
+            result = date_str.parseString("1999/12/31")  # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1)
+        """
+        msg = kwargs.get("message", "failed user-defined condition")
+        exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException
+        for fn in fns:
+            def pa(s,l,t):
+                if not bool(_trim_arity(fn)(s,l,t)):
+                    raise exc_type(s,l,msg)
+            self.parseAction.append(pa)
+        self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False)
+        return self
+
+    def setFailAction( self, fn ):
+        """Define action to perform if parsing fails at this expression.
+           Fail acton fn is a callable function that takes the arguments
+           C{fn(s,loc,expr,err)} where:
+            - s = string being parsed
+            - loc = location where expression match was attempted and failed
+            - expr = the parse expression that failed
+            - err = the exception thrown
+           The function returns no value.  It may throw C{L{ParseFatalException}}
+           if it is desired to stop parsing immediately."""
+        self.failAction = fn
+        return self
+
+    def _skipIgnorables( self, instring, loc ):
+        exprsFound = True
+        while exprsFound:
+            exprsFound = False
+            for e in self.ignoreExprs:
+                try:
+                    while 1:
+                        loc,dummy = e._parse( instring, loc )
+                        exprsFound = True
+                except ParseException:
+                    pass
+        return loc
+
+    def preParse( self, instring, loc ):
+        if self.ignoreExprs:
+            loc = self._skipIgnorables( instring, loc )
+
+        if self.skipWhitespace:
+            wt = self.whiteChars
+            instrlen = len(instring)
+            while loc < instrlen and instring[loc] in wt:
+                loc += 1
+
+        return loc
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        return loc, []
+
+    def postParse( self, instring, loc, tokenlist ):
+        return tokenlist
+
+    #~ @profile
+    def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ):
+        debugging = ( self.debug ) #and doActions )
+
+        if debugging or self.failAction:
+            #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))
+            if (self.debugActions[0] ):
+                self.debugActions[0]( instring, loc, self )
+            if callPreParse and self.callPreparse:
+                preloc = self.preParse( instring, loc )
+            else:
+                preloc = loc
+            tokensStart = preloc
+            try:
+                try:
+                    loc,tokens = self.parseImpl( instring, preloc, doActions )
+                except IndexError:
+                    raise ParseException( instring, len(instring), self.errmsg, self )
+            except ParseBaseException as err:
+                #~ print ("Exception raised:", err)
+                if self.debugActions[2]:
+                    self.debugActions[2]( instring, tokensStart, self, err )
+                if self.failAction:
+                    self.failAction( instring, tokensStart, self, err )
+                raise
+        else:
+            if callPreParse and self.callPreparse:
+                preloc = self.preParse( instring, loc )
+            else:
+                preloc = loc
+            tokensStart = preloc
+            if self.mayIndexError or preloc >= len(instring):
+                try:
+                    loc,tokens = self.parseImpl( instring, preloc, doActions )
+                except IndexError:
+                    raise ParseException( instring, len(instring), self.errmsg, self )
+            else:
+                loc,tokens = self.parseImpl( instring, preloc, doActions )
+
+        tokens = self.postParse( instring, loc, tokens )
+
+        retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults )
+        if self.parseAction and (doActions or self.callDuringTry):
+            if debugging:
+                try:
+                    for fn in self.parseAction:
+                        tokens = fn( instring, tokensStart, retTokens )
+                        if tokens is not None:
+                            retTokens = ParseResults( tokens,
+                                                      self.resultsName,
+                                                      asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
+                                                      modal=self.modalResults )
+                except ParseBaseException as err:
+                    #~ print "Exception raised in user parse action:", err
+                    if (self.debugActions[2] ):
+                        self.debugActions[2]( instring, tokensStart, self, err )
+                    raise
+            else:
+                for fn in self.parseAction:
+                    tokens = fn( instring, tokensStart, retTokens )
+                    if tokens is not None:
+                        retTokens = ParseResults( tokens,
+                                                  self.resultsName,
+                                                  asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
+                                                  modal=self.modalResults )
+        if debugging:
+            #~ print ("Matched",self,"->",retTokens.asList())
+            if (self.debugActions[1] ):
+                self.debugActions[1]( instring, tokensStart, loc, self, retTokens )
+
+        return loc, retTokens
+
+    def tryParse( self, instring, loc ):
+        try:
+            return self._parse( instring, loc, doActions=False )[0]
+        except ParseFatalException:
+            raise ParseException( instring, loc, self.errmsg, self)
+    
+    def canParseNext(self, instring, loc):
+        try:
+            self.tryParse(instring, loc)
+        except (ParseException, IndexError):
+            return False
+        else:
+            return True
+
+    class _UnboundedCache(object):
+        def __init__(self):
+            cache = {}
+            self.not_in_cache = not_in_cache = object()
+
+            def get(self, key):
+                return cache.get(key, not_in_cache)
+
+            def set(self, key, value):
+                cache[key] = value
+
+            def clear(self):
+                cache.clear()
+                
+            def cache_len(self):
+                return len(cache)
+
+            self.get = types.MethodType(get, self)
+            self.set = types.MethodType(set, self)
+            self.clear = types.MethodType(clear, self)
+            self.__len__ = types.MethodType(cache_len, self)
+
+    if _OrderedDict is not None:
+        class _FifoCache(object):
+            def __init__(self, size):
+                self.not_in_cache = not_in_cache = object()
+
+                cache = _OrderedDict()
+
+                def get(self, key):
+                    return cache.get(key, not_in_cache)
+
+                def set(self, key, value):
+                    cache[key] = value
+                    while len(cache) > size:
+                        try:
+                            cache.popitem(False)
+                        except KeyError:
+                            pass
+
+                def clear(self):
+                    cache.clear()
+
+                def cache_len(self):
+                    return len(cache)
+
+                self.get = types.MethodType(get, self)
+                self.set = types.MethodType(set, self)
+                self.clear = types.MethodType(clear, self)
+                self.__len__ = types.MethodType(cache_len, self)
+
+    else:
+        class _FifoCache(object):
+            def __init__(self, size):
+                self.not_in_cache = not_in_cache = object()
+
+                cache = {}
+                key_fifo = collections.deque([], size)
+
+                def get(self, key):
+                    return cache.get(key, not_in_cache)
+
+                def set(self, key, value):
+                    cache[key] = value
+                    while len(key_fifo) > size:
+                        cache.pop(key_fifo.popleft(), None)
+                    key_fifo.append(key)
+
+                def clear(self):
+                    cache.clear()
+                    key_fifo.clear()
+
+                def cache_len(self):
+                    return len(cache)
+
+                self.get = types.MethodType(get, self)
+                self.set = types.MethodType(set, self)
+                self.clear = types.MethodType(clear, self)
+                self.__len__ = types.MethodType(cache_len, self)
+
+    # argument cache for optimizing repeated calls when backtracking through recursive expressions
+    packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail
+    packrat_cache_lock = RLock()
+    packrat_cache_stats = [0, 0]
+
+    # this method gets repeatedly called during backtracking with the same arguments -
+    # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression
+    def _parseCache( self, instring, loc, doActions=True, callPreParse=True ):
+        HIT, MISS = 0, 1
+        lookup = (self, instring, loc, callPreParse, doActions)
+        with ParserElement.packrat_cache_lock:
+            cache = ParserElement.packrat_cache
+            value = cache.get(lookup)
+            if value is cache.not_in_cache:
+                ParserElement.packrat_cache_stats[MISS] += 1
+                try:
+                    value = self._parseNoCache(instring, loc, doActions, callPreParse)
+                except ParseBaseException as pe:
+                    # cache a copy of the exception, without the traceback
+                    cache.set(lookup, pe.__class__(*pe.args))
+                    raise
+                else:
+                    cache.set(lookup, (value[0], value[1].copy()))
+                    return value
+            else:
+                ParserElement.packrat_cache_stats[HIT] += 1
+                if isinstance(value, Exception):
+                    raise value
+                return (value[0], value[1].copy())
+
+    _parse = _parseNoCache
+
+    @staticmethod
+    def resetCache():
+        ParserElement.packrat_cache.clear()
+        ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats)
+
+    _packratEnabled = False
+    @staticmethod
+    def enablePackrat(cache_size_limit=128):
+        """Enables "packrat" parsing, which adds memoizing to the parsing logic.
+           Repeated parse attempts at the same string location (which happens
+           often in many complex grammars) can immediately return a cached value,
+           instead of re-executing parsing/validating code.  Memoizing is done of
+           both valid results and parsing exceptions.
+           
+           Parameters:
+            - cache_size_limit - (default=C{128}) - if an integer value is provided
+              will limit the size of the packrat cache; if None is passed, then
+              the cache size will be unbounded; if 0 is passed, the cache will
+              be effectively disabled.
+            
+           This speedup may break existing programs that use parse actions that
+           have side-effects.  For this reason, packrat parsing is disabled when
+           you first import pyparsing.  To activate the packrat feature, your
+           program must call the class method C{ParserElement.enablePackrat()}.  If
+           your program uses C{psyco} to "compile as you go", you must call
+           C{enablePackrat} before calling C{psyco.full()}.  If you do not do this,
+           Python will crash.  For best results, call C{enablePackrat()} immediately
+           after importing pyparsing.
+           
+           Example::
+               import pyparsing
+               pyparsing.ParserElement.enablePackrat()
+        """
+        if not ParserElement._packratEnabled:
+            ParserElement._packratEnabled = True
+            if cache_size_limit is None:
+                ParserElement.packrat_cache = ParserElement._UnboundedCache()
+            else:
+                ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit)
+            ParserElement._parse = ParserElement._parseCache
+
+    def parseString( self, instring, parseAll=False ):
+        """
+        Execute the parse expression with the given string.
+        This is the main interface to the client code, once the complete
+        expression has been built.
+
+        If you want the grammar to require that the entire input string be
+        successfully parsed, then set C{parseAll} to True (equivalent to ending
+        the grammar with C{L{StringEnd()}}).
+
+        Note: C{parseString} implicitly calls C{expandtabs()} on the input string,
+        in order to report proper column numbers in parse actions.
+        If the input string contains tabs and
+        the grammar uses parse actions that use the C{loc} argument to index into the
+        string being parsed, you can ensure you have a consistent view of the input
+        string by:
+         - calling C{parseWithTabs} on your grammar before calling C{parseString}
+           (see L{I{parseWithTabs}})
+         - define your parse action using the full C{(s,loc,toks)} signature, and
+           reference the input string using the parse action's C{s} argument
+         - explictly expand the tabs in your input string before calling
+           C{parseString}
+        
+        Example::
+            Word('a').parseString('aaaaabaaa')  # -> ['aaaaa']
+            Word('a').parseString('aaaaabaaa', parseAll=True)  # -> Exception: Expected end of text
+        """
+        ParserElement.resetCache()
+        if not self.streamlined:
+            self.streamline()
+            #~ self.saveAsList = True
+        for e in self.ignoreExprs:
+            e.streamline()
+        if not self.keepTabs:
+            instring = instring.expandtabs()
+        try:
+            loc, tokens = self._parse( instring, 0 )
+            if parseAll:
+                loc = self.preParse( instring, loc )
+                se = Empty() + StringEnd()
+                se._parse( instring, loc )
+        except ParseBaseException as exc:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                raise exc
+        else:
+            return tokens
+
+    def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ):
+        """
+        Scan the input string for expression matches.  Each match will return the
+        matching tokens, start location, and end location.  May be called with optional
+        C{maxMatches} argument, to clip scanning after 'n' matches are found.  If
+        C{overlap} is specified, then overlapping matches will be reported.
+
+        Note that the start and end locations are reported relative to the string
+        being parsed.  See L{I{parseString}} for more information on parsing
+        strings with embedded tabs.
+
+        Example::
+            source = "sldjf123lsdjjkf345sldkjf879lkjsfd987"
+            print(source)
+            for tokens,start,end in Word(alphas).scanString(source):
+                print(' '*start + '^'*(end-start))
+                print(' '*start + tokens[0])
+        
+        prints::
+        
+            sldjf123lsdjjkf345sldkjf879lkjsfd987
+            ^^^^^
+            sldjf
+                    ^^^^^^^
+                    lsdjjkf
+                              ^^^^^^
+                              sldkjf
+                                       ^^^^^^
+                                       lkjsfd
+        """
+        if not self.streamlined:
+            self.streamline()
+        for e in self.ignoreExprs:
+            e.streamline()
+
+        if not self.keepTabs:
+            instring = _ustr(instring).expandtabs()
+        instrlen = len(instring)
+        loc = 0
+        preparseFn = self.preParse
+        parseFn = self._parse
+        ParserElement.resetCache()
+        matches = 0
+        try:
+            while loc <= instrlen and matches < maxMatches:
+                try:
+                    preloc = preparseFn( instring, loc )
+                    nextLoc,tokens = parseFn( instring, preloc, callPreParse=False )
+                except ParseException:
+                    loc = preloc+1
+                else:
+                    if nextLoc > loc:
+                        matches += 1
+                        yield tokens, preloc, nextLoc
+                        if overlap:
+                            nextloc = preparseFn( instring, loc )
+                            if nextloc > loc:
+                                loc = nextLoc
+                            else:
+                                loc += 1
+                        else:
+                            loc = nextLoc
+                    else:
+                        loc = preloc+1
+        except ParseBaseException as exc:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                raise exc
+
+    def transformString( self, instring ):
+        """
+        Extension to C{L{scanString}}, to modify matching text with modified tokens that may
+        be returned from a parse action.  To use C{transformString}, define a grammar and
+        attach a parse action to it that modifies the returned token list.
+        Invoking C{transformString()} on a target string will then scan for matches,
+        and replace the matched text patterns according to the logic in the parse
+        action.  C{transformString()} returns the resulting transformed string.
+        
+        Example::
+            wd = Word(alphas)
+            wd.setParseAction(lambda toks: toks[0].title())
+            
+            print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york."))
+        Prints::
+            Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York.
+        """
+        out = []
+        lastE = 0
+        # force preservation of s, to minimize unwanted transformation of string, and to
+        # keep string locs straight between transformString and scanString
+        self.keepTabs = True
+        try:
+            for t,s,e in self.scanString( instring ):
+                out.append( instring[lastE:s] )
+                if t:
+                    if isinstance(t,ParseResults):
+                        out += t.asList()
+                    elif isinstance(t,list):
+                        out += t
+                    else:
+                        out.append(t)
+                lastE = e
+            out.append(instring[lastE:])
+            out = [o for o in out if o]
+            return "".join(map(_ustr,_flatten(out)))
+        except ParseBaseException as exc:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                raise exc
+
+    def searchString( self, instring, maxMatches=_MAX_INT ):
+        """
+        Another extension to C{L{scanString}}, simplifying the access to the tokens found
+        to match the given parse expression.  May be called with optional
+        C{maxMatches} argument, to clip searching after 'n' matches are found.
+        
+        Example::
+            # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters
+            cap_word = Word(alphas.upper(), alphas.lower())
+            
+            print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))
+
+            # the sum() builtin can be used to merge results into a single ParseResults object
+            print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")))
+        prints::
+            [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']]
+            ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity']
+        """
+        try:
+            return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ])
+        except ParseBaseException as exc:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                raise exc
+
+    def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False):
+        """
+        Generator method to split a string using the given expression as a separator.
+        May be called with optional C{maxsplit} argument, to limit the number of splits;
+        and the optional C{includeSeparators} argument (default=C{False}), if the separating
+        matching text should be included in the split results.
+        
+        Example::        
+            punc = oneOf(list(".,;:/-!?"))
+            print(list(punc.split("This, this?, this sentence, is badly punctuated!")))
+        prints::
+            ['This', ' this', '', ' this sentence', ' is badly punctuated', '']
+        """
+        splits = 0
+        last = 0
+        for t,s,e in self.scanString(instring, maxMatches=maxsplit):
+            yield instring[last:s]
+            if includeSeparators:
+                yield t[0]
+            last = e
+        yield instring[last:]
+
+    def __add__(self, other ):
+        """
+        Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement
+        converts them to L{Literal}s by default.
+        
+        Example::
+            greet = Word(alphas) + "," + Word(alphas) + "!"
+            hello = "Hello, World!"
+            print (hello, "->", greet.parseString(hello))
+        Prints::
+            Hello, World! -> ['Hello', ',', 'World', '!']
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return And( [ self, other ] )
+
+    def __radd__(self, other ):
+        """
+        Implementation of + operator when left operand is not a C{L{ParserElement}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other + self
+
+    def __sub__(self, other):
+        """
+        Implementation of - operator, returns C{L{And}} with error stop
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return self + And._ErrorStop() + other
+
+    def __rsub__(self, other ):
+        """
+        Implementation of - operator when left operand is not a C{L{ParserElement}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other - self
+
+    def __mul__(self,other):
+        """
+        Implementation of * operator, allows use of C{expr * 3} in place of
+        C{expr + expr + expr}.  Expressions may also me multiplied by a 2-integer
+        tuple, similar to C{{min,max}} multipliers in regular expressions.  Tuples
+        may also include C{None} as in:
+         - C{expr*(n,None)} or C{expr*(n,)} is equivalent
+              to C{expr*n + L{ZeroOrMore}(expr)}
+              (read as "at least n instances of C{expr}")
+         - C{expr*(None,n)} is equivalent to C{expr*(0,n)}
+              (read as "0 to n instances of C{expr}")
+         - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)}
+         - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)}
+
+        Note that C{expr*(None,n)} does not raise an exception if
+        more than n exprs exist in the input stream; that is,
+        C{expr*(None,n)} does not enforce a maximum number of expr
+        occurrences.  If this behavior is desired, then write
+        C{expr*(None,n) + ~expr}
+        """
+        if isinstance(other,int):
+            minElements, optElements = other,0
+        elif isinstance(other,tuple):
+            other = (other + (None, None))[:2]
+            if other[0] is None:
+                other = (0, other[1])
+            if isinstance(other[0],int) and other[1] is None:
+                if other[0] == 0:
+                    return ZeroOrMore(self)
+                if other[0] == 1:
+                    return OneOrMore(self)
+                else:
+                    return self*other[0] + ZeroOrMore(self)
+            elif isinstance(other[0],int) and isinstance(other[1],int):
+                minElements, optElements = other
+                optElements -= minElements
+            else:
+                raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1]))
+        else:
+            raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other))
+
+        if minElements < 0:
+            raise ValueError("cannot multiply ParserElement by negative value")
+        if optElements < 0:
+            raise ValueError("second tuple value must be greater or equal to first tuple value")
+        if minElements == optElements == 0:
+            raise ValueError("cannot multiply ParserElement by 0 or (0,0)")
+
+        if (optElements):
+            def makeOptionalList(n):
+                if n>1:
+                    return Optional(self + makeOptionalList(n-1))
+                else:
+                    return Optional(self)
+            if minElements:
+                if minElements == 1:
+                    ret = self + makeOptionalList(optElements)
+                else:
+                    ret = And([self]*minElements) + makeOptionalList(optElements)
+            else:
+                ret = makeOptionalList(optElements)
+        else:
+            if minElements == 1:
+                ret = self
+            else:
+                ret = And([self]*minElements)
+        return ret
+
+    def __rmul__(self, other):
+        return self.__mul__(other)
+
+    def __or__(self, other ):
+        """
+        Implementation of | operator - returns C{L{MatchFirst}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return MatchFirst( [ self, other ] )
+
+    def __ror__(self, other ):
+        """
+        Implementation of | operator when left operand is not a C{L{ParserElement}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other | self
+
+    def __xor__(self, other ):
+        """
+        Implementation of ^ operator - returns C{L{Or}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return Or( [ self, other ] )
+
+    def __rxor__(self, other ):
+        """
+        Implementation of ^ operator when left operand is not a C{L{ParserElement}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other ^ self
+
+    def __and__(self, other ):
+        """
+        Implementation of & operator - returns C{L{Each}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return Each( [ self, other ] )
+
+    def __rand__(self, other ):
+        """
+        Implementation of & operator when left operand is not a C{L{ParserElement}}
+        """
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        if not isinstance( other, ParserElement ):
+            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
+                    SyntaxWarning, stacklevel=2)
+            return None
+        return other & self
+
+    def __invert__( self ):
+        """
+        Implementation of ~ operator - returns C{L{NotAny}}
+        """
+        return NotAny( self )
+
+    def __call__(self, name=None):
+        """
+        Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}.
+        
+        If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be
+        passed as C{True}.
+           
+        If C{name} is omitted, same as calling C{L{copy}}.
+
+        Example::
+            # these are equivalent
+            userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno")
+            userdata = Word(alphas)("name") + Word(nums+"-")("socsecno")             
+        """
+        if name is not None:
+            return self.setResultsName(name)
+        else:
+            return self.copy()
+
+    def suppress( self ):
+        """
+        Suppresses the output of this C{ParserElement}; useful to keep punctuation from
+        cluttering up returned output.
+        """
+        return Suppress( self )
+
+    def leaveWhitespace( self ):
+        """
+        Disables the skipping of whitespace before matching the characters in the
+        C{ParserElement}'s defined pattern.  This is normally only used internally by
+        the pyparsing module, but may be needed in some whitespace-sensitive grammars.
+        """
+        self.skipWhitespace = False
+        return self
+
+    def setWhitespaceChars( self, chars ):
+        """
+        Overrides the default whitespace chars
+        """
+        self.skipWhitespace = True
+        self.whiteChars = chars
+        self.copyDefaultWhiteChars = False
+        return self
+
+    def parseWithTabs( self ):
+        """
+        Overrides default behavior to expand C{}s to spaces before parsing the input string.
+        Must be called before C{parseString} when the input grammar contains elements that
+        match C{} characters.
+        """
+        self.keepTabs = True
+        return self
+
+    def ignore( self, other ):
+        """
+        Define expression to be ignored (e.g., comments) while doing pattern
+        matching; may be called repeatedly, to define multiple comment or other
+        ignorable patterns.
+        
+        Example::
+            patt = OneOrMore(Word(alphas))
+            patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj']
+            
+            patt.ignore(cStyleComment)
+            patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd']
+        """
+        if isinstance(other, basestring):
+            other = Suppress(other)
+
+        if isinstance( other, Suppress ):
+            if other not in self.ignoreExprs:
+                self.ignoreExprs.append(other)
+        else:
+            self.ignoreExprs.append( Suppress( other.copy() ) )
+        return self
+
+    def setDebugActions( self, startAction, successAction, exceptionAction ):
+        """
+        Enable display of debugging messages while doing pattern matching.
+        """
+        self.debugActions = (startAction or _defaultStartDebugAction,
+                             successAction or _defaultSuccessDebugAction,
+                             exceptionAction or _defaultExceptionDebugAction)
+        self.debug = True
+        return self
+
+    def setDebug( self, flag=True ):
+        """
+        Enable display of debugging messages while doing pattern matching.
+        Set C{flag} to True to enable, False to disable.
+
+        Example::
+            wd = Word(alphas).setName("alphaword")
+            integer = Word(nums).setName("numword")
+            term = wd | integer
+            
+            # turn on debugging for wd
+            wd.setDebug()
+
+            OneOrMore(term).parseString("abc 123 xyz 890")
+        
+        prints::
+            Match alphaword at loc 0(1,1)
+            Matched alphaword -> ['abc']
+            Match alphaword at loc 3(1,4)
+            Exception raised:Expected alphaword (at char 4), (line:1, col:5)
+            Match alphaword at loc 7(1,8)
+            Matched alphaword -> ['xyz']
+            Match alphaword at loc 11(1,12)
+            Exception raised:Expected alphaword (at char 12), (line:1, col:13)
+            Match alphaword at loc 15(1,16)
+            Exception raised:Expected alphaword (at char 15), (line:1, col:16)
+
+        The output shown is that produced by the default debug actions - custom debug actions can be
+        specified using L{setDebugActions}. Prior to attempting
+        to match the C{wd} expression, the debugging message C{"Match  at loc (,)"}
+        is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"}
+        message is shown. Also note the use of L{setName} to assign a human-readable name to the expression,
+        which makes debugging and exception messages easier to understand - for instance, the default
+        name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}.
+        """
+        if flag:
+            self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction )
+        else:
+            self.debug = False
+        return self
+
+    def __str__( self ):
+        return self.name
+
+    def __repr__( self ):
+        return _ustr(self)
+
+    def streamline( self ):
+        self.streamlined = True
+        self.strRepr = None
+        return self
+
+    def checkRecursion( self, parseElementList ):
+        pass
+
+    def validate( self, validateTrace=[] ):
+        """
+        Check defined expressions for valid structure, check for infinite recursive definitions.
+        """
+        self.checkRecursion( [] )
+
+    def parseFile( self, file_or_filename, parseAll=False ):
+        """
+        Execute the parse expression on the given file or filename.
+        If a filename is specified (instead of a file object),
+        the entire file is opened, read, and closed before parsing.
+        """
+        try:
+            file_contents = file_or_filename.read()
+        except AttributeError:
+            with open(file_or_filename, "r") as f:
+                file_contents = f.read()
+        try:
+            return self.parseString(file_contents, parseAll)
+        except ParseBaseException as exc:
+            if ParserElement.verbose_stacktrace:
+                raise
+            else:
+                # catch and re-raise exception from here, clears out pyparsing internal stack trace
+                raise exc
+
+    def __eq__(self,other):
+        if isinstance(other, ParserElement):
+            return self is other or vars(self) == vars(other)
+        elif isinstance(other, basestring):
+            return self.matches(other)
+        else:
+            return super(ParserElement,self)==other
+
+    def __ne__(self,other):
+        return not (self == other)
+
+    def __hash__(self):
+        return hash(id(self))
+
+    def __req__(self,other):
+        return self == other
+
+    def __rne__(self,other):
+        return not (self == other)
+
+    def matches(self, testString, parseAll=True):
+        """
+        Method for quick testing of a parser against a test string. Good for simple 
+        inline microtests of sub expressions while building up larger parser.
+           
+        Parameters:
+         - testString - to test against this expression for a match
+         - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests
+            
+        Example::
+            expr = Word(nums)
+            assert expr.matches("100")
+        """
+        try:
+            self.parseString(_ustr(testString), parseAll=parseAll)
+            return True
+        except ParseBaseException:
+            return False
+                
+    def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False):
+        """
+        Execute the parse expression on a series of test strings, showing each
+        test, the parsed results or where the parse failed. Quick and easy way to
+        run a parse expression against a list of sample strings.
+           
+        Parameters:
+         - tests - a list of separate test strings, or a multiline string of test strings
+         - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests           
+         - comment - (default=C{'#'}) - expression for indicating embedded comments in the test 
+              string; pass None to disable comment filtering
+         - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline;
+              if False, only dump nested list
+         - printResults - (default=C{True}) prints test output to stdout
+         - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing
+
+        Returns: a (success, results) tuple, where success indicates that all tests succeeded
+        (or failed if C{failureTests} is True), and the results contain a list of lines of each 
+        test's output
+        
+        Example::
+            number_expr = pyparsing_common.number.copy()
+
+            result = number_expr.runTests('''
+                # unsigned integer
+                100
+                # negative integer
+                -100
+                # float with scientific notation
+                6.02e23
+                # integer with scientific notation
+                1e-12
+                ''')
+            print("Success" if result[0] else "Failed!")
+
+            result = number_expr.runTests('''
+                # stray character
+                100Z
+                # missing leading digit before '.'
+                -.100
+                # too many '.'
+                3.14.159
+                ''', failureTests=True)
+            print("Success" if result[0] else "Failed!")
+        prints::
+            # unsigned integer
+            100
+            [100]
+
+            # negative integer
+            -100
+            [-100]
+
+            # float with scientific notation
+            6.02e23
+            [6.02e+23]
+
+            # integer with scientific notation
+            1e-12
+            [1e-12]
+
+            Success
+            
+            # stray character
+            100Z
+               ^
+            FAIL: Expected end of text (at char 3), (line:1, col:4)
+
+            # missing leading digit before '.'
+            -.100
+            ^
+            FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1)
+
+            # too many '.'
+            3.14.159
+                ^
+            FAIL: Expected end of text (at char 4), (line:1, col:5)
+
+            Success
+
+        Each test string must be on a single line. If you want to test a string that spans multiple
+        lines, create a test like this::
+
+            expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines")
+        
+        (Note that this is a raw string literal, you must include the leading 'r'.)
+        """
+        if isinstance(tests, basestring):
+            tests = list(map(str.strip, tests.rstrip().splitlines()))
+        if isinstance(comment, basestring):
+            comment = Literal(comment)
+        allResults = []
+        comments = []
+        success = True
+        for t in tests:
+            if comment is not None and comment.matches(t, False) or comments and not t:
+                comments.append(t)
+                continue
+            if not t:
+                continue
+            out = ['\n'.join(comments), t]
+            comments = []
+            try:
+                t = t.replace(r'\n','\n')
+                result = self.parseString(t, parseAll=parseAll)
+                out.append(result.dump(full=fullDump))
+                success = success and not failureTests
+            except ParseBaseException as pe:
+                fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else ""
+                if '\n' in t:
+                    out.append(line(pe.loc, t))
+                    out.append(' '*(col(pe.loc,t)-1) + '^' + fatal)
+                else:
+                    out.append(' '*pe.loc + '^' + fatal)
+                out.append("FAIL: " + str(pe))
+                success = success and failureTests
+                result = pe
+            except Exception as exc:
+                out.append("FAIL-EXCEPTION: " + str(exc))
+                success = success and failureTests
+                result = exc
+
+            if printResults:
+                if fullDump:
+                    out.append('')
+                print('\n'.join(out))
+
+            allResults.append((t, result))
+        
+        return success, allResults
+
+        
+class Token(ParserElement):
+    """
+    Abstract C{ParserElement} subclass, for defining atomic matching patterns.
+    """
+    def __init__( self ):
+        super(Token,self).__init__( savelist=False )
+
+
+class Empty(Token):
+    """
+    An empty token, will always match.
+    """
+    def __init__( self ):
+        super(Empty,self).__init__()
+        self.name = "Empty"
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+
+
+class NoMatch(Token):
+    """
+    A token that will never match.
+    """
+    def __init__( self ):
+        super(NoMatch,self).__init__()
+        self.name = "NoMatch"
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+        self.errmsg = "Unmatchable token"
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        raise ParseException(instring, loc, self.errmsg, self)
+
+
+class Literal(Token):
+    """
+    Token to exactly match a specified string.
+    
+    Example::
+        Literal('blah').parseString('blah')  # -> ['blah']
+        Literal('blah').parseString('blahfooblah')  # -> ['blah']
+        Literal('blah').parseString('bla')  # -> Exception: Expected "blah"
+    
+    For case-insensitive matching, use L{CaselessLiteral}.
+    
+    For keyword matching (force word break before and after the matched string),
+    use L{Keyword} or L{CaselessKeyword}.
+    """
+    def __init__( self, matchString ):
+        super(Literal,self).__init__()
+        self.match = matchString
+        self.matchLen = len(matchString)
+        try:
+            self.firstMatchChar = matchString[0]
+        except IndexError:
+            warnings.warn("null string passed to Literal; use Empty() instead",
+                            SyntaxWarning, stacklevel=2)
+            self.__class__ = Empty
+        self.name = '"%s"' % _ustr(self.match)
+        self.errmsg = "Expected " + self.name
+        self.mayReturnEmpty = False
+        self.mayIndexError = False
+
+    # Performance tuning: this routine gets called a *lot*
+    # if this is a single character match string  and the first character matches,
+    # short-circuit as quickly as possible, and avoid calling startswith
+    #~ @profile
+    def parseImpl( self, instring, loc, doActions=True ):
+        if (instring[loc] == self.firstMatchChar and
+            (self.matchLen==1 or instring.startswith(self.match,loc)) ):
+            return loc+self.matchLen, self.match
+        raise ParseException(instring, loc, self.errmsg, self)
+_L = Literal
+ParserElement._literalStringClass = Literal
+
+class Keyword(Token):
+    """
+    Token to exactly match a specified string as a keyword, that is, it must be
+    immediately followed by a non-keyword character.  Compare with C{L{Literal}}:
+     - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}.
+     - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'}
+    Accepts two optional constructor arguments in addition to the keyword string:
+     - C{identChars} is a string of characters that would be valid identifier characters,
+          defaulting to all alphanumerics + "_" and "$"
+     - C{caseless} allows case-insensitive matching, default is C{False}.
+       
+    Example::
+        Keyword("start").parseString("start")  # -> ['start']
+        Keyword("start").parseString("starting")  # -> Exception
+
+    For case-insensitive matching, use L{CaselessKeyword}.
+    """
+    DEFAULT_KEYWORD_CHARS = alphanums+"_$"
+
+    def __init__( self, matchString, identChars=None, caseless=False ):
+        super(Keyword,self).__init__()
+        if identChars is None:
+            identChars = Keyword.DEFAULT_KEYWORD_CHARS
+        self.match = matchString
+        self.matchLen = len(matchString)
+        try:
+            self.firstMatchChar = matchString[0]
+        except IndexError:
+            warnings.warn("null string passed to Keyword; use Empty() instead",
+                            SyntaxWarning, stacklevel=2)
+        self.name = '"%s"' % self.match
+        self.errmsg = "Expected " + self.name
+        self.mayReturnEmpty = False
+        self.mayIndexError = False
+        self.caseless = caseless
+        if caseless:
+            self.caselessmatch = matchString.upper()
+            identChars = identChars.upper()
+        self.identChars = set(identChars)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.caseless:
+            if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
+                 (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and
+                 (loc == 0 or instring[loc-1].upper() not in self.identChars) ):
+                return loc+self.matchLen, self.match
+        else:
+            if (instring[loc] == self.firstMatchChar and
+                (self.matchLen==1 or instring.startswith(self.match,loc)) and
+                (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and
+                (loc == 0 or instring[loc-1] not in self.identChars) ):
+                return loc+self.matchLen, self.match
+        raise ParseException(instring, loc, self.errmsg, self)
+
+    def copy(self):
+        c = super(Keyword,self).copy()
+        c.identChars = Keyword.DEFAULT_KEYWORD_CHARS
+        return c
+
+    @staticmethod
+    def setDefaultKeywordChars( chars ):
+        """Overrides the default Keyword chars
+        """
+        Keyword.DEFAULT_KEYWORD_CHARS = chars
+
+class CaselessLiteral(Literal):
+    """
+    Token to match a specified string, ignoring case of letters.
+    Note: the matched results will always be in the case of the given
+    match string, NOT the case of the input text.
+
+    Example::
+        OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD']
+        
+    (Contrast with example for L{CaselessKeyword}.)
+    """
+    def __init__( self, matchString ):
+        super(CaselessLiteral,self).__init__( matchString.upper() )
+        # Preserve the defining literal.
+        self.returnString = matchString
+        self.name = "'%s'" % self.returnString
+        self.errmsg = "Expected " + self.name
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if instring[ loc:loc+self.matchLen ].upper() == self.match:
+            return loc+self.matchLen, self.returnString
+        raise ParseException(instring, loc, self.errmsg, self)
+
+class CaselessKeyword(Keyword):
+    """
+    Caseless version of L{Keyword}.
+
+    Example::
+        OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD']
+        
+    (Contrast with example for L{CaselessLiteral}.)
+    """
+    def __init__( self, matchString, identChars=None ):
+        super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True )
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
+             (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ):
+            return loc+self.matchLen, self.match
+        raise ParseException(instring, loc, self.errmsg, self)
+
+class CloseMatch(Token):
+    """
+    A variation on L{Literal} which matches "close" matches, that is, 
+    strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters:
+     - C{match_string} - string to be matched
+     - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match
+    
+    The results from a successful parse will contain the matched text from the input string and the following named results:
+     - C{mismatches} - a list of the positions within the match_string where mismatches were found
+     - C{original} - the original match_string used to compare against the input string
+    
+    If C{mismatches} is an empty list, then the match was an exact match.
+    
+    Example::
+        patt = CloseMatch("ATCATCGAATGGA")
+        patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']})
+        patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1)
+
+        # exact match
+        patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']})
+
+        # close match allowing up to 2 mismatches
+        patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2)
+        patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']})
+    """
+    def __init__(self, match_string, maxMismatches=1):
+        super(CloseMatch,self).__init__()
+        self.name = match_string
+        self.match_string = match_string
+        self.maxMismatches = maxMismatches
+        self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches)
+        self.mayIndexError = False
+        self.mayReturnEmpty = False
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        start = loc
+        instrlen = len(instring)
+        maxloc = start + len(self.match_string)
+
+        if maxloc <= instrlen:
+            match_string = self.match_string
+            match_stringloc = 0
+            mismatches = []
+            maxMismatches = self.maxMismatches
+
+            for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)):
+                src,mat = s_m
+                if src != mat:
+                    mismatches.append(match_stringloc)
+                    if len(mismatches) > maxMismatches:
+                        break
+            else:
+                loc = match_stringloc + 1
+                results = ParseResults([instring[start:loc]])
+                results['original'] = self.match_string
+                results['mismatches'] = mismatches
+                return loc, results
+
+        raise ParseException(instring, loc, self.errmsg, self)
+
+
+class Word(Token):
+    """
+    Token for matching words composed of allowed character sets.
+    Defined with string containing all allowed initial characters,
+    an optional string containing allowed body characters (if omitted,
+    defaults to the initial character set), and an optional minimum,
+    maximum, and/or exact length.  The default value for C{min} is 1 (a
+    minimum value < 1 is not valid); the default values for C{max} and C{exact}
+    are 0, meaning no maximum or exact length restriction. An optional
+    C{excludeChars} parameter can list characters that might be found in 
+    the input C{bodyChars} string; useful to define a word of all printables
+    except for one or two characters, for instance.
+    
+    L{srange} is useful for defining custom character set strings for defining 
+    C{Word} expressions, using range notation from regular expression character sets.
+    
+    A common mistake is to use C{Word} to match a specific literal string, as in 
+    C{Word("Address")}. Remember that C{Word} uses the string argument to define
+    I{sets} of matchable characters. This expression would match "Add", "AAA",
+    "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'.
+    To match an exact literal string, use L{Literal} or L{Keyword}.
+
+    pyparsing includes helper strings for building Words:
+     - L{alphas}
+     - L{nums}
+     - L{alphanums}
+     - L{hexnums}
+     - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.)
+     - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.)
+     - L{printables} (any non-whitespace character)
+
+    Example::
+        # a word composed of digits
+        integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9"))
+        
+        # a word with a leading capital, and zero or more lowercase
+        capital_word = Word(alphas.upper(), alphas.lower())
+
+        # hostnames are alphanumeric, with leading alpha, and '-'
+        hostname = Word(alphas, alphanums+'-')
+        
+        # roman numeral (not a strict parser, accepts invalid mix of characters)
+        roman = Word("IVXLCDM")
+        
+        # any string of non-whitespace characters, except for ','
+        csv_value = Word(printables, excludeChars=",")
+    """
+    def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ):
+        super(Word,self).__init__()
+        if excludeChars:
+            initChars = ''.join(c for c in initChars if c not in excludeChars)
+            if bodyChars:
+                bodyChars = ''.join(c for c in bodyChars if c not in excludeChars)
+        self.initCharsOrig = initChars
+        self.initChars = set(initChars)
+        if bodyChars :
+            self.bodyCharsOrig = bodyChars
+            self.bodyChars = set(bodyChars)
+        else:
+            self.bodyCharsOrig = initChars
+            self.bodyChars = set(initChars)
+
+        self.maxSpecified = max > 0
+
+        if min < 1:
+            raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted")
+
+        self.minLen = min
+
+        if max > 0:
+            self.maxLen = max
+        else:
+            self.maxLen = _MAX_INT
+
+        if exact > 0:
+            self.maxLen = exact
+            self.minLen = exact
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayIndexError = False
+        self.asKeyword = asKeyword
+
+        if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0):
+            if self.bodyCharsOrig == self.initCharsOrig:
+                self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig)
+            elif len(self.initCharsOrig) == 1:
+                self.reString = "%s[%s]*" % \
+                                      (re.escape(self.initCharsOrig),
+                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
+            else:
+                self.reString = "[%s][%s]*" % \
+                                      (_escapeRegexRangeChars(self.initCharsOrig),
+                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
+            if self.asKeyword:
+                self.reString = r"\b"+self.reString+r"\b"
+            try:
+                self.re = re.compile( self.reString )
+            except Exception:
+                self.re = None
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.re:
+            result = self.re.match(instring,loc)
+            if not result:
+                raise ParseException(instring, loc, self.errmsg, self)
+
+            loc = result.end()
+            return loc, result.group()
+
+        if not(instring[ loc ] in self.initChars):
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        start = loc
+        loc += 1
+        instrlen = len(instring)
+        bodychars = self.bodyChars
+        maxloc = start + self.maxLen
+        maxloc = min( maxloc, instrlen )
+        while loc < maxloc and instring[loc] in bodychars:
+            loc += 1
+
+        throwException = False
+        if loc - start < self.minLen:
+            throwException = True
+        if self.maxSpecified and loc < instrlen and instring[loc] in bodychars:
+            throwException = True
+        if self.asKeyword:
+            if (start>0 and instring[start-1] in bodychars) or (loc4:
+                    return s[:4]+"..."
+                else:
+                    return s
+
+            if ( self.initCharsOrig != self.bodyCharsOrig ):
+                self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) )
+            else:
+                self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig)
+
+        return self.strRepr
+
+
+class Regex(Token):
+    r"""
+    Token for matching strings that match a given regular expression.
+    Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module.
+    If the given regex contains named groups (defined using C{(?P...)}), these will be preserved as 
+    named parse results.
+
+    Example::
+        realnum = Regex(r"[+-]?\d+\.\d*")
+        date = Regex(r'(?P\d{4})-(?P\d\d?)-(?P\d\d?)')
+        # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression
+        roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})")
+    """
+    compiledREtype = type(re.compile("[A-Z]"))
+    def __init__( self, pattern, flags=0):
+        """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags."""
+        super(Regex,self).__init__()
+
+        if isinstance(pattern, basestring):
+            if not pattern:
+                warnings.warn("null string passed to Regex; use Empty() instead",
+                        SyntaxWarning, stacklevel=2)
+
+            self.pattern = pattern
+            self.flags = flags
+
+            try:
+                self.re = re.compile(self.pattern, self.flags)
+                self.reString = self.pattern
+            except sre_constants.error:
+                warnings.warn("invalid pattern (%s) passed to Regex" % pattern,
+                    SyntaxWarning, stacklevel=2)
+                raise
+
+        elif isinstance(pattern, Regex.compiledREtype):
+            self.re = pattern
+            self.pattern = \
+            self.reString = str(pattern)
+            self.flags = flags
+            
+        else:
+            raise ValueError("Regex may only be constructed with a string or a compiled RE object")
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayIndexError = False
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        result = self.re.match(instring,loc)
+        if not result:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        loc = result.end()
+        d = result.groupdict()
+        ret = ParseResults(result.group())
+        if d:
+            for k in d:
+                ret[k] = d[k]
+        return loc,ret
+
+    def __str__( self ):
+        try:
+            return super(Regex,self).__str__()
+        except Exception:
+            pass
+
+        if self.strRepr is None:
+            self.strRepr = "Re:(%s)" % repr(self.pattern)
+
+        return self.strRepr
+
+
+class QuotedString(Token):
+    r"""
+    Token for matching strings that are delimited by quoting characters.
+    
+    Defined with the following parameters:
+        - quoteChar - string of one or more characters defining the quote delimiting string
+        - escChar - character to escape quotes, typically backslash (default=C{None})
+        - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None})
+        - multiline - boolean indicating whether quotes can span multiple lines (default=C{False})
+        - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True})
+        - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar)
+        - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True})
+
+    Example::
+        qs = QuotedString('"')
+        print(qs.searchString('lsjdf "This is the quote" sldjf'))
+        complex_qs = QuotedString('{{', endQuoteChar='}}')
+        print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf'))
+        sql_qs = QuotedString('"', escQuote='""')
+        print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf'))
+    prints::
+        [['This is the quote']]
+        [['This is the "quote"']]
+        [['This is the quote with "embedded" quotes']]
+    """
+    def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True):
+        super(QuotedString,self).__init__()
+
+        # remove white space from quote chars - wont work anyway
+        quoteChar = quoteChar.strip()
+        if not quoteChar:
+            warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
+            raise SyntaxError()
+
+        if endQuoteChar is None:
+            endQuoteChar = quoteChar
+        else:
+            endQuoteChar = endQuoteChar.strip()
+            if not endQuoteChar:
+                warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
+                raise SyntaxError()
+
+        self.quoteChar = quoteChar
+        self.quoteCharLen = len(quoteChar)
+        self.firstQuoteChar = quoteChar[0]
+        self.endQuoteChar = endQuoteChar
+        self.endQuoteCharLen = len(endQuoteChar)
+        self.escChar = escChar
+        self.escQuote = escQuote
+        self.unquoteResults = unquoteResults
+        self.convertWhitespaceEscapes = convertWhitespaceEscapes
+
+        if multiline:
+            self.flags = re.MULTILINE | re.DOTALL
+            self.pattern = r'%s(?:[^%s%s]' % \
+                ( re.escape(self.quoteChar),
+                  _escapeRegexRangeChars(self.endQuoteChar[0]),
+                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
+        else:
+            self.flags = 0
+            self.pattern = r'%s(?:[^%s\n\r%s]' % \
+                ( re.escape(self.quoteChar),
+                  _escapeRegexRangeChars(self.endQuoteChar[0]),
+                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
+        if len(self.endQuoteChar) > 1:
+            self.pattern += (
+                '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]),
+                                               _escapeRegexRangeChars(self.endQuoteChar[i]))
+                                    for i in range(len(self.endQuoteChar)-1,0,-1)) + ')'
+                )
+        if escQuote:
+            self.pattern += (r'|(?:%s)' % re.escape(escQuote))
+        if escChar:
+            self.pattern += (r'|(?:%s.)' % re.escape(escChar))
+            self.escCharReplacePattern = re.escape(self.escChar)+"(.)"
+        self.pattern += (r')*%s' % re.escape(self.endQuoteChar))
+
+        try:
+            self.re = re.compile(self.pattern, self.flags)
+            self.reString = self.pattern
+        except sre_constants.error:
+            warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern,
+                SyntaxWarning, stacklevel=2)
+            raise
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayIndexError = False
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None
+        if not result:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        loc = result.end()
+        ret = result.group()
+
+        if self.unquoteResults:
+
+            # strip off quotes
+            ret = ret[self.quoteCharLen:-self.endQuoteCharLen]
+
+            if isinstance(ret,basestring):
+                # replace escaped whitespace
+                if '\\' in ret and self.convertWhitespaceEscapes:
+                    ws_map = {
+                        r'\t' : '\t',
+                        r'\n' : '\n',
+                        r'\f' : '\f',
+                        r'\r' : '\r',
+                    }
+                    for wslit,wschar in ws_map.items():
+                        ret = ret.replace(wslit, wschar)
+
+                # replace escaped characters
+                if self.escChar:
+                    ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret)
+
+                # replace escaped quotes
+                if self.escQuote:
+                    ret = ret.replace(self.escQuote, self.endQuoteChar)
+
+        return loc, ret
+
+    def __str__( self ):
+        try:
+            return super(QuotedString,self).__str__()
+        except Exception:
+            pass
+
+        if self.strRepr is None:
+            self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar)
+
+        return self.strRepr
+
+
+class CharsNotIn(Token):
+    """
+    Token for matching words composed of characters I{not} in a given set (will
+    include whitespace in matched characters if not listed in the provided exclusion set - see example).
+    Defined with string containing all disallowed characters, and an optional
+    minimum, maximum, and/or exact length.  The default value for C{min} is 1 (a
+    minimum value < 1 is not valid); the default values for C{max} and C{exact}
+    are 0, meaning no maximum or exact length restriction.
+
+    Example::
+        # define a comma-separated-value as anything that is not a ','
+        csv_value = CharsNotIn(',')
+        print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213"))
+    prints::
+        ['dkls', 'lsdkjf', 's12 34', '@!#', '213']
+    """
+    def __init__( self, notChars, min=1, max=0, exact=0 ):
+        super(CharsNotIn,self).__init__()
+        self.skipWhitespace = False
+        self.notChars = notChars
+
+        if min < 1:
+            raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted")
+
+        self.minLen = min
+
+        if max > 0:
+            self.maxLen = max
+        else:
+            self.maxLen = _MAX_INT
+
+        if exact > 0:
+            self.maxLen = exact
+            self.minLen = exact
+
+        self.name = _ustr(self)
+        self.errmsg = "Expected " + self.name
+        self.mayReturnEmpty = ( self.minLen == 0 )
+        self.mayIndexError = False
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if instring[loc] in self.notChars:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        start = loc
+        loc += 1
+        notchars = self.notChars
+        maxlen = min( start+self.maxLen, len(instring) )
+        while loc < maxlen and \
+              (instring[loc] not in notchars):
+            loc += 1
+
+        if loc - start < self.minLen:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        return loc, instring[start:loc]
+
+    def __str__( self ):
+        try:
+            return super(CharsNotIn, self).__str__()
+        except Exception:
+            pass
+
+        if self.strRepr is None:
+            if len(self.notChars) > 4:
+                self.strRepr = "!W:(%s...)" % self.notChars[:4]
+            else:
+                self.strRepr = "!W:(%s)" % self.notChars
+
+        return self.strRepr
+
+class White(Token):
+    """
+    Special matching class for matching whitespace.  Normally, whitespace is ignored
+    by pyparsing grammars.  This class is included when some whitespace structures
+    are significant.  Define with a string containing the whitespace characters to be
+    matched; default is C{" \\t\\r\\n"}.  Also takes optional C{min}, C{max}, and C{exact} arguments,
+    as defined for the C{L{Word}} class.
+    """
+    whiteStrs = {
+        " " : "",
+        "\t": "",
+        "\n": "",
+        "\r": "",
+        "\f": "",
+        }
+    def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0):
+        super(White,self).__init__()
+        self.matchWhite = ws
+        self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) )
+        #~ self.leaveWhitespace()
+        self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite))
+        self.mayReturnEmpty = True
+        self.errmsg = "Expected " + self.name
+
+        self.minLen = min
+
+        if max > 0:
+            self.maxLen = max
+        else:
+            self.maxLen = _MAX_INT
+
+        if exact > 0:
+            self.maxLen = exact
+            self.minLen = exact
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if not(instring[ loc ] in self.matchWhite):
+            raise ParseException(instring, loc, self.errmsg, self)
+        start = loc
+        loc += 1
+        maxloc = start + self.maxLen
+        maxloc = min( maxloc, len(instring) )
+        while loc < maxloc and instring[loc] in self.matchWhite:
+            loc += 1
+
+        if loc - start < self.minLen:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        return loc, instring[start:loc]
+
+
+class _PositionToken(Token):
+    def __init__( self ):
+        super(_PositionToken,self).__init__()
+        self.name=self.__class__.__name__
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+
+class GoToColumn(_PositionToken):
+    """
+    Token to advance to a specific column of input text; useful for tabular report scraping.
+    """
+    def __init__( self, colno ):
+        super(GoToColumn,self).__init__()
+        self.col = colno
+
+    def preParse( self, instring, loc ):
+        if col(loc,instring) != self.col:
+            instrlen = len(instring)
+            if self.ignoreExprs:
+                loc = self._skipIgnorables( instring, loc )
+            while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col :
+                loc += 1
+        return loc
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        thiscol = col( loc, instring )
+        if thiscol > self.col:
+            raise ParseException( instring, loc, "Text not in expected column", self )
+        newloc = loc + self.col - thiscol
+        ret = instring[ loc: newloc ]
+        return newloc, ret
+
+
+class LineStart(_PositionToken):
+    """
+    Matches if current position is at the beginning of a line within the parse string
+    
+    Example::
+    
+        test = '''\
+        AAA this line
+        AAA and this line
+          AAA but not this one
+        B AAA and definitely not this one
+        '''
+
+        for t in (LineStart() + 'AAA' + restOfLine).searchString(test):
+            print(t)
+    
+    Prints::
+        ['AAA', ' this line']
+        ['AAA', ' and this line']    
+
+    """
+    def __init__( self ):
+        super(LineStart,self).__init__()
+        self.errmsg = "Expected start of line"
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if col(loc, instring) == 1:
+            return loc, []
+        raise ParseException(instring, loc, self.errmsg, self)
+
+class LineEnd(_PositionToken):
+    """
+    Matches if current position is at the end of a line within the parse string
+    """
+    def __init__( self ):
+        super(LineEnd,self).__init__()
+        self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") )
+        self.errmsg = "Expected end of line"
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if loc len(instring):
+            return loc, []
+        else:
+            raise ParseException(instring, loc, self.errmsg, self)
+
+class WordStart(_PositionToken):
+    """
+    Matches if the current position is at the beginning of a Word, and
+    is not preceded by any character in a given set of C{wordChars}
+    (default=C{printables}). To emulate the C{\b} behavior of regular expressions,
+    use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of
+    the string being parsed, or at the beginning of a line.
+    """
+    def __init__(self, wordChars = printables):
+        super(WordStart,self).__init__()
+        self.wordChars = set(wordChars)
+        self.errmsg = "Not at the start of a word"
+
+    def parseImpl(self, instring, loc, doActions=True ):
+        if loc != 0:
+            if (instring[loc-1] in self.wordChars or
+                instring[loc] not in self.wordChars):
+                raise ParseException(instring, loc, self.errmsg, self)
+        return loc, []
+
+class WordEnd(_PositionToken):
+    """
+    Matches if the current position is at the end of a Word, and
+    is not followed by any character in a given set of C{wordChars}
+    (default=C{printables}). To emulate the C{\b} behavior of regular expressions,
+    use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of
+    the string being parsed, or at the end of a line.
+    """
+    def __init__(self, wordChars = printables):
+        super(WordEnd,self).__init__()
+        self.wordChars = set(wordChars)
+        self.skipWhitespace = False
+        self.errmsg = "Not at the end of a word"
+
+    def parseImpl(self, instring, loc, doActions=True ):
+        instrlen = len(instring)
+        if instrlen>0 and loc maxExcLoc:
+                    maxException = err
+                    maxExcLoc = err.loc
+            except IndexError:
+                if len(instring) > maxExcLoc:
+                    maxException = ParseException(instring,len(instring),e.errmsg,self)
+                    maxExcLoc = len(instring)
+            else:
+                # save match among all matches, to retry longest to shortest
+                matches.append((loc2, e))
+
+        if matches:
+            matches.sort(key=lambda x: -x[0])
+            for _,e in matches:
+                try:
+                    return e._parse( instring, loc, doActions )
+                except ParseException as err:
+                    err.__traceback__ = None
+                    if err.loc > maxExcLoc:
+                        maxException = err
+                        maxExcLoc = err.loc
+
+        if maxException is not None:
+            maxException.msg = self.errmsg
+            raise maxException
+        else:
+            raise ParseException(instring, loc, "no defined alternatives to match", self)
+
+
+    def __ixor__(self, other ):
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        return self.append( other ) #Or( [ self, other ] )
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}"
+
+        return self.strRepr
+
+    def checkRecursion( self, parseElementList ):
+        subRecCheckList = parseElementList[:] + [ self ]
+        for e in self.exprs:
+            e.checkRecursion( subRecCheckList )
+
+
+class MatchFirst(ParseExpression):
+    """
+    Requires that at least one C{ParseExpression} is found.
+    If two expressions match, the first one listed is the one that will match.
+    May be constructed using the C{'|'} operator.
+
+    Example::
+        # construct MatchFirst using '|' operator
+        
+        # watch the order of expressions to match
+        number = Word(nums) | Combine(Word(nums) + '.' + Word(nums))
+        print(number.searchString("123 3.1416 789")) #  Fail! -> [['123'], ['3'], ['1416'], ['789']]
+
+        # put more selective expression first
+        number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums)
+        print(number.searchString("123 3.1416 789")) #  Better -> [['123'], ['3.1416'], ['789']]
+    """
+    def __init__( self, exprs, savelist = False ):
+        super(MatchFirst,self).__init__(exprs, savelist)
+        if self.exprs:
+            self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs)
+        else:
+            self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        maxExcLoc = -1
+        maxException = None
+        for e in self.exprs:
+            try:
+                ret = e._parse( instring, loc, doActions )
+                return ret
+            except ParseException as err:
+                if err.loc > maxExcLoc:
+                    maxException = err
+                    maxExcLoc = err.loc
+            except IndexError:
+                if len(instring) > maxExcLoc:
+                    maxException = ParseException(instring,len(instring),e.errmsg,self)
+                    maxExcLoc = len(instring)
+
+        # only got here if no expression matched, raise exception for match that made it the furthest
+        else:
+            if maxException is not None:
+                maxException.msg = self.errmsg
+                raise maxException
+            else:
+                raise ParseException(instring, loc, "no defined alternatives to match", self)
+
+    def __ior__(self, other ):
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass( other )
+        return self.append( other ) #MatchFirst( [ self, other ] )
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}"
+
+        return self.strRepr
+
+    def checkRecursion( self, parseElementList ):
+        subRecCheckList = parseElementList[:] + [ self ]
+        for e in self.exprs:
+            e.checkRecursion( subRecCheckList )
+
+
+class Each(ParseExpression):
+    """
+    Requires all given C{ParseExpression}s to be found, but in any order.
+    Expressions may be separated by whitespace.
+    May be constructed using the C{'&'} operator.
+
+    Example::
+        color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN")
+        shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON")
+        integer = Word(nums)
+        shape_attr = "shape:" + shape_type("shape")
+        posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn")
+        color_attr = "color:" + color("color")
+        size_attr = "size:" + integer("size")
+
+        # use Each (using operator '&') to accept attributes in any order 
+        # (shape and posn are required, color and size are optional)
+        shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr)
+
+        shape_spec.runTests('''
+            shape: SQUARE color: BLACK posn: 100, 120
+            shape: CIRCLE size: 50 color: BLUE posn: 50,80
+            color:GREEN size:20 shape:TRIANGLE posn:20,40
+            '''
+            )
+    prints::
+        shape: SQUARE color: BLACK posn: 100, 120
+        ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']]
+        - color: BLACK
+        - posn: ['100', ',', '120']
+          - x: 100
+          - y: 120
+        - shape: SQUARE
+
+
+        shape: CIRCLE size: 50 color: BLUE posn: 50,80
+        ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']]
+        - color: BLUE
+        - posn: ['50', ',', '80']
+          - x: 50
+          - y: 80
+        - shape: CIRCLE
+        - size: 50
+
+
+        color: GREEN size: 20 shape: TRIANGLE posn: 20,40
+        ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']]
+        - color: GREEN
+        - posn: ['20', ',', '40']
+          - x: 20
+          - y: 40
+        - shape: TRIANGLE
+        - size: 20
+    """
+    def __init__( self, exprs, savelist = True ):
+        super(Each,self).__init__(exprs, savelist)
+        self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs)
+        self.skipWhitespace = True
+        self.initExprGroups = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.initExprGroups:
+            self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional))
+            opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ]
+            opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)]
+            self.optionals = opt1 + opt2
+            self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ]
+            self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ]
+            self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ]
+            self.required += self.multirequired
+            self.initExprGroups = False
+        tmpLoc = loc
+        tmpReqd = self.required[:]
+        tmpOpt  = self.optionals[:]
+        matchOrder = []
+
+        keepMatching = True
+        while keepMatching:
+            tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired
+            failed = []
+            for e in tmpExprs:
+                try:
+                    tmpLoc = e.tryParse( instring, tmpLoc )
+                except ParseException:
+                    failed.append(e)
+                else:
+                    matchOrder.append(self.opt1map.get(id(e),e))
+                    if e in tmpReqd:
+                        tmpReqd.remove(e)
+                    elif e in tmpOpt:
+                        tmpOpt.remove(e)
+            if len(failed) == len(tmpExprs):
+                keepMatching = False
+
+        if tmpReqd:
+            missing = ", ".join(_ustr(e) for e in tmpReqd)
+            raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing )
+
+        # add any unmatched Optionals, in case they have default values defined
+        matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt]
+
+        resultlist = []
+        for e in matchOrder:
+            loc,results = e._parse(instring,loc,doActions)
+            resultlist.append(results)
+
+        finalResults = sum(resultlist, ParseResults([]))
+        return loc, finalResults
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}"
+
+        return self.strRepr
+
+    def checkRecursion( self, parseElementList ):
+        subRecCheckList = parseElementList[:] + [ self ]
+        for e in self.exprs:
+            e.checkRecursion( subRecCheckList )
+
+
+class ParseElementEnhance(ParserElement):
+    """
+    Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens.
+    """
+    def __init__( self, expr, savelist=False ):
+        super(ParseElementEnhance,self).__init__(savelist)
+        if isinstance( expr, basestring ):
+            if issubclass(ParserElement._literalStringClass, Token):
+                expr = ParserElement._literalStringClass(expr)
+            else:
+                expr = ParserElement._literalStringClass(Literal(expr))
+        self.expr = expr
+        self.strRepr = None
+        if expr is not None:
+            self.mayIndexError = expr.mayIndexError
+            self.mayReturnEmpty = expr.mayReturnEmpty
+            self.setWhitespaceChars( expr.whiteChars )
+            self.skipWhitespace = expr.skipWhitespace
+            self.saveAsList = expr.saveAsList
+            self.callPreparse = expr.callPreparse
+            self.ignoreExprs.extend(expr.ignoreExprs)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.expr is not None:
+            return self.expr._parse( instring, loc, doActions, callPreParse=False )
+        else:
+            raise ParseException("",loc,self.errmsg,self)
+
+    def leaveWhitespace( self ):
+        self.skipWhitespace = False
+        self.expr = self.expr.copy()
+        if self.expr is not None:
+            self.expr.leaveWhitespace()
+        return self
+
+    def ignore( self, other ):
+        if isinstance( other, Suppress ):
+            if other not in self.ignoreExprs:
+                super( ParseElementEnhance, self).ignore( other )
+                if self.expr is not None:
+                    self.expr.ignore( self.ignoreExprs[-1] )
+        else:
+            super( ParseElementEnhance, self).ignore( other )
+            if self.expr is not None:
+                self.expr.ignore( self.ignoreExprs[-1] )
+        return self
+
+    def streamline( self ):
+        super(ParseElementEnhance,self).streamline()
+        if self.expr is not None:
+            self.expr.streamline()
+        return self
+
+    def checkRecursion( self, parseElementList ):
+        if self in parseElementList:
+            raise RecursiveGrammarException( parseElementList+[self] )
+        subRecCheckList = parseElementList[:] + [ self ]
+        if self.expr is not None:
+            self.expr.checkRecursion( subRecCheckList )
+
+    def validate( self, validateTrace=[] ):
+        tmp = validateTrace[:]+[self]
+        if self.expr is not None:
+            self.expr.validate(tmp)
+        self.checkRecursion( [] )
+
+    def __str__( self ):
+        try:
+            return super(ParseElementEnhance,self).__str__()
+        except Exception:
+            pass
+
+        if self.strRepr is None and self.expr is not None:
+            self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) )
+        return self.strRepr
+
+
+class FollowedBy(ParseElementEnhance):
+    """
+    Lookahead matching of the given parse expression.  C{FollowedBy}
+    does I{not} advance the parsing position within the input string, it only
+    verifies that the specified parse expression matches at the current
+    position.  C{FollowedBy} always returns a null token list.
+
+    Example::
+        # use FollowedBy to match a label only if it is followed by a ':'
+        data_word = Word(alphas)
+        label = data_word + FollowedBy(':')
+        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
+        
+        OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint()
+    prints::
+        [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']]
+    """
+    def __init__( self, expr ):
+        super(FollowedBy,self).__init__(expr)
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        self.expr.tryParse( instring, loc )
+        return loc, []
+
+
+class NotAny(ParseElementEnhance):
+    """
+    Lookahead to disallow matching with the given parse expression.  C{NotAny}
+    does I{not} advance the parsing position within the input string, it only
+    verifies that the specified parse expression does I{not} match at the current
+    position.  Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny}
+    always returns a null token list.  May be constructed using the '~' operator.
+
+    Example::
+        
+    """
+    def __init__( self, expr ):
+        super(NotAny,self).__init__(expr)
+        #~ self.leaveWhitespace()
+        self.skipWhitespace = False  # do NOT use self.leaveWhitespace(), don't want to propagate to exprs
+        self.mayReturnEmpty = True
+        self.errmsg = "Found unwanted token, "+_ustr(self.expr)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        if self.expr.canParseNext(instring, loc):
+            raise ParseException(instring, loc, self.errmsg, self)
+        return loc, []
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "~{" + _ustr(self.expr) + "}"
+
+        return self.strRepr
+
+class _MultipleMatch(ParseElementEnhance):
+    def __init__( self, expr, stopOn=None):
+        super(_MultipleMatch, self).__init__(expr)
+        self.saveAsList = True
+        ender = stopOn
+        if isinstance(ender, basestring):
+            ender = ParserElement._literalStringClass(ender)
+        self.not_ender = ~ender if ender is not None else None
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        self_expr_parse = self.expr._parse
+        self_skip_ignorables = self._skipIgnorables
+        check_ender = self.not_ender is not None
+        if check_ender:
+            try_not_ender = self.not_ender.tryParse
+        
+        # must be at least one (but first see if we are the stopOn sentinel;
+        # if so, fail)
+        if check_ender:
+            try_not_ender(instring, loc)
+        loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False )
+        try:
+            hasIgnoreExprs = (not not self.ignoreExprs)
+            while 1:
+                if check_ender:
+                    try_not_ender(instring, loc)
+                if hasIgnoreExprs:
+                    preloc = self_skip_ignorables( instring, loc )
+                else:
+                    preloc = loc
+                loc, tmptokens = self_expr_parse( instring, preloc, doActions )
+                if tmptokens or tmptokens.haskeys():
+                    tokens += tmptokens
+        except (ParseException,IndexError):
+            pass
+
+        return loc, tokens
+        
+class OneOrMore(_MultipleMatch):
+    """
+    Repetition of one or more of the given expression.
+    
+    Parameters:
+     - expr - expression that must match one or more times
+     - stopOn - (default=C{None}) - expression for a terminating sentinel
+          (only required if the sentinel would ordinarily match the repetition 
+          expression)          
+
+    Example::
+        data_word = Word(alphas)
+        label = data_word + FollowedBy(':')
+        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join))
+
+        text = "shape: SQUARE posn: upper left color: BLACK"
+        OneOrMore(attr_expr).parseString(text).pprint()  # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']]
+
+        # use stopOn attribute for OneOrMore to avoid reading label string as part of the data
+        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
+        OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']]
+        
+        # could also be written as
+        (attr_expr * (1,)).parseString(text).pprint()
+    """
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "{" + _ustr(self.expr) + "}..."
+
+        return self.strRepr
+
+class ZeroOrMore(_MultipleMatch):
+    """
+    Optional repetition of zero or more of the given expression.
+    
+    Parameters:
+     - expr - expression that must match zero or more times
+     - stopOn - (default=C{None}) - expression for a terminating sentinel
+          (only required if the sentinel would ordinarily match the repetition 
+          expression)          
+
+    Example: similar to L{OneOrMore}
+    """
+    def __init__( self, expr, stopOn=None):
+        super(ZeroOrMore,self).__init__(expr, stopOn=stopOn)
+        self.mayReturnEmpty = True
+        
+    def parseImpl( self, instring, loc, doActions=True ):
+        try:
+            return super(ZeroOrMore, self).parseImpl(instring, loc, doActions)
+        except (ParseException,IndexError):
+            return loc, []
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "[" + _ustr(self.expr) + "]..."
+
+        return self.strRepr
+
+class _NullToken(object):
+    def __bool__(self):
+        return False
+    __nonzero__ = __bool__
+    def __str__(self):
+        return ""
+
+_optionalNotMatched = _NullToken()
+class Optional(ParseElementEnhance):
+    """
+    Optional matching of the given expression.
+
+    Parameters:
+     - expr - expression that must match zero or more times
+     - default (optional) - value to be returned if the optional expression is not found.
+
+    Example::
+        # US postal code can be a 5-digit zip, plus optional 4-digit qualifier
+        zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4)))
+        zip.runTests('''
+            # traditional ZIP code
+            12345
+            
+            # ZIP+4 form
+            12101-0001
+            
+            # invalid ZIP
+            98765-
+            ''')
+    prints::
+        # traditional ZIP code
+        12345
+        ['12345']
+
+        # ZIP+4 form
+        12101-0001
+        ['12101-0001']
+
+        # invalid ZIP
+        98765-
+             ^
+        FAIL: Expected end of text (at char 5), (line:1, col:6)
+    """
+    def __init__( self, expr, default=_optionalNotMatched ):
+        super(Optional,self).__init__( expr, savelist=False )
+        self.saveAsList = self.expr.saveAsList
+        self.defaultValue = default
+        self.mayReturnEmpty = True
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        try:
+            loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
+        except (ParseException,IndexError):
+            if self.defaultValue is not _optionalNotMatched:
+                if self.expr.resultsName:
+                    tokens = ParseResults([ self.defaultValue ])
+                    tokens[self.expr.resultsName] = self.defaultValue
+                else:
+                    tokens = [ self.defaultValue ]
+            else:
+                tokens = []
+        return loc, tokens
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+
+        if self.strRepr is None:
+            self.strRepr = "[" + _ustr(self.expr) + "]"
+
+        return self.strRepr
+
+class SkipTo(ParseElementEnhance):
+    """
+    Token for skipping over all undefined text until the matched expression is found.
+
+    Parameters:
+     - expr - target expression marking the end of the data to be skipped
+     - include - (default=C{False}) if True, the target expression is also parsed 
+          (the skipped text and target expression are returned as a 2-element list).
+     - ignore - (default=C{None}) used to define grammars (typically quoted strings and 
+          comments) that might contain false matches to the target expression
+     - failOn - (default=C{None}) define expressions that are not allowed to be 
+          included in the skipped test; if found before the target expression is found, 
+          the SkipTo is not a match
+
+    Example::
+        report = '''
+            Outstanding Issues Report - 1 Jan 2000
+
+               # | Severity | Description                               |  Days Open
+            -----+----------+-------------------------------------------+-----------
+             101 | Critical | Intermittent system crash                 |          6
+              94 | Cosmetic | Spelling error on Login ('log|n')         |         14
+              79 | Minor    | System slow when running too many reports |         47
+            '''
+        integer = Word(nums)
+        SEP = Suppress('|')
+        # use SkipTo to simply match everything up until the next SEP
+        # - ignore quoted strings, so that a '|' character inside a quoted string does not match
+        # - parse action will call token.strip() for each matched token, i.e., the description body
+        string_data = SkipTo(SEP, ignore=quotedString)
+        string_data.setParseAction(tokenMap(str.strip))
+        ticket_expr = (integer("issue_num") + SEP 
+                      + string_data("sev") + SEP 
+                      + string_data("desc") + SEP 
+                      + integer("days_open"))
+        
+        for tkt in ticket_expr.searchString(report):
+            print tkt.dump()
+    prints::
+        ['101', 'Critical', 'Intermittent system crash', '6']
+        - days_open: 6
+        - desc: Intermittent system crash
+        - issue_num: 101
+        - sev: Critical
+        ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14']
+        - days_open: 14
+        - desc: Spelling error on Login ('log|n')
+        - issue_num: 94
+        - sev: Cosmetic
+        ['79', 'Minor', 'System slow when running too many reports', '47']
+        - days_open: 47
+        - desc: System slow when running too many reports
+        - issue_num: 79
+        - sev: Minor
+    """
+    def __init__( self, other, include=False, ignore=None, failOn=None ):
+        super( SkipTo, self ).__init__( other )
+        self.ignoreExpr = ignore
+        self.mayReturnEmpty = True
+        self.mayIndexError = False
+        self.includeMatch = include
+        self.asList = False
+        if isinstance(failOn, basestring):
+            self.failOn = ParserElement._literalStringClass(failOn)
+        else:
+            self.failOn = failOn
+        self.errmsg = "No match found for "+_ustr(self.expr)
+
+    def parseImpl( self, instring, loc, doActions=True ):
+        startloc = loc
+        instrlen = len(instring)
+        expr = self.expr
+        expr_parse = self.expr._parse
+        self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None
+        self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None
+        
+        tmploc = loc
+        while tmploc <= instrlen:
+            if self_failOn_canParseNext is not None:
+                # break if failOn expression matches
+                if self_failOn_canParseNext(instring, tmploc):
+                    break
+                    
+            if self_ignoreExpr_tryParse is not None:
+                # advance past ignore expressions
+                while 1:
+                    try:
+                        tmploc = self_ignoreExpr_tryParse(instring, tmploc)
+                    except ParseBaseException:
+                        break
+            
+            try:
+                expr_parse(instring, tmploc, doActions=False, callPreParse=False)
+            except (ParseException, IndexError):
+                # no match, advance loc in string
+                tmploc += 1
+            else:
+                # matched skipto expr, done
+                break
+
+        else:
+            # ran off the end of the input string without matching skipto expr, fail
+            raise ParseException(instring, loc, self.errmsg, self)
+
+        # build up return values
+        loc = tmploc
+        skiptext = instring[startloc:loc]
+        skipresult = ParseResults(skiptext)
+        
+        if self.includeMatch:
+            loc, mat = expr_parse(instring,loc,doActions,callPreParse=False)
+            skipresult += mat
+
+        return loc, skipresult
+
+class Forward(ParseElementEnhance):
+    """
+    Forward declaration of an expression to be defined later -
+    used for recursive grammars, such as algebraic infix notation.
+    When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator.
+
+    Note: take care when assigning to C{Forward} not to overlook precedence of operators.
+    Specifically, '|' has a lower precedence than '<<', so that::
+        fwdExpr << a | b | c
+    will actually be evaluated as::
+        (fwdExpr << a) | b | c
+    thereby leaving b and c out as parseable alternatives.  It is recommended that you
+    explicitly group the values inserted into the C{Forward}::
+        fwdExpr << (a | b | c)
+    Converting to use the '<<=' operator instead will avoid this problem.
+
+    See L{ParseResults.pprint} for an example of a recursive parser created using
+    C{Forward}.
+    """
+    def __init__( self, other=None ):
+        super(Forward,self).__init__( other, savelist=False )
+
+    def __lshift__( self, other ):
+        if isinstance( other, basestring ):
+            other = ParserElement._literalStringClass(other)
+        self.expr = other
+        self.strRepr = None
+        self.mayIndexError = self.expr.mayIndexError
+        self.mayReturnEmpty = self.expr.mayReturnEmpty
+        self.setWhitespaceChars( self.expr.whiteChars )
+        self.skipWhitespace = self.expr.skipWhitespace
+        self.saveAsList = self.expr.saveAsList
+        self.ignoreExprs.extend(self.expr.ignoreExprs)
+        return self
+        
+    def __ilshift__(self, other):
+        return self << other
+    
+    def leaveWhitespace( self ):
+        self.skipWhitespace = False
+        return self
+
+    def streamline( self ):
+        if not self.streamlined:
+            self.streamlined = True
+            if self.expr is not None:
+                self.expr.streamline()
+        return self
+
+    def validate( self, validateTrace=[] ):
+        if self not in validateTrace:
+            tmp = validateTrace[:]+[self]
+            if self.expr is not None:
+                self.expr.validate(tmp)
+        self.checkRecursion([])
+
+    def __str__( self ):
+        if hasattr(self,"name"):
+            return self.name
+        return self.__class__.__name__ + ": ..."
+
+        # stubbed out for now - creates awful memory and perf issues
+        self._revertClass = self.__class__
+        self.__class__ = _ForwardNoRecurse
+        try:
+            if self.expr is not None:
+                retString = _ustr(self.expr)
+            else:
+                retString = "None"
+        finally:
+            self.__class__ = self._revertClass
+        return self.__class__.__name__ + ": " + retString
+
+    def copy(self):
+        if self.expr is not None:
+            return super(Forward,self).copy()
+        else:
+            ret = Forward()
+            ret <<= self
+            return ret
+
+class _ForwardNoRecurse(Forward):
+    def __str__( self ):
+        return "..."
+
+class TokenConverter(ParseElementEnhance):
+    """
+    Abstract subclass of C{ParseExpression}, for converting parsed results.
+    """
+    def __init__( self, expr, savelist=False ):
+        super(TokenConverter,self).__init__( expr )#, savelist )
+        self.saveAsList = False
+
+class Combine(TokenConverter):
+    """
+    Converter to concatenate all matching tokens to a single string.
+    By default, the matching patterns must also be contiguous in the input string;
+    this can be disabled by specifying C{'adjacent=False'} in the constructor.
+
+    Example::
+        real = Word(nums) + '.' + Word(nums)
+        print(real.parseString('3.1416')) # -> ['3', '.', '1416']
+        # will also erroneously match the following
+        print(real.parseString('3. 1416')) # -> ['3', '.', '1416']
+
+        real = Combine(Word(nums) + '.' + Word(nums))
+        print(real.parseString('3.1416')) # -> ['3.1416']
+        # no match when there are internal spaces
+        print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...)
+    """
+    def __init__( self, expr, joinString="", adjacent=True ):
+        super(Combine,self).__init__( expr )
+        # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself
+        if adjacent:
+            self.leaveWhitespace()
+        self.adjacent = adjacent
+        self.skipWhitespace = True
+        self.joinString = joinString
+        self.callPreparse = True
+
+    def ignore( self, other ):
+        if self.adjacent:
+            ParserElement.ignore(self, other)
+        else:
+            super( Combine, self).ignore( other )
+        return self
+
+    def postParse( self, instring, loc, tokenlist ):
+        retToks = tokenlist.copy()
+        del retToks[:]
+        retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults)
+
+        if self.resultsName and retToks.haskeys():
+            return [ retToks ]
+        else:
+            return retToks
+
+class Group(TokenConverter):
+    """
+    Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions.
+
+    Example::
+        ident = Word(alphas)
+        num = Word(nums)
+        term = ident | num
+        func = ident + Optional(delimitedList(term))
+        print(func.parseString("fn a,b,100"))  # -> ['fn', 'a', 'b', '100']
+
+        func = ident + Group(Optional(delimitedList(term)))
+        print(func.parseString("fn a,b,100"))  # -> ['fn', ['a', 'b', '100']]
+    """
+    def __init__( self, expr ):
+        super(Group,self).__init__( expr )
+        self.saveAsList = True
+
+    def postParse( self, instring, loc, tokenlist ):
+        return [ tokenlist ]
+
+class Dict(TokenConverter):
+    """
+    Converter to return a repetitive expression as a list, but also as a dictionary.
+    Each element can also be referenced using the first token in the expression as its key.
+    Useful for tabular report scraping when the first column can be used as a item key.
+
+    Example::
+        data_word = Word(alphas)
+        label = data_word + FollowedBy(':')
+        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join))
+
+        text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
+        attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
+        
+        # print attributes as plain groups
+        print(OneOrMore(attr_expr).parseString(text).dump())
+        
+        # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names
+        result = Dict(OneOrMore(Group(attr_expr))).parseString(text)
+        print(result.dump())
+        
+        # access named fields as dict entries, or output as dict
+        print(result['shape'])        
+        print(result.asDict())
+    prints::
+        ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap']
+
+        [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
+        - color: light blue
+        - posn: upper left
+        - shape: SQUARE
+        - texture: burlap
+        SQUARE
+        {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'}
+    See more examples at L{ParseResults} of accessing fields by results name.
+    """
+    def __init__( self, expr ):
+        super(Dict,self).__init__( expr )
+        self.saveAsList = True
+
+    def postParse( self, instring, loc, tokenlist ):
+        for i,tok in enumerate(tokenlist):
+            if len(tok) == 0:
+                continue
+            ikey = tok[0]
+            if isinstance(ikey,int):
+                ikey = _ustr(tok[0]).strip()
+            if len(tok)==1:
+                tokenlist[ikey] = _ParseResultsWithOffset("",i)
+            elif len(tok)==2 and not isinstance(tok[1],ParseResults):
+                tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i)
+            else:
+                dictvalue = tok.copy() #ParseResults(i)
+                del dictvalue[0]
+                if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()):
+                    tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i)
+                else:
+                    tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i)
+
+        if self.resultsName:
+            return [ tokenlist ]
+        else:
+            return tokenlist
+
+
+class Suppress(TokenConverter):
+    """
+    Converter for ignoring the results of a parsed expression.
+
+    Example::
+        source = "a, b, c,d"
+        wd = Word(alphas)
+        wd_list1 = wd + ZeroOrMore(',' + wd)
+        print(wd_list1.parseString(source))
+
+        # often, delimiters that are useful during parsing are just in the
+        # way afterward - use Suppress to keep them out of the parsed output
+        wd_list2 = wd + ZeroOrMore(Suppress(',') + wd)
+        print(wd_list2.parseString(source))
+    prints::
+        ['a', ',', 'b', ',', 'c', ',', 'd']
+        ['a', 'b', 'c', 'd']
+    (See also L{delimitedList}.)
+    """
+    def postParse( self, instring, loc, tokenlist ):
+        return []
+
+    def suppress( self ):
+        return self
+
+
+class OnlyOnce(object):
+    """
+    Wrapper for parse actions, to ensure they are only called once.
+    """
+    def __init__(self, methodCall):
+        self.callable = _trim_arity(methodCall)
+        self.called = False
+    def __call__(self,s,l,t):
+        if not self.called:
+            results = self.callable(s,l,t)
+            self.called = True
+            return results
+        raise ParseException(s,l,"")
+    def reset(self):
+        self.called = False
+
+def traceParseAction(f):
+    """
+    Decorator for debugging parse actions. 
+    
+    When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".}
+    When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised.
+
+    Example::
+        wd = Word(alphas)
+
+        @traceParseAction
+        def remove_duplicate_chars(tokens):
+            return ''.join(sorted(set(''.join(tokens))))
+
+        wds = OneOrMore(wd).setParseAction(remove_duplicate_chars)
+        print(wds.parseString("slkdjs sld sldd sdlf sdljf"))
+    prints::
+        >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {}))
+        <3:
+            thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc
+        sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) )
+        try:
+            ret = f(*paArgs)
+        except Exception as exc:
+            sys.stderr.write( "< ['aa', 'bb', 'cc']
+        delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE']
+    """
+    dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..."
+    if combine:
+        return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName)
+    else:
+        return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName)
+
+def countedArray( expr, intExpr=None ):
+    """
+    Helper to define a counted list of expressions.
+    This helper defines a pattern of the form::
+        integer expr expr expr...
+    where the leading integer tells how many expr expressions follow.
+    The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed.
+    
+    If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value.
+
+    Example::
+        countedArray(Word(alphas)).parseString('2 ab cd ef')  # -> ['ab', 'cd']
+
+        # in this parser, the leading integer value is given in binary,
+        # '10' indicating that 2 values are in the array
+        binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2))
+        countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef')  # -> ['ab', 'cd']
+    """
+    arrayExpr = Forward()
+    def countFieldParseAction(s,l,t):
+        n = t[0]
+        arrayExpr << (n and Group(And([expr]*n)) or Group(empty))
+        return []
+    if intExpr is None:
+        intExpr = Word(nums).setParseAction(lambda t:int(t[0]))
+    else:
+        intExpr = intExpr.copy()
+    intExpr.setName("arrayLen")
+    intExpr.addParseAction(countFieldParseAction, callDuringTry=True)
+    return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...')
+
+def _flatten(L):
+    ret = []
+    for i in L:
+        if isinstance(i,list):
+            ret.extend(_flatten(i))
+        else:
+            ret.append(i)
+    return ret
+
+def matchPreviousLiteral(expr):
+    """
+    Helper to define an expression that is indirectly defined from
+    the tokens matched in a previous expression, that is, it looks
+    for a 'repeat' of a previous expression.  For example::
+        first = Word(nums)
+        second = matchPreviousLiteral(first)
+        matchExpr = first + ":" + second
+    will match C{"1:1"}, but not C{"1:2"}.  Because this matches a
+    previous literal, will also match the leading C{"1:1"} in C{"1:10"}.
+    If this is not desired, use C{matchPreviousExpr}.
+    Do I{not} use with packrat parsing enabled.
+    """
+    rep = Forward()
+    def copyTokenToRepeater(s,l,t):
+        if t:
+            if len(t) == 1:
+                rep << t[0]
+            else:
+                # flatten t tokens
+                tflat = _flatten(t.asList())
+                rep << And(Literal(tt) for tt in tflat)
+        else:
+            rep << Empty()
+    expr.addParseAction(copyTokenToRepeater, callDuringTry=True)
+    rep.setName('(prev) ' + _ustr(expr))
+    return rep
+
+def matchPreviousExpr(expr):
+    """
+    Helper to define an expression that is indirectly defined from
+    the tokens matched in a previous expression, that is, it looks
+    for a 'repeat' of a previous expression.  For example::
+        first = Word(nums)
+        second = matchPreviousExpr(first)
+        matchExpr = first + ":" + second
+    will match C{"1:1"}, but not C{"1:2"}.  Because this matches by
+    expressions, will I{not} match the leading C{"1:1"} in C{"1:10"};
+    the expressions are evaluated first, and then compared, so
+    C{"1"} is compared with C{"10"}.
+    Do I{not} use with packrat parsing enabled.
+    """
+    rep = Forward()
+    e2 = expr.copy()
+    rep <<= e2
+    def copyTokenToRepeater(s,l,t):
+        matchTokens = _flatten(t.asList())
+        def mustMatchTheseTokens(s,l,t):
+            theseTokens = _flatten(t.asList())
+            if  theseTokens != matchTokens:
+                raise ParseException("",0,"")
+        rep.setParseAction( mustMatchTheseTokens, callDuringTry=True )
+    expr.addParseAction(copyTokenToRepeater, callDuringTry=True)
+    rep.setName('(prev) ' + _ustr(expr))
+    return rep
+
+def _escapeRegexRangeChars(s):
+    #~  escape these chars: ^-]
+    for c in r"\^-]":
+        s = s.replace(c,_bslash+c)
+    s = s.replace("\n",r"\n")
+    s = s.replace("\t",r"\t")
+    return _ustr(s)
+
+def oneOf( strs, caseless=False, useRegex=True ):
+    """
+    Helper to quickly define a set of alternative Literals, and makes sure to do
+    longest-first testing when there is a conflict, regardless of the input order,
+    but returns a C{L{MatchFirst}} for best performance.
+
+    Parameters:
+     - strs - a string of space-delimited literals, or a collection of string literals
+     - caseless - (default=C{False}) - treat all literals as caseless
+     - useRegex - (default=C{True}) - as an optimization, will generate a Regex
+          object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or
+          if creating a C{Regex} raises an exception)
+
+    Example::
+        comp_oper = oneOf("< = > <= >= !=")
+        var = Word(alphas)
+        number = Word(nums)
+        term = var | number
+        comparison_expr = term + comp_oper + term
+        print(comparison_expr.searchString("B = 12  AA=23 B<=AA AA>12"))
+    prints::
+        [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']]
+    """
+    if caseless:
+        isequal = ( lambda a,b: a.upper() == b.upper() )
+        masks = ( lambda a,b: b.upper().startswith(a.upper()) )
+        parseElementClass = CaselessLiteral
+    else:
+        isequal = ( lambda a,b: a == b )
+        masks = ( lambda a,b: b.startswith(a) )
+        parseElementClass = Literal
+
+    symbols = []
+    if isinstance(strs,basestring):
+        symbols = strs.split()
+    elif isinstance(strs, Iterable):
+        symbols = list(strs)
+    else:
+        warnings.warn("Invalid argument to oneOf, expected string or iterable",
+                SyntaxWarning, stacklevel=2)
+    if not symbols:
+        return NoMatch()
+
+    i = 0
+    while i < len(symbols)-1:
+        cur = symbols[i]
+        for j,other in enumerate(symbols[i+1:]):
+            if ( isequal(other, cur) ):
+                del symbols[i+j+1]
+                break
+            elif ( masks(cur, other) ):
+                del symbols[i+j+1]
+                symbols.insert(i,other)
+                cur = other
+                break
+        else:
+            i += 1
+
+    if not caseless and useRegex:
+        #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] ))
+        try:
+            if len(symbols)==len("".join(symbols)):
+                return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols))
+            else:
+                return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols))
+        except Exception:
+            warnings.warn("Exception creating Regex for oneOf, building MatchFirst",
+                    SyntaxWarning, stacklevel=2)
+
+
+    # last resort, just use MatchFirst
+    return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols))
+
+def dictOf( key, value ):
+    """
+    Helper to easily and clearly define a dictionary by specifying the respective patterns
+    for the key and value.  Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens
+    in the proper order.  The key pattern can include delimiting markers or punctuation,
+    as long as they are suppressed, thereby leaving the significant key text.  The value
+    pattern can include named results, so that the C{Dict} results can include named token
+    fields.
+
+    Example::
+        text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
+        attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
+        print(OneOrMore(attr_expr).parseString(text).dump())
+        
+        attr_label = label
+        attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)
+
+        # similar to Dict, but simpler call format
+        result = dictOf(attr_label, attr_value).parseString(text)
+        print(result.dump())
+        print(result['shape'])
+        print(result.shape)  # object attribute access works too
+        print(result.asDict())
+    prints::
+        [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
+        - color: light blue
+        - posn: upper left
+        - shape: SQUARE
+        - texture: burlap
+        SQUARE
+        SQUARE
+        {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'}
+    """
+    return Dict( ZeroOrMore( Group ( key + value ) ) )
+
+def originalTextFor(expr, asString=True):
+    """
+    Helper to return the original, untokenized text for a given expression.  Useful to
+    restore the parsed fields of an HTML start tag into the raw tag text itself, or to
+    revert separate tokens with intervening whitespace back to the original matching
+    input text. By default, returns astring containing the original parsed text.  
+       
+    If the optional C{asString} argument is passed as C{False}, then the return value is a 
+    C{L{ParseResults}} containing any results names that were originally matched, and a 
+    single token containing the original matched text from the input string.  So if 
+    the expression passed to C{L{originalTextFor}} contains expressions with defined
+    results names, you must set C{asString} to C{False} if you want to preserve those
+    results name values.
+
+    Example::
+        src = "this is test  bold text  normal text "
+        for tag in ("b","i"):
+            opener,closer = makeHTMLTags(tag)
+            patt = originalTextFor(opener + SkipTo(closer) + closer)
+            print(patt.searchString(src)[0])
+    prints::
+        [' bold text ']
+        ['text']
+    """
+    locMarker = Empty().setParseAction(lambda s,loc,t: loc)
+    endlocMarker = locMarker.copy()
+    endlocMarker.callPreparse = False
+    matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end")
+    if asString:
+        extractText = lambda s,l,t: s[t._original_start:t._original_end]
+    else:
+        def extractText(s,l,t):
+            t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]]
+    matchExpr.setParseAction(extractText)
+    matchExpr.ignoreExprs = expr.ignoreExprs
+    return matchExpr
+
+def ungroup(expr): 
+    """
+    Helper to undo pyparsing's default grouping of And expressions, even
+    if all but one are non-empty.
+    """
+    return TokenConverter(expr).setParseAction(lambda t:t[0])
+
+def locatedExpr(expr):
+    """
+    Helper to decorate a returned token with its starting and ending locations in the input string.
+    This helper adds the following results names:
+     - locn_start = location where matched expression begins
+     - locn_end = location where matched expression ends
+     - value = the actual parsed results
+
+    Be careful if the input text contains C{} characters, you may want to call
+    C{L{ParserElement.parseWithTabs}}
+
+    Example::
+        wd = Word(alphas)
+        for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"):
+            print(match)
+    prints::
+        [[0, 'ljsdf', 5]]
+        [[8, 'lksdjjf', 15]]
+        [[18, 'lkkjj', 23]]
+    """
+    locator = Empty().setParseAction(lambda s,l,t: l)
+    return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end"))
+
+
+# convenience constants for positional expressions
+empty       = Empty().setName("empty")
+lineStart   = LineStart().setName("lineStart")
+lineEnd     = LineEnd().setName("lineEnd")
+stringStart = StringStart().setName("stringStart")
+stringEnd   = StringEnd().setName("stringEnd")
+
+_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1])
+_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16)))
+_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8)))
+_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1)
+_charRange = Group(_singleChar + Suppress("-") + _singleChar)
+_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]"
+
+def srange(s):
+    r"""
+    Helper to easily define string ranges for use in Word construction.  Borrows
+    syntax from regexp '[]' string range definitions::
+        srange("[0-9]")   -> "0123456789"
+        srange("[a-z]")   -> "abcdefghijklmnopqrstuvwxyz"
+        srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_"
+    The input string must be enclosed in []'s, and the returned string is the expanded
+    character set joined into a single string.
+    The values enclosed in the []'s may be:
+     - a single character
+     - an escaped character with a leading backslash (such as C{\-} or C{\]})
+     - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) 
+         (C{\0x##} is also supported for backwards compatibility) 
+     - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character)
+     - a range of any of the above, separated by a dash (C{'a-z'}, etc.)
+     - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.)
+    """
+    _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1))
+    try:
+        return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body)
+    except Exception:
+        return ""
+
+def matchOnlyAtCol(n):
+    """
+    Helper method for defining parse actions that require matching at a specific
+    column in the input text.
+    """
+    def verifyCol(strg,locn,toks):
+        if col(locn,strg) != n:
+            raise ParseException(strg,locn,"matched token not at column %d" % n)
+    return verifyCol
+
+def replaceWith(replStr):
+    """
+    Helper method for common parse actions that simply return a literal value.  Especially
+    useful when used with C{L{transformString}()}.
+
+    Example::
+        num = Word(nums).setParseAction(lambda toks: int(toks[0]))
+        na = oneOf("N/A NA").setParseAction(replaceWith(math.nan))
+        term = na | num
+        
+        OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234]
+    """
+    return lambda s,l,t: [replStr]
+
+def removeQuotes(s,l,t):
+    """
+    Helper parse action for removing quotation marks from parsed quoted strings.
+
+    Example::
+        # by default, quotation marks are included in parsed results
+        quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"]
+
+        # use removeQuotes to strip quotation marks from parsed results
+        quotedString.setParseAction(removeQuotes)
+        quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"]
+    """
+    return t[0][1:-1]
+
+def tokenMap(func, *args):
+    """
+    Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional 
+    args are passed, they are forwarded to the given function as additional arguments after
+    the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the
+    parsed data to an integer using base 16.
+
+    Example (compare the last to example in L{ParserElement.transformString}::
+        hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16))
+        hex_ints.runTests('''
+            00 11 22 aa FF 0a 0d 1a
+            ''')
+        
+        upperword = Word(alphas).setParseAction(tokenMap(str.upper))
+        OneOrMore(upperword).runTests('''
+            my kingdom for a horse
+            ''')
+
+        wd = Word(alphas).setParseAction(tokenMap(str.title))
+        OneOrMore(wd).setParseAction(' '.join).runTests('''
+            now is the winter of our discontent made glorious summer by this sun of york
+            ''')
+    prints::
+        00 11 22 aa FF 0a 0d 1a
+        [0, 17, 34, 170, 255, 10, 13, 26]
+
+        my kingdom for a horse
+        ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE']
+
+        now is the winter of our discontent made glorious summer by this sun of york
+        ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York']
+    """
+    def pa(s,l,t):
+        return [func(tokn, *args) for tokn in t]
+
+    try:
+        func_name = getattr(func, '__name__', 
+                            getattr(func, '__class__').__name__)
+    except Exception:
+        func_name = str(func)
+    pa.__name__ = func_name
+
+    return pa
+
+upcaseTokens = tokenMap(lambda t: _ustr(t).upper())
+"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}"""
+
+downcaseTokens = tokenMap(lambda t: _ustr(t).lower())
+"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}"""
+    
+def _makeTags(tagStr, xml):
+    """Internal helper to construct opening and closing tag expressions, given a tag name"""
+    if isinstance(tagStr,basestring):
+        resname = tagStr
+        tagStr = Keyword(tagStr, caseless=not xml)
+    else:
+        resname = tagStr.name
+
+    tagAttrName = Word(alphas,alphanums+"_-:")
+    if (xml):
+        tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes )
+        openTag = Suppress("<") + tagStr("tag") + \
+                Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \
+                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
+    else:
+        printablesLessRAbrack = "".join(c for c in printables if c not in ">")
+        tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack)
+        openTag = Suppress("<") + tagStr("tag") + \
+                Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \
+                Optional( Suppress("=") + tagAttrValue ) ))) + \
+                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
+    closeTag = Combine(_L("")
+
+    openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname)
+    closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("" % resname)
+    openTag.tag = resname
+    closeTag.tag = resname
+    return openTag, closeTag
+
+def makeHTMLTags(tagStr):
+    """
+    Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches
+    tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values.
+
+    Example::
+        text = 'More info at the pyparsing wiki page'
+        # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple
+        a,a_end = makeHTMLTags("A")
+        link_expr = a + SkipTo(a_end)("link_text") + a_end
+        
+        for link in link_expr.searchString(text):
+            # attributes in the  tag (like "href" shown here) are also accessible as named results
+            print(link.link_text, '->', link.href)
+    prints::
+        pyparsing -> http://pyparsing.wikispaces.com
+    """
+    return _makeTags( tagStr, False )
+
+def makeXMLTags(tagStr):
+    """
+    Helper to construct opening and closing tag expressions for XML, given a tag name. Matches
+    tags only in the given upper/lower case.
+
+    Example: similar to L{makeHTMLTags}
+    """
+    return _makeTags( tagStr, True )
+
+def withAttribute(*args,**attrDict):
+    """
+    Helper to create a validating parse action to be used with start tags created
+    with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag
+    with a required attribute value, to avoid false matches on common tags such as
+    C{} or C{
}. + + Call C{withAttribute} with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in C{(align="right")}, or + - as an explicit dict with C{**} operator, when an attribute name is also a Python + reserved word, as in C{**{"class":"Customer", "align":"right"}} + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + If just testing for C{class} (with or without a namespace), use C{L{withClass}}. + + To verify that the attribute exists, but without specifying a value, pass + C{withAttribute.ANY_VALUE} as the value. + + Example:: + html = ''' +
+ Some text +
1 4 0 1 0
+
1,3 2,3 1,1
+
this has no type
+
+ + ''' + div,div_end = makeHTMLTags("div") + + # only match div tag having a type attribute with value "grid" + div_grid = div().setParseAction(withAttribute(type="grid")) + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + # construct a match with any div tag having a type attribute, regardless of the value + div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +def withClass(classname, namespace=''): + """ + Simplified version of C{L{withAttribute}} when matching on a div class - made + difficult because C{class} is a reserved word in Python. + + Example:: + html = ''' +
+ Some text +
1 4 0 1 0
+
1,3 2,3 1,1
+
this <div> has no class
+
+ + ''' + div,div_end = makeHTMLTags("div") + div_grid = div().setParseAction(withClass("grid")) + + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + classattr = "%s:class" % namespace if namespace else "class" + return withAttribute(**{classattr : classname}) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): + """ + Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. The generated parser will also recognize the use + of parentheses to override operator precedences (see example below). + + Note: if you define a deep operator list, you may see performance issues + when using infixNotation. See L{ParserElement.enablePackrat} for a + mechanism to potentially improve your parser performance. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted); if the parse action + is passed a tuple or list of functions, this is equivalent to + calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) + - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) + - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) + + Example:: + # simple example of four-function arithmetic with ints and variable names + integer = pyparsing_common.signed_integer + varname = pyparsing_common.identifier + + arith_expr = infixNotation(integer | varname, + [ + ('-', 1, opAssoc.RIGHT), + (oneOf('* /'), 2, opAssoc.LEFT), + (oneOf('+ -'), 2, opAssoc.LEFT), + ]) + + arith_expr.runTests(''' + 5+3*6 + (5+3)*6 + -2--11 + ''', fullDump=False) + prints:: + 5+3*6 + [[5, '+', [3, '*', 6]]] + + (5+3)*6 + [[[5, '+', 3], '*', 6]] + + -2--11 + [[['-', 2], '-', ['-', 11]]] + """ + ret = Forward() + lastExpr = baseExpr | ( lpar + ret + rpar ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward().setName(termName) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + if isinstance(pa, (tuple, list)): + matchExpr.setParseAction(*pa) + else: + matchExpr.setParseAction(pa) + thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) + lastExpr = thisExpr + ret <<= lastExpr + return ret + +operatorPrecedence = infixNotation +"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" + +dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") +sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") +quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| + Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): + """ + Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression + - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression + - content - expression for items within the nested lists (default=C{None}) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the C{ignoreExpr} argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. + The default is L{quotedString}, but if no expressions are to be ignored, + then pass C{None} for this argument. + + Example:: + data_type = oneOf("void int short long char float double") + decl_data_type = Combine(data_type + Optional(Word('*'))) + ident = Word(alphas+'_', alphanums+'_') + number = pyparsing_common.number + arg = Group(decl_data_type + ident) + LPAR,RPAR = map(Suppress, "()") + + code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) + + c_function = (decl_data_type("type") + + ident("name") + + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + + code_body("body")) + c_function.ignore(cStyleComment) + + source_code = ''' + int is_odd(int x) { + return (x%2); + } + + int dec_to_hex(char hchar) { + if (hchar >= '0' && hchar <= '9') { + return (ord(hchar)-ord('0')); + } else { + return (10+ord(hchar)-ord('A')); + } + } + ''' + for func in c_function.searchString(source_code): + print("%(name)s (%(type)s) args: %(args)s" % func) + + prints:: + is_odd (int) args: [['int', 'x']] + dec_to_hex (int) args: [['char', 'hchar']] + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + ret.setName('nested %s%s expression' % (opener,closer)) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """ + Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=C{True}) + + A valid block must contain at least one C{blockStatement}. + + Example:: + data = ''' + def A(z): + A1 + B = 100 + G = A2 + A2 + A3 + B + def BB(a,b,c): + BB1 + def BBA(): + bba1 + bba2 + bba3 + C + D + def spam(x,y): + def eggs(z): + pass + ''' + + + indentStack = [1] + stmt = Forward() + + identifier = Word(alphas, alphanums) + funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") + func_body = indentedBlock(stmt, indentStack) + funcDef = Group( funcDecl + func_body ) + + rvalue = Forward() + funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") + rvalue << (funcCall | identifier | Word(nums)) + assignment = Group(identifier + "=" + rvalue) + stmt << ( funcDef | assignment | identifier ) + + module_body = OneOrMore(stmt) + + parseTree = module_body.parseString(data) + parseTree.pprint() + prints:: + [['def', + 'A', + ['(', 'z', ')'], + ':', + [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], + 'B', + ['def', + 'BB', + ['(', 'a', 'b', 'c', ')'], + ':', + [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], + 'C', + 'D', + ['def', + 'spam', + ['(', 'x', 'y', ')'], + ':', + [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') + PEER = Empty().setParseAction(checkPeerIndent).setName('') + UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') + if indent: + smExpr = Group( Optional(NL) + + #~ FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr.setName('indented block') + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) +_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) +commonHTMLEntity = Regex('&(?P' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") +def replaceHTMLEntity(t): + """Helper parser action to replace common HTML entities with their special characters""" + return _htmlEntityMap.get(t.entity) + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") +"Comment of the form C{/* ... */}" + +htmlComment = Regex(r"").setName("HTML comment") +"Comment of the form C{}" + +restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") +dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") +"Comment of the form C{// ... (to end of line)}" + +cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") +"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" + +javaStyleComment = cppStyleComment +"Same as C{L{cppStyleComment}}" + +pythonStyleComment = Regex(r"#.*").setName("Python style comment") +"Comment of the form C{# ... (to end of line)}" + +_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + + Optional( Word(" \t") + + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") +commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") +"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. + This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" + +# some other useful expressions - using lower-case class name since we are really using this as a namespace +class pyparsing_common: + """ + Here are some common low-level expressions that may be useful in jump-starting parser development: + - numeric forms (L{integers}, L{reals}, L{scientific notation}) + - common L{programming identifiers} + - network addresses (L{MAC}, L{IPv4}, L{IPv6}) + - ISO8601 L{dates} and L{datetime} + - L{UUID} + - L{comma-separated list} + Parse actions: + - C{L{convertToInteger}} + - C{L{convertToFloat}} + - C{L{convertToDate}} + - C{L{convertToDatetime}} + - C{L{stripHTMLTags}} + - C{L{upcaseTokens}} + - C{L{downcaseTokens}} + + Example:: + pyparsing_common.number.runTests(''' + # any int or real number, returned as the appropriate type + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.fnumber.runTests(''' + # any int or real number, returned as float + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.hex_integer.runTests(''' + # hex numbers + 100 + FF + ''') + + pyparsing_common.fraction.runTests(''' + # fractions + 1/2 + -3/4 + ''') + + pyparsing_common.mixed_integer.runTests(''' + # mixed fractions + 1 + 1/2 + -3/4 + 1-3/4 + ''') + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(''' + # uuid + 12345678-1234-5678-1234-567812345678 + ''') + prints:: + # any int or real number, returned as the appropriate type + 100 + [100] + + -100 + [-100] + + +100 + [100] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # any int or real number, returned as float + 100 + [100.0] + + -100 + [-100.0] + + +100 + [100.0] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # hex numbers + 100 + [256] + + FF + [255] + + # fractions + 1/2 + [0.5] + + -3/4 + [-0.75] + + # mixed fractions + 1 + [1] + + 1/2 + [0.5] + + -3/4 + [-0.75] + + 1-3/4 + [1.75] + + # uuid + 12345678-1234-5678-1234-567812345678 + [UUID('12345678-1234-5678-1234-567812345678')] + """ + + convertToInteger = tokenMap(int) + """ + Parse action for converting parsed integers to Python int + """ + + convertToFloat = tokenMap(float) + """ + Parse action for converting parsed numbers to Python float + """ + + integer = Word(nums).setName("integer").setParseAction(convertToInteger) + """expression that parses an unsigned integer, returns an int""" + + hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) + """expression that parses a hexadecimal integer, returns an int""" + + signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) + """expression that parses an integer with optional leading sign, returns an int""" + + fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") + """fractional expression of an integer divided by an integer, returns a float""" + fraction.addParseAction(lambda t: t[0]/t[-1]) + + mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") + """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" + mixed_integer.addParseAction(sum) + + real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) + """expression that parses a floating point number and returns a float""" + + sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) + """expression that parses a floating point number with optional scientific notation and returns a float""" + + # streamlining this expression makes the docs nicer-looking + number = (sci_real | real | signed_integer).streamline() + """any numeric expression, returns the corresponding Python type""" + + fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) + """any int or real number, returned as float""" + + identifier = Word(alphas+'_', alphanums+'_').setName("identifier") + """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" + + ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") + "IPv4 address (C{0.0.0.0 - 255.255.255.255})" + + _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") + _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") + _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") + _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) + _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") + ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") + "IPv6 address (long, short, or mixed form)" + + mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") + "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" + + @staticmethod + def convertToDate(fmt="%Y-%m-%d"): + """ + Helper to create a parse action for converting parsed date string to Python datetime.date + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) + + Example:: + date_expr = pyparsing_common.iso8601_date.copy() + date_expr.setParseAction(pyparsing_common.convertToDate()) + print(date_expr.parseString("1999-12-31")) + prints:: + [datetime.date(1999, 12, 31)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt).date() + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + @staticmethod + def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): + """ + Helper to create a parse action for converting parsed datetime string to Python datetime.datetime + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) + + Example:: + dt_expr = pyparsing_common.iso8601_datetime.copy() + dt_expr.setParseAction(pyparsing_common.convertToDatetime()) + print(dt_expr.parseString("1999-12-31T23:59:59.999")) + prints:: + [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt) + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + iso8601_date = Regex(r'(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?').setName("ISO8601 date") + "ISO8601 date (C{yyyy-mm-dd})" + + iso8601_datetime = Regex(r'(?P\d{4})-(?P\d\d)-(?P\d\d)[T ](?P\d\d):(?P\d\d)(:(?P\d\d(\.\d*)?)?)?(?PZ|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") + "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" + + uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") + "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" + + _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() + @staticmethod + def stripHTMLTags(s, l, tokens): + """ + Parse action to remove HTML tags from web page HTML source + + Example:: + # strip HTML links from normal text + text = 'More info at the
pyparsing wiki page' + td,td_end = makeHTMLTags("TD") + table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end + + print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' + """ + return pyparsing_common._html_stripper.transformString(tokens[0]) + + _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + + Optional( White(" \t") ) ) ).streamline().setName("commaItem") + comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") + """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" + + upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) + """Parse action to convert tokens to upper case.""" + + downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) + """Parse action to convert tokens to lower case.""" + + +if __name__ == "__main__": + + selectToken = CaselessLiteral("select") + fromToken = CaselessLiteral("from") + + ident = Word(alphas, alphanums + "_$") + + columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + columnNameList = Group(delimitedList(columnName)).setName("columns") + columnSpec = ('*' | columnNameList) + + tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + tableNameList = Group(delimitedList(tableName)).setName("tables") + + simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") + + # demo runTests method, including embedded comments in test string + simpleSQL.runTests(""" + # '*' as column list and dotted table name + select * from SYS.XYZZY + + # caseless match on "SELECT", and casts back to "select" + SELECT * from XYZZY, ABC + + # list of column names, and mixed case SELECT keyword + Select AA,BB,CC from Sys.dual + + # multiple tables + Select A, B, C from Sys.dual, Table2 + + # invalid SELECT keyword - should fail + Xelect A, B, C from Sys.dual + + # incomplete command - should fail + Select + + # invalid column name - should fail + Select ^^^ frox Sys.dual + + """) + + pyparsing_common.number.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + # any int or real number, returned as float + pyparsing_common.fnumber.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + pyparsing_common.hex_integer.runTests(""" + 100 + FF + """) + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(""" + 12345678-1234-5678-1234-567812345678 + """) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/six.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/six.py new file mode 100644 index 0000000..190c023 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/_vendor/six.py @@ -0,0 +1,868 @@ +"""Utilities for writing code that runs on Python 2 and 3""" + +# Copyright (c) 2010-2015 Benjamin Peterson +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson " +__version__ = "1.10.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + if from_value is None: + raise value + raise value from from_value +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + raise value from from_value +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/archive_util.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/archive_util.py new file mode 100644 index 0000000..8143604 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/archive_util.py @@ -0,0 +1,173 @@ +"""Utilities for extracting common archive formats""" + +import zipfile +import tarfile +import os +import shutil +import posixpath +import contextlib +from distutils.errors import DistutilsError + +from pkg_resources import ensure_directory + +__all__ = [ + "unpack_archive", "unpack_zipfile", "unpack_tarfile", "default_filter", + "UnrecognizedFormat", "extraction_drivers", "unpack_directory", +] + + +class UnrecognizedFormat(DistutilsError): + """Couldn't recognize the archive type""" + + +def default_filter(src, dst): + """The default progress/filter callback; returns True for all files""" + return dst + + +def unpack_archive(filename, extract_dir, progress_filter=default_filter, + drivers=None): + """Unpack `filename` to `extract_dir`, or raise ``UnrecognizedFormat`` + + `progress_filter` is a function taking two arguments: a source path + internal to the archive ('/'-separated), and a filesystem path where it + will be extracted. The callback must return the desired extract path + (which may be the same as the one passed in), or else ``None`` to skip + that file or directory. The callback can thus be used to report on the + progress of the extraction, as well as to filter the items extracted or + alter their extraction paths. + + `drivers`, if supplied, must be a non-empty sequence of functions with the + same signature as this function (minus the `drivers` argument), that raise + ``UnrecognizedFormat`` if they do not support extracting the designated + archive type. The `drivers` are tried in sequence until one is found that + does not raise an error, or until all are exhausted (in which case + ``UnrecognizedFormat`` is raised). If you do not supply a sequence of + drivers, the module's ``extraction_drivers`` constant will be used, which + means that ``unpack_zipfile`` and ``unpack_tarfile`` will be tried, in that + order. + """ + for driver in drivers or extraction_drivers: + try: + driver(filename, extract_dir, progress_filter) + except UnrecognizedFormat: + continue + else: + return + else: + raise UnrecognizedFormat( + "Not a recognized archive type: %s" % filename + ) + + +def unpack_directory(filename, extract_dir, progress_filter=default_filter): + """"Unpack" a directory, using the same interface as for archives + + Raises ``UnrecognizedFormat`` if `filename` is not a directory + """ + if not os.path.isdir(filename): + raise UnrecognizedFormat("%s is not a directory" % filename) + + paths = { + filename: ('', extract_dir), + } + for base, dirs, files in os.walk(filename): + src, dst = paths[base] + for d in dirs: + paths[os.path.join(base, d)] = src + d + '/', os.path.join(dst, d) + for f in files: + target = os.path.join(dst, f) + target = progress_filter(src + f, target) + if not target: + # skip non-files + continue + ensure_directory(target) + f = os.path.join(base, f) + shutil.copyfile(f, target) + shutil.copystat(f, target) + + +def unpack_zipfile(filename, extract_dir, progress_filter=default_filter): + """Unpack zip `filename` to `extract_dir` + + Raises ``UnrecognizedFormat`` if `filename` is not a zipfile (as determined + by ``zipfile.is_zipfile()``). See ``unpack_archive()`` for an explanation + of the `progress_filter` argument. + """ + + if not zipfile.is_zipfile(filename): + raise UnrecognizedFormat("%s is not a zip file" % (filename,)) + + with zipfile.ZipFile(filename) as z: + for info in z.infolist(): + name = info.filename + + # don't extract absolute paths or ones with .. in them + if name.startswith('/') or '..' in name.split('/'): + continue + + target = os.path.join(extract_dir, *name.split('/')) + target = progress_filter(name, target) + if not target: + continue + if name.endswith('/'): + # directory + ensure_directory(target) + else: + # file + ensure_directory(target) + data = z.read(info.filename) + with open(target, 'wb') as f: + f.write(data) + unix_attributes = info.external_attr >> 16 + if unix_attributes: + os.chmod(target, unix_attributes) + + +def unpack_tarfile(filename, extract_dir, progress_filter=default_filter): + """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` + + Raises ``UnrecognizedFormat`` if `filename` is not a tarfile (as determined + by ``tarfile.open()``). See ``unpack_archive()`` for an explanation + of the `progress_filter` argument. + """ + try: + tarobj = tarfile.open(filename) + except tarfile.TarError: + raise UnrecognizedFormat( + "%s is not a compressed or uncompressed tar file" % (filename,) + ) + with contextlib.closing(tarobj): + # don't do any chowning! + tarobj.chown = lambda *args: None + for member in tarobj: + name = member.name + # don't extract absolute paths or ones with .. in them + if not name.startswith('/') and '..' not in name.split('/'): + prelim_dst = os.path.join(extract_dir, *name.split('/')) + + # resolve any links and to extract the link targets as normal + # files + while member is not None and (member.islnk() or member.issym()): + linkpath = member.linkname + if member.issym(): + base = posixpath.dirname(member.name) + linkpath = posixpath.join(base, linkpath) + linkpath = posixpath.normpath(linkpath) + member = tarobj._getmember(linkpath) + + if member is not None and (member.isfile() or member.isdir()): + final_dst = progress_filter(name, prelim_dst) + if final_dst: + if final_dst.endswith(os.sep): + final_dst = final_dst[:-1] + try: + # XXX Ugh + tarobj._extract_member(member, final_dst) + except tarfile.ExtractError: + # chown/chmod/mkfifo/mknode/makedev failed + pass + return True + + +extraction_drivers = unpack_directory, unpack_zipfile, unpack_tarfile diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/build_meta.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/build_meta.py new file mode 100644 index 0000000..eb9e815 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/build_meta.py @@ -0,0 +1,264 @@ +"""A PEP 517 interface to setuptools + +Previously, when a user or a command line tool (let's call it a "frontend") +needed to make a request of setuptools to take a certain action, for +example, generating a list of installation requirements, the frontend would +would call "setup.py egg_info" or "setup.py bdist_wheel" on the command line. + +PEP 517 defines a different method of interfacing with setuptools. Rather +than calling "setup.py" directly, the frontend should: + + 1. Set the current directory to the directory with a setup.py file + 2. Import this module into a safe python interpreter (one in which + setuptools can potentially set global variables or crash hard). + 3. Call one of the functions defined in PEP 517. + +What each function does is defined in PEP 517. However, here is a "casual" +definition of the functions (this definition should not be relied on for +bug reports or API stability): + + - `build_wheel`: build a wheel in the folder and return the basename + - `get_requires_for_build_wheel`: get the `setup_requires` to build + - `prepare_metadata_for_build_wheel`: get the `install_requires` + - `build_sdist`: build an sdist in the folder and return the basename + - `get_requires_for_build_sdist`: get the `setup_requires` to build + +Again, this is not a formal definition! Just a "taste" of the module. +""" + +import io +import os +import sys +import tokenize +import shutil +import contextlib + +import setuptools +import distutils +from setuptools.py31compat import TemporaryDirectory + +from pkg_resources import parse_requirements +from pkg_resources.py31compat import makedirs + +__all__ = ['get_requires_for_build_sdist', + 'get_requires_for_build_wheel', + 'prepare_metadata_for_build_wheel', + 'build_wheel', + 'build_sdist', + '__legacy__', + 'SetupRequirementsError'] + +class SetupRequirementsError(BaseException): + def __init__(self, specifiers): + self.specifiers = specifiers + + +class Distribution(setuptools.dist.Distribution): + def fetch_build_eggs(self, specifiers): + specifier_list = list(map(str, parse_requirements(specifiers))) + + raise SetupRequirementsError(specifier_list) + + @classmethod + @contextlib.contextmanager + def patch(cls): + """ + Replace + distutils.dist.Distribution with this class + for the duration of this context. + """ + orig = distutils.core.Distribution + distutils.core.Distribution = cls + try: + yield + finally: + distutils.core.Distribution = orig + + +def _to_str(s): + """ + Convert a filename to a string (on Python 2, explicitly + a byte string, not Unicode) as distutils checks for the + exact type str. + """ + if sys.version_info[0] == 2 and not isinstance(s, str): + # Assume it's Unicode, as that's what the PEP says + # should be provided. + return s.encode(sys.getfilesystemencoding()) + return s + + +def _get_immediate_subdirectories(a_dir): + return [name for name in os.listdir(a_dir) + if os.path.isdir(os.path.join(a_dir, name))] + + +def _file_with_extension(directory, extension): + matching = ( + f for f in os.listdir(directory) + if f.endswith(extension) + ) + file, = matching + return file + + +def _open_setup_script(setup_script): + if not os.path.exists(setup_script): + # Supply a default setup.py + return io.StringIO(u"from setuptools import setup; setup()") + + return getattr(tokenize, 'open', open)(setup_script) + + +class _BuildMetaBackend(object): + + def _fix_config(self, config_settings): + config_settings = config_settings or {} + config_settings.setdefault('--global-option', []) + return config_settings + + def _get_build_requires(self, config_settings, requirements): + config_settings = self._fix_config(config_settings) + + sys.argv = sys.argv[:1] + ['egg_info'] + \ + config_settings["--global-option"] + try: + with Distribution.patch(): + self.run_setup() + except SetupRequirementsError as e: + requirements += e.specifiers + + return requirements + + def run_setup(self, setup_script='setup.py'): + # Note that we can reuse our build directory between calls + # Correctness comes first, then optimization later + __file__ = setup_script + __name__ = '__main__' + + with _open_setup_script(__file__) as f: + code = f.read().replace(r'\r\n', r'\n') + + exec(compile(code, __file__, 'exec'), locals()) + + def get_requires_for_build_wheel(self, config_settings=None): + config_settings = self._fix_config(config_settings) + return self._get_build_requires(config_settings, requirements=['wheel']) + + def get_requires_for_build_sdist(self, config_settings=None): + config_settings = self._fix_config(config_settings) + return self._get_build_requires(config_settings, requirements=[]) + + def prepare_metadata_for_build_wheel(self, metadata_directory, + config_settings=None): + sys.argv = sys.argv[:1] + ['dist_info', '--egg-base', + _to_str(metadata_directory)] + self.run_setup() + + dist_info_directory = metadata_directory + while True: + dist_infos = [f for f in os.listdir(dist_info_directory) + if f.endswith('.dist-info')] + + if (len(dist_infos) == 0 and + len(_get_immediate_subdirectories(dist_info_directory)) == 1): + + dist_info_directory = os.path.join( + dist_info_directory, os.listdir(dist_info_directory)[0]) + continue + + assert len(dist_infos) == 1 + break + + # PEP 517 requires that the .dist-info directory be placed in the + # metadata_directory. To comply, we MUST copy the directory to the root + if dist_info_directory != metadata_directory: + shutil.move( + os.path.join(dist_info_directory, dist_infos[0]), + metadata_directory) + shutil.rmtree(dist_info_directory, ignore_errors=True) + + return dist_infos[0] + + def _build_with_temp_dir(self, setup_command, result_extension, + result_directory, config_settings): + config_settings = self._fix_config(config_settings) + result_directory = os.path.abspath(result_directory) + + # Build in a temporary directory, then copy to the target. + makedirs(result_directory, exist_ok=True) + with TemporaryDirectory(dir=result_directory) as tmp_dist_dir: + sys.argv = (sys.argv[:1] + setup_command + + ['--dist-dir', tmp_dist_dir] + + config_settings["--global-option"]) + self.run_setup() + + result_basename = _file_with_extension(tmp_dist_dir, result_extension) + result_path = os.path.join(result_directory, result_basename) + if os.path.exists(result_path): + # os.rename will fail overwriting on non-Unix. + os.remove(result_path) + os.rename(os.path.join(tmp_dist_dir, result_basename), result_path) + + return result_basename + + + def build_wheel(self, wheel_directory, config_settings=None, + metadata_directory=None): + return self._build_with_temp_dir(['bdist_wheel'], '.whl', + wheel_directory, config_settings) + + def build_sdist(self, sdist_directory, config_settings=None): + return self._build_with_temp_dir(['sdist', '--formats', 'gztar'], + '.tar.gz', sdist_directory, + config_settings) + + +class _BuildMetaLegacyBackend(_BuildMetaBackend): + """Compatibility backend for setuptools + + This is a version of setuptools.build_meta that endeavors to maintain backwards + compatibility with pre-PEP 517 modes of invocation. It exists as a temporary + bridge between the old packaging mechanism and the new packaging mechanism, + and will eventually be removed. + """ + def run_setup(self, setup_script='setup.py'): + # In order to maintain compatibility with scripts assuming that + # the setup.py script is in a directory on the PYTHONPATH, inject + # '' into sys.path. (pypa/setuptools#1642) + sys_path = list(sys.path) # Save the original path + + script_dir = os.path.dirname(os.path.abspath(setup_script)) + if script_dir not in sys.path: + sys.path.insert(0, script_dir) + + # Some setup.py scripts (e.g. in pygame and numpy) use sys.argv[0] to + # get the directory of the source code. They expect it to refer to the + # setup.py script. + sys_argv_0 = sys.argv[0] + sys.argv[0] = setup_script + + try: + super(_BuildMetaLegacyBackend, + self).run_setup(setup_script=setup_script) + finally: + # While PEP 517 frontends should be calling each hook in a fresh + # subprocess according to the standard (and thus it should not be + # strictly necessary to restore the old sys.path), we'll restore + # the original path so that the path manipulation does not persist + # within the hook after run_setup is called. + sys.path[:] = sys_path + sys.argv[0] = sys_argv_0 + +# The primary backend +_BACKEND = _BuildMetaBackend() + +get_requires_for_build_wheel = _BACKEND.get_requires_for_build_wheel +get_requires_for_build_sdist = _BACKEND.get_requires_for_build_sdist +prepare_metadata_for_build_wheel = _BACKEND.prepare_metadata_for_build_wheel +build_wheel = _BACKEND.build_wheel +build_sdist = _BACKEND.build_sdist + + +# The legacy backend +__legacy__ = _BuildMetaLegacyBackend() diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/cli-32.exe b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/cli-32.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch literal 65536 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

@|$jDp4t7maBT@by!vG1&J_?=DS4W3Hu6w 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[c}iI#RErv3nvcIClH@!{vM)zJ_weD zu_-L8NU*GlC{d0L!!VW10^+~>qmNB~Y8H+F}!P8_d(PpvjzMJQmr z)FkX;2B~<|3JfJeWv@IXo~nTtp$}Gjie> zs8UDG*kid(%i5QCBp~MA;#I186PI-nZ&k7!k8BiLJSuR>h7ArSYHD~B0I z=T6L{zqglekt0JjG5z&|GWb4?+B5+{p^fgTufl_KesA{@I&g7rNq==^SGc5GcM%$N zDBG2)qExz*Z;jGN_-iD-y8i2BCq)p}2lKcspLg>w-;qwg(()HXrZa3jd!}spuwBVX zwmX!iwU?#7uoQnunw|OlU~+c z^L5Ak3zWhaA4B^FhMMboO0k*O2GL)lD9_<$5b>czbCvKcSt+u*gA*=%dH>Q-Bc11h zzO7jbXN)&5mBf=w2anK6P$YcJZQoWa2#E!v{hFKxxm7Fc)Fc9iC35{|Lp7bIDjrhC zgMiGf4r2yquH{U7WdMio;XS4Y%Ry{q7#kv#gZ07i`7eo#MMh_o68E*Fd_#nrri^4b zX+slbsv>+8pmck%oLDUL()8NRJ#Z z8DReF_eq2zsjEXGs)yS{k}ykS1B!ZrY0f6O65^lslJv3g&wfpDg-&EwF8wrc=hSwm zPlV&n%%yE_@onOwK?)`GNJ6MQ0drMuBYWCH5dkD)uErh@*k}#GcFl<-;;TN+5vb|b zctkCv;*zL7f)A;QuO%(81r0)&aUz4EQu;kA!k@7i8RZ)koMaWW`5cC6n@{w!!J$5d zx}l)4VP4xL=BKi&c^{n_Qi`q@G{vimblcVR53b#*X$FUOQFm!A8JKahNSiBdY+x3bJZfD8n{--FLUM4+Mx@{vM_ep zkk)U=K8R(rhU(X_faI*ZO}cn`5t*O}lx^j8|0rt-)o=Axn^DGcQTi!#7hxLTq?|HQ zB;T6(nrsCeYK0_o%)IO+CP{n#+|;w1ZmvD2c-J{i88bp63RjyKOE!B!D3U{RCs*Zh z&^%65VM(J34230U4bHS}M@SYS9TEK}c%)2<$h1|T;##zRtjRt@#1T%J=kAhOiw+Z% z7DpyWVK@6%9K^uVD9LDKj)dR^aZK6$@Lt)l;sj@`QSzBm{TlLG{JKM_^60Zr2w~nr zr>P-BaV8OjjWm?hQ3$ZCx+lyD%q`~4iNF9xWKi$t&pzBhwN9Dq-o^v9@=abLR#|

KZqkLal4YCRR9VNhIM|rBqmzzcImvcx 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/cli-64.exe b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/cli-64.exe new file mode 100644 index 0000000000000000000000000000000000000000..675e6bf3743f3d3011c238657e7128ee9960ef7f GIT binary patch literal 74752 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/cli.exe b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/cli.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch literal 65536 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

@|$jDp4t7maBT@by!vG1&J_?=DS4W3Hu6w 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[c}iI#RErv3nvcIClH@!{vM)zJ_weD zu_-L8NU*GlC{d0L!!VW10^+~>qmNB~Y8H+F}!P8_d(PpvjzMJQmr z)FkX;2B~<|3JfJeWv@IXo~nTtp$}Gjie> zs8UDG*kid(%i5QCBp~MA;#I186PI-nZ&k7!k8BiLJSuR>h7ArSYHD~B0I z=T6L{zqglekt0JjG5z&|GWb4?+B5+{p^fgTufl_KesA{@I&g7rNq==^SGc5GcM%$N zDBG2)qExz*Z;jGN_-iD-y8i2BCq)p}2lKcspLg>w-;qwg(()HXrZa3jd!}spuwBVX zwmX!iwU?#7uoQnunw|OlU~+c z^L5Ak3zWhaA4B^FhMMboO0k*O2GL)lD9_<$5b>czbCvKcSt+u*gA*=%dH>Q-Bc11h zzO7jbXN)&5mBf=w2anK6P$YcJZQoWa2#E!v{hFKxxm7Fc)Fc9iC35{|Lp7bIDjrhC zgMiGf4r2yquH{U7WdMio;XS4Y%Ry{q7#kv#gZ07i`7eo#MMh_o68E*Fd_#nrri^4b zX+slbsv>+8pmck%oLDUL()8NRJ#Z z8DReF_eq2zsjEXGs)yS{k}ykS1B!ZrY0f6O65^lslJv3g&wfpDg-&EwF8wrc=hSwm zPlV&n%%yE_@onOwK?)`GNJ6MQ0drMuBYWCH5dkD)uErh@*k}#GcFl<-;;TN+5vb|b zctkCv;*zL7f)A;QuO%(81r0)&aUz4EQu;kA!k@7i8RZ)koMaWW`5cC6n@{w!!J$5d zx}l)4VP4xL=BKi&c^{n_Qi`q@G{vimblcVR53b#*X$FUOQFm!A8JKahNSiBdY+x3bJZfD8n{--FLUM4+Mx@{vM_ep zkk)U=K8R(rhU(X_faI*ZO}cn`5t*O}lx^j8|0rt-)o=Axn^DGcQTi!#7hxLTq?|HQ zB;T6(nrsCeYK0_o%)IO+CP{n#+|;w1ZmvD2c-J{i88bp63RjyKOE!B!D3U{RCs*Zh z&^%65VM(J34230U4bHS}M@SYS9TEK}c%)2<$h1|T;##zRtjRt@#1T%J=kAhOiw+Z% z7DpyWVK@6%9K^uVD9LDKj)dR^aZK6$@Lt)l;sj@`QSzBm{TlLG{JKM_^60Zr2w~nr zr>P-BaV8OjjWm?hQ3$ZCx+lyD%q`~4iNF9xWKi$t&pzBhwN9Dq-o^v9@=abLR#|

KZqkLal4YCRR9VNhIM|rBqmzzcImvcx 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 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__init__.py b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__init__.py new file mode 100644 index 0000000..743f558 --- /dev/null +++ b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__init__.py @@ -0,0 +1,17 @@ +__all__ = [ + 'alias', 'bdist_egg', 'bdist_rpm', 'build_ext', 'build_py', 'develop', + 'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts', + 'sdist', 'setopt', 'test', 'install_egg_info', 'install_scripts', + 'bdist_wininst', 'upload_docs', 'build_clib', 'dist_info', +] + +from distutils.command.bdist import bdist +import sys + +from setuptools.command import install_scripts + +if 'egg' not in bdist.format_commands: + bdist.format_command['egg'] = ('bdist_egg', "Python .egg file") + bdist.format_commands.append('egg') + +del bdist, sys diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/__init__.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a735ecf0e927b4b1da62b311405d5d84d2b47b86 GIT binary patch literal 698 zcmY*WJ#Q2-5Vd!2Z#S2_Tm(XC({7P;>6d(w5%Obj{yjN5uknK$G)tn$H_C~kDzmi9 zct!`D+nne4AK6h?@B+C)XZPa`4R6#KQK^b+GB95%ReYtC+-A4A%HNT?te>SqS|cHy z+$jT5=;iVVgYOWoja5Q_h^g8`zfGmm8*QCWQ!QaDOb=07n<~sjXW>$Lq)rb&SaX-g z!9^K0uRw0J^AS=3Lr*>i9nnvts3E5FW6s}l^CJUoFhkyKul2$7!wo-Od+VeU%C(Rt zdzmeE%P0T)j`p5JWa%Jr8Ga+eEZb$yabA#gGw z_{C6Z9gT&ibzLWW)$A&Tr=Y-?lETHWWI2rlTjQJfuH?Pq_Ol~_v$+d z7g%j)et%{w*J-A$H7>?`x9Y+53_{C-_70eQ(0~C~3O9PCOs9J=7_ij64oIv{8%fx%cW+xK#*fj!D)2W3p)^O-0_gO6NYcTTOXenn9eoS~`8DXp?;HlY(b G&HezmDB|(} literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/alias.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/alias.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84fd1f08a5deffd1b4f744f7db4ff1cab309b91f GIT binary patch literal 2456 zcmZ`*&vV;E6y9C^uwpw+D53dL=m<(f4cP8Xdw>~W3N3{T0VbR@Wi+yOV=Iv*XLp?@ z8k++ycm9O-*gJm+XI(k<&M61Vdn+e(T99T}yHC5Tx8M8Tw~CgR>jbXB^zW!xBIGaZ zEM7Kr?m|&NK*b5CDH+m$Qf#x74Xwa3Z7a2hPT&mPz#Z0t8rW>^JSKtn4dE`YJtn*+ z+?f?DagQ&7z0T{qq}6y1tCAKi*X}1uk9Cr&??*bxv#+JhCD^TDG-_F8L-0h0ah~lZ z{j!mpAz?34qHI*ga4$(kOmVgO#o%c{xd%mk0u`tC$YS@@X+fl_W{`#bRKIK1W z`~>83r5NT%qNK9esG9!GaRz9$;EUh@VkF;$OE(p%Gr6rTc-k|{k@wr$;cP~Kg;0Xm*3NU>Wbxp;vC_U8i8$Fi z@x^fz>-5B+d7ce7&w=u@Xee6#qk+i$vB`^ey8^Z4RuHU0ST6uzuq~}rWbz7pPa?78 zI#!q%3oszc*P$pQSpdTtWt6=ru2fLGy6y!aP{(Re?&17Dp@MBgz&L$MK@tE8byov( zXAnMkTKJrxV606U^lfcV*o4m5j8Ss9jqqp(X8~}|0h7OD`yrh&c)GI3$<#Xh180EH z{POC2Guz_sgk1pvLiOAw+55NxuWgbk49kHS-H{|dQRw&C$Tn>ES-@|GF>)7EQgT}jd$`YEK!Br z-p`XvViFmJkr<=WLnTKNl{GF;LOISLcQ$a$+gM%3F|~QZze14Gg3%wr0JRMjp-tw3 zdf|PU+6Ku=o6K`O&)^ed2Ay39>bXt@(82R>lRRWoHnk>9!?`%4 zK;df~EZN7#0`v#VEpCHl%UB#^`HH(>@puiX3uFhnuM_UAlZmyCiUAaK`)S^b(qgsU zu3GKtfc8rp_g`FUxAA#yb<#YJ(vlR*?e|1M8Rv>rH#-V0+g=G$1)c3 z2E187$pG{&*d9Pph!VsfZuhLfc_#7wPODL_B6rQ-Mn~X}hBBHHTzz>$cEmB9?O8`9 z#~nNzl%Z*`xiDfL?+%zi$qji;ppDNJq0tTV(FI4(!&!QtRRsG2lgemXlQr3z<<(d3 F{0lSDXEp!; literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/bdist_egg.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/bdist_egg.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5278a2e91622d34841f95513e99fc5d33fad51a0 GIT binary patch literal 14244 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 X!I^bRpo0D;lX0GRiug;z=0E*E8XA!9 literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dbfab14c355a501ca204243a9a017378e1e778e5 GIT binary patch literal 1846 zcma)6O>f&a7$zxMcAR8g_knKhVZ3Cm54N&qJFEzT4jZu3vZ1{h7zA0QZKbs6l2TH; zHZY(C+8y@~oMZozuG^*eeW3$}J(TSvT{fT;_#x`$`#yT!_hG!f-6Uwk`LFRWH9~%N zFBhASm%Hfp76w5CRb)gNp=89m9wlEB!G!me2v2%P?1|T9g5D=B|0S%+VdBP%jp5}k zy5$%o=~6-5iLSTw()EQeYEMbGCIWb=mm58i+B`DjQQW75G&$P0$I_ToNS+TR7qTB0 zD(7c*yeEh8ajFf^H5a-v>T9L+NtzArG%F9Ebojj@<8m;F(yR{~&1Gf_vviroBgx}T zaKy2x&UlOuW248?s0mMEl@uz@rRY??Zg=<>>Li|6Zs77}n%O*7>LxEN;_-IdO-i;` zzS{CpE=>lDNqZD$@jwbhuN>je@UL-CNe9gGG~@Ta`^N3%ChZkDkl1C&J;0Y^6({)p z*bezgnh$xA3BXM>u;QenW(_|pMm>DueQ?r~IpRCV>zIiijpID+r7F!QOaBR&K5K66 zp?`^PuVa{z1*+hbQj*gnw(w@etp!28*kRdNliKpjO)wI{KYmn{zBcK=xcrwM_FJ^{ ztyKLN#5Az?>W6TsM>3R3r8>`#^f0qJ3#~~)Bgfi?@rkrBXbUjk7U>B20wLi*X3}6Q z>>SJNI8P7UL>D4L);2ITLsf15IyR`KtikSvG)w$`% z%bB;c3-B&SN3qpWMouv;RZeL}_Lat^VGpoadwl6sHNC#h z-X+Am)hM?vD!<$u$b8MF*}`dq%bG0pbmd#JmRo48I_ zYlsjyyUnF#1f<=om(VO(aoVV;G4EmZKDzw?1EEd2g{OgMYm@yJY`^7Jbo$}{GIH1o z%0?8qa*Cp|8AT&43gy;YQS`8g)#^(ooO__YYHw2IT+% literal 0 HcmV?d00001 diff --git a/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/bdist_wininst.cpython-39.pyc b/src/awesome-date-dimension/.venv/lib/python3.9/site-packages/setuptools/command/__pycache__/bdist_wininst.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c325bce307a989a1c47b57d28e3fbf497cbbcdc6 GIT binary patch literal 1022 zcmZuvOK%e~5cXq}tdgdJ3UNXZabl5(3tT8ds1g#~aw!s0F4kskl1+E*#rCEm+MehS zX^;FRUpaB-#0AEiw6v%r&9`IkJihTvIvn;9$l~-@dP)%b5f0ZSg2N%GeF7kmzy&HX zK^T=}N-_F?1QGNM2`cH5e4|q$@DWO)pWuxqS-|T;;cy6Q9|A};#R5S@ug!s{R79e4 zhNh9|LXOxEXCk+bpX4f6))@>jS;%lHfm_gbpmqe%pd~uT4Q|KbV_P zU)@5hu{Lv-TU*N)`>&oKTzMwM_X6>>DEwe+@FJg066$wCXC|N3F4xN6yN!SettF9< ztSmnJ-jHs}Il^a<85 z+^Tr<-G@~Tu@BYWVRuhO143mzJIag^ZIrn|eOD*am*gKqmsncTfr+t<-_qBRqYNjn3NQI%> x05R?lTAI+nqp&ToDuo?yUwnLni3u!QXEO{|oAMuoX_#PJm#{7JtXjt|9cN zUR)jyEbhT0zlDh+YUQY~FtSjAL)+3EoI8aZx`wuMujqw6Lp!-&Y=v7E`WjJ}de0E` zn0