.*) # store the extra garbage
+''', re.VERBOSE).match
+
+
+def _findLocalTimeZoneName(isDST):
+ if not daylight:
+ # Daylight savings does not occur in this time zone.
+ isDST = 0
+ try:
+ # Get the name of the current time zone depending
+ # on DST.
+ _localzone = PytzCache._zmap[tzname[isDST].lower()]
+ except BaseException:
+ try:
+ # Generate a GMT-offset zone name.
+ if isDST:
+ localzone = altzone
+ else:
+ localzone = timezone
+ offset = (-localzone / 3600.0)
+ majorOffset = int(offset)
+ if majorOffset != 0:
+ minorOffset = abs(int((offset % majorOffset) * 60.0))
+ else:
+ minorOffset = 0
+ m = majorOffset >= 0 and '+' or ''
+ lz = '%s%0.02d%0.02d' % (m, majorOffset, minorOffset)
+ _localzone = PytzCache._zmap[('GMT%s' % lz).lower()]
+ except BaseException:
+ _localzone = ''
+ return _localzone
+
+
+_localzone0 = _findLocalTimeZoneName(0)
+_localzone1 = _findLocalTimeZoneName(1)
+_multipleZones = (_localzone0 != _localzone1)
+
+# Some utility functions for calculating dates:
+
+
+def _calcSD(t):
+ # Returns timezone-independent days since epoch and the fractional
+ # part of the days.
+ dd = t + EPOCH - 86400.0
+ d = dd / 86400.0
+ s = d - math.floor(d)
+ return s, d
+
+
+def _calcDependentSecond(tz, t):
+ # Calculates the timezone-dependent second (integer part only)
+ # from the timezone-independent second.
+ fset = _tzoffset(tz, t)
+ return fset + long(math.floor(t)) + long(EPOCH) - 86400
+
+
+def _calcDependentSecond2(yr, mo, dy, hr, mn, sc):
+ # Calculates the timezone-dependent second (integer part only)
+ # from the date given.
+ ss = int(hr) * 3600 + int(mn) * 60 + int(sc)
+ x = long(_julianday(yr, mo, dy) - jd1901) * 86400 + ss
+ return x
+
+
+def _calcIndependentSecondEtc(tz, x, ms):
+ # Derive the timezone-independent second from the timezone
+ # dependent second.
+ fsetAtEpoch = _tzoffset(tz, 0.0)
+ nearTime = x - fsetAtEpoch - long(EPOCH) + 86400 + ms
+ # nearTime is now within an hour of being correct.
+ # Recalculate t according to DST.
+ fset = long(_tzoffset(tz, nearTime))
+ d = (x - fset) / 86400.0 + (ms / 86400.0)
+ t = x - fset - long(EPOCH) + 86400 + ms
+ micros = (x + 86400 - fset) * 1000000 + \
+ long(round(ms * 1000000.0)) - long(EPOCH * 1000000.0)
+ s = d - math.floor(d)
+ return (s, d, t, micros)
+
+
+def _calcHMS(x, ms):
+ # hours, minutes, seconds from integer and float.
+ hr = x // 3600
+ x = x - hr * 3600
+ mn = x // 60
+ sc = x - mn * 60 + ms
+ return (hr, mn, sc)
+
+
+def _calcYMDHMS(x, ms):
+ # x is a timezone-dependent integer of seconds.
+ # Produces yr,mo,dy,hr,mn,sc.
+ yr, mo, dy = _calendarday(x // 86400 + jd1901)
+ x = int(x - (x // 86400) * 86400)
+ hr = x // 3600
+ x = x - hr * 3600
+ mn = x // 60
+ sc = x - mn * 60 + ms
+ return (yr, mo, dy, hr, mn, sc)
+
+
+def _julianday(yr, mo, dy):
+ y, m, d = long(yr), long(mo), long(dy)
+ if m > 12:
+ y = y + m // 12
+ m = m % 12
+ elif m < 1:
+ m = -m
+ y = y - m // 12 - 1
+ m = 12 - m % 12
+ if y > 0:
+ yr_correct = 0
+ else:
+ yr_correct = 3
+ if m < 3:
+ y, m = y - 1, m + 12
+ if y * 10000 + m * 100 + d > 15821014:
+ b = 2 - y // 100 + y // 400
+ else:
+ b = 0
+ return ((1461 * y - yr_correct) // 4 +
+ 306001 * (m + 1) // 10000 + d + 1720994 + b)
+
+
+def _calendarday(j):
+ j = long(j)
+ if (j < 2299160):
+ b = j + 1525
+ else:
+ a = (4 * j - 7468861) // 146097
+ b = j + 1526 + a - a // 4
+ c = (20 * b - 2442) // 7305
+ d = 1461 * c // 4
+ e = 10000 * (b - d) // 306001
+ dy = int(b - d - 306001 * e // 10000)
+ mo = (e < 14) and int(e - 1) or int(e - 13)
+ yr = (mo > 2) and (c - 4716) or (c - 4715)
+ return (int(yr), int(mo), int(dy))
+
+
+def _tzoffset(tz, t):
+ """Returns the offset in seconds to GMT from a specific timezone (tz) at
+ a specific time (t). NB! The _tzoffset result is the same same sign as
+ the time zone, i.e. GMT+2 has a 7200 second offset. This is the opposite
+ sign of time.timezone which (confusingly) is -7200 for GMT+2."""
+ try:
+ return _TZINFO[tz].info(t)[0]
+ except Exception:
+ if numericTimeZoneMatch(tz) is not None:
+ return int(tz[0:3]) * 3600 + int(tz[0] + tz[3:5]) * 60
+ else:
+ return 0 # ??
+
+
+def _correctYear(year):
+ # Y2K patch.
+ if year >= 0 and year < 100:
+ # 00-69 means 2000-2069, 70-99 means 1970-1999.
+ if year < 70:
+ year = 2000 + year
+ else:
+ year = 1900 + year
+ return year
+
+
+def safegmtime(t):
+ '''gmtime with a safety zone.'''
+ try:
+ return gmtime(t)
+ except (ValueError, OverflowError):
+ raise TimeError('The time %f is beyond the range of this Python '
+ 'implementation.' % float(t))
+
+
+def safelocaltime(t):
+ '''localtime with a safety zone.'''
+ try:
+ return localtime(t)
+ except (ValueError, OverflowError):
+ raise TimeError('The time %f is beyond the range of this Python '
+ 'implementation.' % float(t))
+
+
+def _tzoffset2rfc822zone(seconds):
+ """Takes an offset, such as from _tzoffset(), and returns an rfc822
+ compliant zone specification. Please note that the result of
+ _tzoffset() is the negative of what time.localzone and time.altzone is.
+ """
+ return "%+03d%02d" % divmod((seconds // 60), 60)
+
+
+def _tzoffset2iso8601zone(seconds):
+ """Takes an offset, such as from _tzoffset(), and returns an ISO 8601
+ compliant zone specification. Please note that the result of
+ _tzoffset() is the negative of what time.localzone and time.altzone is.
+ """
+ return "%+03d:%02d" % divmod((seconds // 60), 60)
+
+
+def Timezones():
+ """Return the list of recognized timezone names"""
+ return sorted(list(PytzCache._zmap.values()))
+
+
+class strftimeFormatter:
+
+ def __init__(self, dt, format):
+ self.dt = dt
+ self.format = format
+
+ def __call__(self):
+ return self.dt.strftime(self.format)
+
+
+@implementer(IDateTime)
+class DateTime:
+ """DateTime objects represent instants in time and provide
+ interfaces for controlling its representation without
+ affecting the absolute value of the object.
+
+ DateTime objects may be created from a wide variety of string
+ or numeric data, or may be computed from other DateTime objects.
+ DateTimes support the ability to convert their representations
+ to many major timezones, as well as the ability to create a
+ DateTime object in the context of a given timezone.
+
+ DateTime objects provide partial numerical behavior:
+
+ - Two date-time objects can be subtracted to obtain a time,
+ in days between the two.
+
+ - A date-time object and a positive or negative number may
+ be added to obtain a new date-time object that is the given
+ number of days later than the input date-time object.
+
+ - A positive or negative number and a date-time object may
+ be added to obtain a new date-time object that is the given
+ number of days later than the input date-time object.
+
+ - A positive or negative number may be subtracted from a
+ date-time object to obtain a new date-time object that is
+ the given number of days earlier than the input date-time
+ object.
+
+ DateTime objects may be converted to integer, long, or float
+ numbers of days since January 1, 1901, using the standard int,
+ long, and float functions (Compatibility Note: int, long and
+ float return the number of days since 1901 in GMT rather than
+ local machine timezone). DateTime objects also provide access
+ to their value in a float format usable with the Python time
+ module, provided that the value of the object falls in the
+ range of the epoch-based time module, and as a datetime.datetime
+ object.
+
+ A DateTime object should be considered immutable; all conversion
+ and numeric operations return a new DateTime object rather than
+ modify the current object."""
+
+ # For security machinery:
+ __roles__ = None
+ __allow_access_to_unprotected_subobjects__ = 1
+
+ # Limit the amount of instance attributes
+ __slots__ = (
+ '_timezone_naive',
+ '_tz',
+ '_dayoffset',
+ '_year',
+ '_month',
+ '_day',
+ '_hour',
+ '_minute',
+ '_second',
+ '_nearsec',
+ '_d',
+ '_micros',
+ 'time',
+ )
+
+ def __init__(self, *args, **kw):
+ """Return a new date-time object"""
+ try:
+ return self._parse_args(*args, **kw)
+ except (DateError, TimeError, DateTimeError):
+ raise
+ except Exception:
+ raise SyntaxError('Unable to parse {}, {}'.format(args, kw))
+
+ def __getstate__(self):
+ return (self._micros,
+ getattr(self, '_timezone_naive', False),
+ self._tz)
+
+ def __setstate__(self, value):
+ if isinstance(value, tuple):
+ micros, tz_naive, tz = value
+ if isinstance(micros, float):
+ # BBB: support for pickle where micros was a float
+ micros = int(micros * 1000000)
+ self._parse_args(micros / 1000000., tz)
+ self._micros = micros
+ self._timezone_naive = tz_naive
+ else:
+ for k, v in value.items():
+ if k in self.__slots__:
+ setattr(self, k, v)
+ # BBB: support for very old DateTime pickles
+ if '_micros' not in value:
+ self._micros = long(value['_t'] * 1000000)
+ if '_timezone_naive' not in value:
+ self._timezone_naive = False
+
+ def _parse_args(self, *args, **kw):
+ """Return a new date-time object.
+
+ A DateTime object always maintains its value as an absolute
+ UTC time, and is represented in the context of some timezone
+ based on the arguments used to create the object. A DateTime
+ object's methods return values based on the timezone context.
+
+ Note that in all cases the local machine timezone is used for
+ representation if no timezone is specified.
+
+ DateTimes may be created with zero to seven arguments.
+
+ - If the function is called with no arguments or with None,
+ then the current date/time is returned, represented in the
+ timezone of the local machine.
+
+ - If the function is invoked with a single string argument
+ which is a recognized timezone name, an object representing
+ the current time is returned, represented in the specified
+ timezone.
+
+ - If the function is invoked with a single string argument
+ representing a valid date/time, an object representing
+ that date/time will be returned.
+
+ As a general rule, any date-time representation that is
+ recognized and unambiguous to a resident of North America
+ is acceptable. The reason for this qualification is that
+ in North America, a date like: 2/1/1994 is interpreted
+ as February 1, 1994, while in some parts of the world,
+ it is interpreted as January 2, 1994.
+
+ A date/time string consists of two components, a date
+ component and an optional time component, separated by one
+ or more spaces. If the time component is omitted, 12:00am is
+ assumed. Any recognized timezone name specified as the final
+ element of the date/time string will be used for computing
+ the date/time value. If you create a DateTime with the
+ string 'Mar 9, 1997 1:45pm US/Pacific', the value will
+ essentially be the same as if you had captured time.time()
+ at the specified date and time on a machine in that timezone:
+
+
+ e = DateTime('US/Eastern')
+ # returns current date/time, represented in US/Eastern.
+
+ x = DateTime('1997/3/9 1:45pm')
+ # returns specified time, represented in local machine zone.
+
+ y = DateTime('Mar 9, 1997 13:45:00')
+ # y is equal to x
+
+
+ The date component consists of year, month, and day
+ values. The year value must be a one-, two-, or
+ four-digit integer. If a one- or two-digit year is
+ used, the year is assumed to be in the twentieth
+ century. The month may be an integer, from 1 to 12, a
+ month name, or a month abbreviation, where a period may
+ optionally follow the abbreviation. The day must be an
+ integer from 1 to the number of days in the month. The
+ year, month, and day values may be separated by
+ periods, hyphens, forward slashes, or spaces. Extra
+ spaces are permitted around the delimiters. Year,
+ month, and day values may be given in any order as long
+ as it is possible to distinguish the components. If all
+ three components are numbers that are less than 13,
+ then a month-day-year ordering is assumed.
+
+ The time component consists of hour, minute, and second
+ values separated by colons. The hour value must be an
+ integer between 0 and 23 inclusively. The minute value
+ must be an integer between 0 and 59 inclusively. The
+ second value may be an integer value between 0 and
+ 59.999 inclusively. The second value or both the minute
+ and second values may be omitted. The time may be
+ followed by am or pm in upper or lower case, in which
+ case a 12-hour clock is assumed.
+
+ New in Zope 2.4:
+ The DateTime constructor automatically detects and handles
+ ISO8601 compliant dates (YYYY-MM-DDThh:ss:mmTZD).
+
+ New in Zope 2.9.6:
+ The existing ISO8601 parser was extended to support almost
+ the whole ISO8601 specification. New formats includes:
+
+
+ y = DateTime('1993-045')
+ # returns the 45th day from 1993, which is 14th February
+
+ w = DateTime('1993-W06-7')
+ # returns the 7th day from the 6th week from 1993, which
+ # is also 14th February
+
+
+ See http://en.wikipedia.org/wiki/ISO_8601 for full specs.
+
+ Note that the Zope DateTime parser assumes timezone naive ISO
+ strings to be in UTC rather than local time as specified.
+
+ - If the DateTime function is invoked with a single numeric
+ argument, the number is assumed to be a floating point value
+ such as that returned by time.time().
+
+ A DateTime object is returned that represents the GMT value
+ of the time.time() float represented in the local machine's
+ timezone.
+
+ - If the DateTime function is invoked with a single argument
+ that is a DateTime instance, a copy of the passed object will
+ be created.
+
+ - New in 2.11:
+ The DateTime function may now be invoked with a single argument
+ that is a datetime.datetime instance. DateTimes may be converted
+ back to datetime.datetime objects with asdatetime().
+ DateTime instances may be converted to a timezone naive
+ datetime.datetime in UTC with utcdatetime().
+
+ - If the function is invoked with two numeric arguments, then
+ the first is taken to be an integer year and the second
+ argument is taken to be an offset in days from the beginning
+ of the year, in the context of the local machine timezone.
+
+ The date-time value returned is the given offset number of
+ days from the beginning of the given year, represented in
+ the timezone of the local machine. The offset may be positive
+ or negative.
+
+ Two-digit years are assumed to be in the twentieth
+ century.
+
+ - If the function is invoked with two arguments, the first
+ a float representing a number of seconds past the epoch
+ in gmt (such as those returned by time.time()) and the
+ second a string naming a recognized timezone, a DateTime
+ with a value of that gmt time will be returned, represented
+ in the given timezone.
+
+
+ import time
+ t = time.time()
+
+ now_east = DateTime(t,'US/Eastern')
+ # Time t represented as US/Eastern
+
+ now_west = DateTime(t,'US/Pacific')
+ # Time t represented as US/Pacific
+
+ # now_east == now_west
+ # only their representations are different
+
+
+ - If the function is invoked with three or more numeric
+ arguments, then the first is taken to be an integer
+ year, the second is taken to be an integer month, and
+ the third is taken to be an integer day. If the
+ combination of values is not valid, then a
+ DateError is raised. Two-digit years are assumed
+ to be in the twentieth century. The fourth, fifth, and
+ sixth arguments specify a time in hours, minutes, and
+ seconds; hours and minutes should be positive integers
+ and seconds is a positive floating point value, all of
+ these default to zero if not given. An optional string may
+ be given as the final argument to indicate timezone (the
+ effect of this is as if you had taken the value of time.time()
+ at that time on a machine in the specified timezone).
+
+ New in Zope 2.7:
+ A new keyword parameter "datefmt" can be passed to the
+ constructor. If set to "international", the constructor
+ is forced to treat ambiguous dates as "days before month
+ before year". This useful if you need to parse non-US
+ dates in a reliable way
+
+ In any case that a floating point number of seconds is given
+ or derived, it's rounded to the nearest millisecond.
+
+ If a string argument passed to the DateTime constructor cannot be
+ parsed, it will raise DateTime.SyntaxError. Invalid date components
+ will raise a DateError, while invalid time or timezone components
+ will raise a DateTimeError.
+
+ The module function Timezones() will return a list of the (common)
+ timezones recognized by the DateTime module. Recognition of
+ timezone names is case-insensitive.
+ """
+
+ datefmt = kw.get('datefmt', getDefaultDateFormat())
+ d = t = s = None
+ ac = len(args)
+ microsecs = None
+
+ if ac == 10:
+ # Internal format called only by DateTime
+ yr, mo, dy, hr, mn, sc, tz, t, d, s = args
+ elif ac == 11:
+ # Internal format that includes milliseconds (from the epoch)
+ yr, mo, dy, hr, mn, sc, tz, t, d, s, millisecs = args
+ microsecs = millisecs * 1000
+
+ elif ac == 12:
+ # Internal format that includes microseconds (from the epoch) and a
+ # flag indicating whether this was constructed in a timezone naive
+ # manner
+ yr, mo, dy, hr, mn, sc, tz, t, d, s, microsecs, tznaive = args
+ if tznaive is not None: # preserve this information
+ self._timezone_naive = tznaive
+
+ elif not args or (ac and args[0] is None):
+ # Current time, to be displayed in local timezone
+ t = time()
+ lt = safelocaltime(t)
+ tz = self.localZone(lt)
+ ms = (t - math.floor(t))
+ s, d = _calcSD(t)
+ yr, mo, dy, hr, mn, sc = lt[:6]
+ sc = sc + ms
+ self._timezone_naive = False
+
+ elif ac == 1:
+ arg = args[0]
+
+ if arg == '':
+ raise SyntaxError(arg)
+
+ if isinstance(arg, DateTime):
+ """Construct a new DateTime instance from a given
+ DateTime instance.
+ """
+ t = arg.timeTime()
+ s, d = _calcSD(t)
+ yr, mo, dy, hr, mn, sc, tz = arg.parts()
+
+ elif isinstance(arg, datetime):
+ yr, mo, dy, hr, mn, sc, numerictz, tznaive = \
+ self._parse_iso8601_preserving_tznaive(arg.isoformat())
+ if arg.tzinfo is None:
+ self._timezone_naive = True
+ tz = None
+ else:
+ self._timezone_naive = False
+ # if we have a pytz tzinfo, use the `zone` attribute
+ # as a key
+ tz = getattr(arg.tzinfo, 'zone', numerictz)
+ ms = sc - math.floor(sc)
+ x = _calcDependentSecond2(yr, mo, dy, hr, mn, sc)
+
+ if tz:
+ try:
+ zone = _TZINFO[tz]
+ except DateTimeError:
+ try:
+ zone = _TZINFO[numerictz]
+ except DateTimeError:
+ raise DateTimeError(
+ 'Unknown time zone in date: %s' % arg)
+ tz = zone.tzinfo.zone
+ else:
+ tz = self._calcTimezoneName(x, ms)
+ s, d, t, microsecs = _calcIndependentSecondEtc(tz, x, ms)
+
+ elif (isinstance(arg, basestring) and
+ arg.lower() in _TZINFO._zidx):
+ # Current time, to be displayed in specified timezone
+ t, tz = time(), _TZINFO._zmap[arg.lower()]
+ ms = (t - math.floor(t))
+ # Use integer arithmetic as much as possible.
+ s, d = _calcSD(t)
+ x = _calcDependentSecond(tz, t)
+ yr, mo, dy, hr, mn, sc = _calcYMDHMS(x, ms)
+
+ elif isinstance(arg, basestring):
+ # Date/time string
+ iso8601 = iso8601Match(arg.strip())
+ fields_iso8601 = iso8601 and iso8601.groupdict() or {}
+ if fields_iso8601 and not fields_iso8601.get('garbage'):
+ yr, mo, dy, hr, mn, sc, tz, tznaive = \
+ self._parse_iso8601_preserving_tznaive(arg)
+ self._timezone_naive = tznaive
+ else:
+ yr, mo, dy, hr, mn, sc, tz = self._parse(arg, datefmt)
+
+ if not self._validDate(yr, mo, dy):
+ raise DateError('Invalid date: %s' % arg)
+ if not self._validTime(hr, mn, int(sc)):
+ raise TimeError('Invalid time: %s' % arg)
+ ms = sc - math.floor(sc)
+ x = _calcDependentSecond2(yr, mo, dy, hr, mn, sc)
+
+ if tz:
+ try:
+ tz = _TZINFO._zmap[tz.lower()]
+ except KeyError:
+ if numericTimeZoneMatch(tz) is None:
+ raise DateTimeError(
+ 'Unknown time zone in date: %s' % arg)
+ else:
+ tz = self._calcTimezoneName(x, ms)
+ s, d, t, microsecs = _calcIndependentSecondEtc(tz, x, ms)
+
+ else:
+ # Seconds from epoch, gmt
+ t = arg
+ lt = safelocaltime(t)
+ tz = self.localZone(lt)
+ ms = (t - math.floor(t))
+ s, d = _calcSD(t)
+ yr, mo, dy, hr, mn, sc = lt[:6]
+ sc = sc + ms
+
+ elif ac == 2:
+ if isinstance(args[1], basestring):
+ # Seconds from epoch (gmt) and timezone
+ t, tz = args
+ ms = (t - math.floor(t))
+ try:
+ tz = _TZINFO._zmap[tz.lower()]
+ except KeyError:
+ if numericTimeZoneMatch(tz) is None:
+ raise DateTimeError('Unknown time zone: %s' % tz)
+ # Use integer arithmetic as much as possible.
+ s, d = _calcSD(t)
+ x = _calcDependentSecond(tz, t)
+ yr, mo, dy, hr, mn, sc = _calcYMDHMS(x, ms)
+ else:
+ # Year, julian expressed in local zone
+ t = time()
+ lt = safelocaltime(t)
+ tz = self.localZone(lt)
+ yr, jul = args
+ yr = _correctYear(yr)
+ d = (_julianday(yr, 1, 0) - jd1901) + jul
+ x_float = d * 86400.0
+ x_floor = math.floor(x_float)
+ ms = x_float - x_floor
+ x = long(x_floor)
+ yr, mo, dy, hr, mn, sc = _calcYMDHMS(x, ms)
+ s, d, t, microsecs = _calcIndependentSecondEtc(tz, x, ms)
+ else:
+ # Explicit format
+ yr, mo, dy = args[:3]
+ hr, mn, sc, tz = 0, 0, 0, 0
+ yr = _correctYear(yr)
+ if not self._validDate(yr, mo, dy):
+ raise DateError('Invalid date: {}'.format(args))
+ args = args[3:]
+ if args:
+ hr, args = args[0], args[1:]
+ if args:
+ mn, args = args[0], args[1:]
+ if args:
+ sc, args = args[0], args[1:]
+ if args:
+ tz, args = args[0], args[1:]
+ if args:
+ raise DateTimeError('Too many arguments')
+ if not self._validTime(hr, mn, sc):
+ raise TimeError('Invalid time: %s' % repr(args))
+
+ x = _calcDependentSecond2(yr, mo, dy, hr, mn, sc)
+ ms = sc - math.floor(sc)
+ if tz:
+ try:
+ tz = _TZINFO._zmap[tz.lower()]
+ except KeyError:
+ if numericTimeZoneMatch(tz) is None:
+ raise DateTimeError('Unknown time zone: %s' % tz)
+ else:
+ # Get local time zone name
+ tz = self._calcTimezoneName(x, ms)
+ s, d, t, microsecs = _calcIndependentSecondEtc(tz, x, ms)
+
+ self._dayoffset = int((_julianday(yr, mo, dy) + 2) % 7)
+ # Round to nearest microsecond in platform-independent way. You
+ # cannot rely on C sprintf (Python '%') formatting to round
+ # consistently; doing it ourselves ensures that all but truly
+ # horrid C sprintf implementations will yield the same result
+ # cross-platform, provided the format asks for exactly 6 digits after
+ # the decimal point.
+ sc = round(sc, 6)
+ if sc >= 60.0: # can happen if, e.g., orig sc was 59.9999999
+ sc = 59.999999
+ self._nearsec = math.floor(sc)
+ self._year, self._month, self._day = yr, mo, dy
+ self._hour, self._minute, self._second = hr, mn, sc
+ self.time, self._d, self._tz = s, d, tz
+ # self._micros is the time since the epoch
+ # in long integer microseconds.
+ if microsecs is None:
+ microsecs = long(round(t * 1000000.0))
+ self._micros = microsecs
+
+ def localZone(self, ltm=None):
+ '''Returns the time zone on the given date. The time zone
+ can change according to daylight savings.'''
+ if not _multipleZones:
+ return _localzone0
+ if ltm is None:
+ ltm = localtime(time())
+ isDST = ltm[8]
+ lz = isDST and _localzone1 or _localzone0
+ return lz
+
+ def _calcTimezoneName(self, x, ms):
+ # Derive the name of the local time zone at the given
+ # timezone-dependent second.
+ if not _multipleZones:
+ return _localzone0
+ fsetAtEpoch = _tzoffset(_localzone0, 0.0)
+ nearTime = x - fsetAtEpoch - long(EPOCH) + 86400 + ms
+ # nearTime is within an hour of being correct.
+ try:
+ ltm = safelocaltime(nearTime)
+ except BaseException:
+ # We are beyond the range of Python's date support.
+ # Hopefully we can assume that daylight savings schedules
+ # repeat every 28 years. Calculate the name of the
+ # time zone using a supported range of years.
+ yr, mo, dy, hr, mn, sc = _calcYMDHMS(x, 0)
+ yr = ((yr - 1970) % 28) + 1970
+ x = _calcDependentSecond2(yr, mo, dy, hr, mn, sc)
+ nearTime = x - fsetAtEpoch - long(EPOCH) + 86400 + ms
+
+ # nearTime might still be negative if we are east of Greenwich.
+ # But we can assume on 1969/12/31 were no timezone changes.
+ nearTime = max(0, nearTime)
+
+ ltm = safelocaltime(nearTime)
+ tz = self.localZone(ltm)
+ return tz
+
+ def _parse(self, st, datefmt=getDefaultDateFormat()):
+ # Parse date-time components from a string
+ month = year = tz = tm = None
+ ValidZones = _TZINFO._zidx
+ TimeModifiers = ['am', 'pm']
+
+ # Find timezone first, since it should always be the last
+ # element, and may contain a slash, confusing the parser.
+ st = st.strip()
+ sp = st.split()
+ tz = sp[-1]
+ if tz and (tz.lower() in ValidZones):
+ self._timezone_naive = False
+ st = ' '.join(sp[:-1])
+ else:
+ self._timezone_naive = True
+ tz = None # Decide later, since the default time zone
+ # could depend on the date.
+
+ ints = []
+ i = 0
+ len_st = len(st)
+ while i < len_st:
+ while i < len_st and st[i] in SPACE_CHARS:
+ i += 1
+ if i < len_st and st[i] in DELIMITERS:
+ d = st[i]
+ i += 1
+ else:
+ d = ''
+ while i < len_st and st[i] in SPACE_CHARS:
+ i += 1
+
+ # The float pattern needs to look back 1 character, because it
+ # actually looks for a preceding colon like ':33.33'. This is
+ # needed to avoid accidentally matching the date part of a
+ # dot-separated date string such as '1999.12.31'.
+ if i > 0:
+ b = i - 1
+ else:
+ b = i
+
+ ts_results = FLT_PATTERN.match(st, b)
+ if ts_results:
+ s = ts_results.group(1)
+ i = i + len(s)
+ ints.append(float(s))
+ continue
+
+ ts_results = INT_PATTERN.match(st, i)
+ if ts_results:
+ s = ts_results.group(0)
+
+ ls = len(s)
+ i = i + ls
+ if (ls == 4 and d and d in '+-' and
+ (len(ints) + (not not month) >= 3)):
+ tz = '{}{}'.format(d, s)
+ else:
+ v = int(s)
+ ints.append(v)
+ continue
+
+ ts_results = NAME_PATTERN.match(st, i)
+ if ts_results:
+ s = ts_results.group(0).lower()
+ i = i + len(s)
+ if i < len_st and st[i] == '.':
+ i += 1
+ # Check for month name:
+ _v = _MONTHMAP.get(s)
+ if _v is not None:
+ if month is None:
+ month = _v
+ else:
+ raise SyntaxError(st)
+ continue
+ # Check for time modifier:
+ if s in TimeModifiers:
+ if tm is None:
+ tm = s
+ else:
+ raise SyntaxError(st)
+ continue
+ # Check for and skip day of week:
+ if s in _DAYMAP:
+ continue
+
+ raise SyntaxError(st)
+
+ day = None
+ if ints[-1] > 60 and d not in ('.', ':', '/') and len(ints) > 2:
+ year = ints[-1]
+ del ints[-1]
+ if month:
+ day = ints[0]
+ del ints[:1]
+ else:
+ if datefmt == "us":
+ month = ints[0]
+ day = ints[1]
+ else:
+ month = ints[1]
+ day = ints[0]
+ del ints[:2]
+ elif month:
+ if len(ints) > 1:
+ if ints[0] > 31:
+ year = ints[0]
+ day = ints[1]
+ else:
+ year = ints[1]
+ day = ints[0]
+ del ints[:2]
+ elif len(ints) > 2:
+ if ints[0] > 31:
+ year = ints[0]
+ if ints[1] > 12:
+ day = ints[1]
+ month = ints[2]
+ else:
+ day = ints[2]
+ month = ints[1]
+ if ints[1] > 31:
+ year = ints[1]
+ if ints[0] > 12 and ints[2] <= 12:
+ day = ints[0]
+ month = ints[2]
+ elif ints[2] > 12 and ints[0] <= 12:
+ day = ints[2]
+ month = ints[0]
+ elif ints[2] > 31:
+ year = ints[2]
+ if ints[0] > 12:
+ day = ints[0]
+ month = ints[1]
+ else:
+ if datefmt == "us":
+ day = ints[1]
+ month = ints[0]
+ else:
+ day = ints[0]
+ month = ints[1]
+
+ elif ints[0] <= 12:
+ month = ints[0]
+ day = ints[1]
+ year = ints[2]
+ del ints[:3]
+
+ if day is None:
+ # Use today's date.
+ year, month, day = localtime(time())[:3]
+
+ year = _correctYear(year)
+ if year < 1000:
+ raise SyntaxError(st)
+
+ leap = year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
+ try:
+ if not day or day > _MONTH_LEN[leap][month]:
+ raise DateError(st)
+ except IndexError:
+ raise DateError(st)
+
+ tod = 0
+ if ints:
+ i = ints[0]
+ # Modify hour to reflect am/pm
+ if tm and (tm == 'pm') and i < 12:
+ i += 12
+ if tm and (tm == 'am') and i == 12:
+ i = 0
+ if i > 24:
+ raise TimeError(st)
+ tod = tod + int(i) * 3600
+ del ints[0]
+ if ints:
+ i = ints[0]
+ if i > 60:
+ raise TimeError(st)
+ tod = tod + int(i) * 60
+ del ints[0]
+ if ints:
+ i = ints[0]
+ if i > 60:
+ raise TimeError(st)
+ tod = tod + i
+ del ints[0]
+ if ints:
+ raise SyntaxError(st)
+
+ tod_int = int(math.floor(tod))
+ ms = tod - tod_int
+ hr, mn, sc = _calcHMS(tod_int, ms)
+ if not tz:
+ # Figure out what time zone it is in the local area
+ # on the given date.
+ x = _calcDependentSecond2(year, month, day, hr, mn, sc)
+ tz = self._calcTimezoneName(x, ms)
+
+ return year, month, day, hr, mn, sc, tz
+
+ # Internal methods
+ def _validDate(self, y, m, d):
+ if m < 1 or m > 12 or y < 0 or d < 1 or d > 31:
+ return 0
+ return d <= _MONTH_LEN[
+ (y % 4 == 0 and (y % 100 != 0 or y % 400 == 0))][m]
+
+ def _validTime(self, h, m, s):
+ return h >= 0 and h <= 23 and m >= 0 and m <= 59 and s >= 0 and s < 60
+
+ def __getattr__(self, name):
+ if '%' in name:
+ return strftimeFormatter(self, name)
+ raise AttributeError(name)
+
+ # Conversion and comparison methods
+
+ def timeTime(self):
+ """Return the date/time as a floating-point number in UTC,
+ in the format used by the Python time module.
+
+ Note that it is possible to create date/time values with
+ DateTime that have no meaningful value to the time module.
+ """
+ return self._micros / 1000000.0
+
+ def toZone(self, z):
+ """Return a DateTime with the value as the current
+ object, represented in the indicated timezone.
+ """
+ t, tz = self._t, _TZINFO._zmap[z.lower()]
+ micros = self.micros()
+ tznaive = False # you're performing a timzone change, can't be naive
+
+ try:
+ # Try to use time module for speed.
+ yr, mo, dy, hr, mn, sc = safegmtime(t + _tzoffset(tz, t))[:6]
+ sc = self._second
+ return self.__class__(yr, mo, dy, hr, mn, sc, tz, t,
+ self._d, self.time, micros, tznaive)
+ except Exception:
+ # gmtime can't perform the calculation in the given range.
+ # Calculate the difference between the two time zones.
+ tzdiff = _tzoffset(tz, t) - _tzoffset(self._tz, t)
+ if tzdiff == 0:
+ return self
+ sc = self._second
+ ms = sc - math.floor(sc)
+ x = _calcDependentSecond2(self._year, self._month, self._day,
+ self._hour, self._minute, sc)
+ x_new = x + tzdiff
+ yr, mo, dy, hr, mn, sc = _calcYMDHMS(x_new, ms)
+ return self.__class__(yr, mo, dy, hr, mn, sc, tz, t,
+ self._d, self.time, micros, tznaive)
+
+ def isFuture(self):
+ """Return true if this object represents a date/time
+ later than the time of the call.
+ """
+ return (self._t > time())
+
+ def isPast(self):
+ """Return true if this object represents a date/time
+ earlier than the time of the call.
+ """
+ return (self._t < time())
+
+ def isCurrentYear(self):
+ """Return true if this object represents a date/time
+ that falls within the current year, in the context
+ of this object's timezone representation.
+ """
+ t = time()
+ return safegmtime(t + _tzoffset(self._tz, t))[0] == self._year
+
+ def isCurrentMonth(self):
+ """Return true if this object represents a date/time
+ that falls within the current month, in the context
+ of this object's timezone representation.
+ """
+ t = time()
+ gmt = safegmtime(t + _tzoffset(self._tz, t))
+ return gmt[0] == self._year and gmt[1] == self._month
+
+ def isCurrentDay(self):
+ """Return true if this object represents a date/time
+ that falls within the current day, in the context
+ of this object's timezone representation.
+ """
+ t = time()
+ gmt = safegmtime(t + _tzoffset(self._tz, t))
+ return (gmt[0] == self._year and gmt[1] == self._month and
+ gmt[2] == self._day)
+
+ def isCurrentHour(self):
+ """Return true if this object represents a date/time
+ that falls within the current hour, in the context
+ of this object's timezone representation.
+ """
+ t = time()
+ gmt = safegmtime(t + _tzoffset(self._tz, t))
+ return (gmt[0] == self._year and gmt[1] == self._month and
+ gmt[2] == self._day and gmt[3] == self._hour)
+
+ def isCurrentMinute(self):
+ """Return true if this object represents a date/time
+ that falls within the current minute, in the context
+ of this object's timezone representation.
+ """
+ t = time()
+ gmt = safegmtime(t + _tzoffset(self._tz, t))
+ return (gmt[0] == self._year and gmt[1] == self._month and
+ gmt[2] == self._day and gmt[3] == self._hour and
+ gmt[4] == self._minute)
+
+ def earliestTime(self):
+ """Return a new DateTime object that represents the earliest
+ possible time (in whole seconds) that still falls within
+ the current object's day, in the object's timezone context.
+ """
+ return self.__class__(
+ self._year, self._month, self._day, 0, 0, 0, self._tz)
+
+ def latestTime(self):
+ """Return a new DateTime object that represents the latest
+ possible time (in whole seconds) that still falls within
+ the current object's day, in the object's timezone context.
+ """
+ return self.__class__(
+ self._year, self._month, self._day, 23, 59, 59, self._tz)
+
+ def greaterThan(self, t):
+ """Compare this DateTime object to another DateTime object
+ OR a floating point number such as that which is returned
+ by the Python time module.
+
+ Returns true if the object represents a date/time greater
+ than the specified DateTime or time module style time.
+
+ Revised to give more correct results through comparison of
+ long integer microseconds.
+ """
+ if t is None:
+ return True
+ if isinstance(t, (float, int)):
+ return self._micros > long(t * 1000000)
+ try:
+ return self._micros > t._micros
+ except AttributeError:
+ return self._micros > t
+
+ __gt__ = greaterThan
+
+ def greaterThanEqualTo(self, t):
+ """Compare this DateTime object to another DateTime object
+ OR a floating point number such as that which is returned
+ by the Python time module.
+
+ Returns true if the object represents a date/time greater
+ than or equal to the specified DateTime or time module style
+ time.
+
+ Revised to give more correct results through comparison of
+ long integer microseconds.
+ """
+ if t is None:
+ return True
+ if isinstance(t, (float, int)):
+ return self._micros >= long(t * 1000000)
+ try:
+ return self._micros >= t._micros
+ except AttributeError:
+ return self._micros >= t
+
+ __ge__ = greaterThanEqualTo
+
+ def equalTo(self, t):
+ """Compare this DateTime object to another DateTime object
+ OR a floating point number such as that which is returned
+ by the Python time module.
+
+ Returns true if the object represents a date/time equal to
+ the specified DateTime or time module style time.
+
+ Revised to give more correct results through comparison of
+ long integer microseconds.
+ """
+ if t is None:
+ return False
+ if isinstance(t, (float, int)):
+ return self._micros == long(t * 1000000)
+ try:
+ return self._micros == t._micros
+ except AttributeError:
+ return self._micros == t
+
+ def notEqualTo(self, t):
+ """Compare this DateTime object to another DateTime object
+ OR a floating point number such as that which is returned
+ by the Python time module.
+
+ Returns true if the object represents a date/time not equal
+ to the specified DateTime or time module style time.
+
+ Revised to give more correct results through comparison of
+ long integer microseconds.
+ """
+ return not self.equalTo(t)
+
+ def __eq__(self, t):
+ """Compare this DateTime object to another DateTime object.
+ Return True if their internal state is the same. Two objects
+ representing the same time in different timezones are regared as
+ unequal. Use the equalTo method if you are only interested in them
+ referring to the same moment in time.
+ """
+ if not isinstance(t, DateTime):
+ return False
+ return (self._micros, self._tz) == (t._micros, t._tz)
+
+ def __ne__(self, t):
+ return not self.__eq__(t)
+
+ def lessThan(self, t):
+ """Compare this DateTime object to another DateTime object
+ OR a floating point number such as that which is returned
+ by the Python time module.
+
+ Returns true if the object represents a date/time less than
+ the specified DateTime or time module style time.
+
+ Revised to give more correct results through comparison of
+ long integer microseconds.
+ """
+ if t is None:
+ return False
+ if isinstance(t, (float, int)):
+ return self._micros < long(t * 1000000)
+ try:
+ return self._micros < t._micros
+ except AttributeError:
+ return self._micros < t
+
+ __lt__ = lessThan
+
+ def lessThanEqualTo(self, t):
+ """Compare this DateTime object to another DateTime object
+ OR a floating point number such as that which is returned
+ by the Python time module.
+
+ Returns true if the object represents a date/time less than
+ or equal to the specified DateTime or time module style time.
+
+ Revised to give more correct results through comparison of
+ long integer microseconds.
+ """
+ if t is None:
+ return False
+ if isinstance(t, (float, int)):
+ return self._micros <= long(t * 1000000)
+ try:
+ return self._micros <= t._micros
+ except AttributeError:
+ return self._micros <= t
+
+ __le__ = lessThanEqualTo
+
+ def isLeapYear(self):
+ """Return true if the current year (in the context of the
+ object's timezone) is a leap year.
+ """
+ return (self._year % 4 == 0 and
+ (self._year % 100 != 0 or self._year % 400 == 0))
+
+ def dayOfYear(self):
+ """Return the day of the year, in context of the timezone
+ representation of the object.
+ """
+ d = int(self._d + (_tzoffset(self._tz, self._t) / 86400.0))
+ return int((d + jd1901) - _julianday(self._year, 1, 0))
+
+ # Component access
+ def parts(self):
+ """Return a tuple containing the calendar year, month,
+ day, hour, minute second and timezone of the object.
+ """
+ return (self._year, self._month, self._day, self._hour,
+ self._minute, self._second, self._tz)
+
+ def timezone(self):
+ """Return the timezone in which the object is represented."""
+ return self._tz
+
+ def tzoffset(self):
+ """Return the timezone offset for the objects timezone."""
+ return _tzoffset(self._tz, self._t)
+
+ def year(self):
+ """Return the calendar year of the object."""
+ return self._year
+
+ def month(self):
+ """Return the month of the object as an integer."""
+ return self._month
+
+ @property
+ def _fmon(self):
+ return _MONTHS[self._month]
+
+ def Month(self):
+ """Return the full month name."""
+ return self._fmon
+
+ @property
+ def _amon(self):
+ return _MONTHS_A[self._month]
+
+ def aMonth(self):
+ """Return the abbreviated month name."""
+ return self._amon
+
+ def Mon(self):
+ """Compatibility: see aMonth."""
+ return self._amon
+
+ @property
+ def _pmon(self):
+ return _MONTHS_P[self._month]
+
+ def pMonth(self):
+ """Return the abbreviated (with period) month name."""
+ return self._pmon
+
+ def Mon_(self):
+ """Compatibility: see pMonth."""
+ return self._pmon
+
+ def day(self):
+ """Return the integer day."""
+ return self._day
+
+ @property
+ def _fday(self):
+ return _DAYS[self._dayoffset]
+
+ def Day(self):
+ """Return the full name of the day of the week."""
+ return self._fday
+
+ def DayOfWeek(self):
+ """Compatibility: see Day."""
+ return self._fday
+
+ @property
+ def _aday(self):
+ return _DAYS_A[self._dayoffset]
+
+ def aDay(self):
+ """Return the abbreviated name of the day of the week."""
+ return self._aday
+
+ @property
+ def _pday(self):
+ return _DAYS_P[self._dayoffset]
+
+ def pDay(self):
+ """Return the abbreviated (with period) name of the day of the week."""
+ return self._pday
+
+ def Day_(self):
+ """Compatibility: see pDay."""
+ return self._pday
+
+ def dow(self):
+ """Return the integer day of the week, where Sunday is 0."""
+ return self._dayoffset
+
+ def dow_1(self):
+ """Return the integer day of the week, where Sunday is 1."""
+ return self._dayoffset + 1
+
+ @property
+ def _pmhour(self):
+ hr = self._hour
+ if hr > 12:
+ return hr - 12
+ return hr or 12
+
+ def h_12(self):
+ """Return the 12-hour clock representation of the hour."""
+ return self._pmhour
+
+ def h_24(self):
+ """Return the 24-hour clock representation of the hour."""
+ return self._hour
+
+ @property
+ def _pm(self):
+ hr = self._hour
+ if hr >= 12:
+ return 'pm'
+ return 'am'
+
+ def ampm(self):
+ """Return the appropriate time modifier (am or pm)."""
+ return self._pm
+
+ def hour(self):
+ """Return the 24-hour clock representation of the hour."""
+ return self._hour
+
+ def minute(self):
+ """Return the minute."""
+ return self._minute
+
+ def second(self):
+ """Return the second."""
+ return self._second
+
+ def millis(self):
+ """Return the millisecond since the epoch in GMT."""
+ return self._micros // 1000
+
+ def micros(self):
+ """Return the microsecond since the epoch in GMT."""
+ return self._micros
+
+ def timezoneNaive(self):
+ """The Python datetime module introduces the idea of distinguishing
+ between timezone aware and timezone naive datetime values. For lossless
+ conversion to and from datetime.datetime we record this
+ information using True / False. DateTime makes no distinction, if we
+ don't have any information we return None here.
+ """
+ try:
+ return self._timezone_naive
+ except AttributeError:
+ return None
+
+ def strftime(self, format):
+ """Format the date/time using the *current timezone representation*."""
+ x = _calcDependentSecond2(self._year, self._month, self._day,
+ self._hour, self._minute, self._second)
+ ltz = self._calcTimezoneName(x, 0)
+ tzdiff = _tzoffset(ltz, self._t) - _tzoffset(self._tz, self._t)
+ zself = self + tzdiff / 86400.0
+ microseconds = int((zself._second - zself._nearsec) * 1000000)
+ unicode_format = False
+ if isinstance(format, explicit_unicode_type):
+ format = format.encode('utf-8')
+ unicode_format = True
+ ds = datetime(zself._year, zself._month, zself._day, zself._hour,
+ zself._minute, int(zself._nearsec),
+ microseconds).strftime(format)
+ if unicode_format:
+ return ds.decode('utf-8')
+ return ds
+
+ # General formats from previous DateTime
+ def Date(self):
+ """Return the date string for the object."""
+ return "%s/%2.2d/%2.2d" % (self._year, self._month, self._day)
+
+ def Time(self):
+ """Return the time string for an object to the nearest second."""
+ return '%2.2d:%2.2d:%2.2d' % (self._hour, self._minute, self._nearsec)
+
+ def TimeMinutes(self):
+ """Return the time string for an object not showing seconds."""
+ return '%2.2d:%2.2d' % (self._hour, self._minute)
+
+ def AMPM(self):
+ """Return the time string for an object to the nearest second."""
+ return '%2.2d:%2.2d:%2.2d %s' % (
+ self._pmhour, self._minute, self._nearsec, self._pm)
+
+ def AMPMMinutes(self):
+ """Return the time string for an object not showing seconds."""
+ return '%2.2d:%2.2d %s' % (self._pmhour, self._minute, self._pm)
+
+ def PreciseTime(self):
+ """Return the time string for the object."""
+ return '%2.2d:%2.2d:%06.3f' % (self._hour, self._minute, self._second)
+
+ def PreciseAMPM(self):
+ """Return the time string for the object."""
+ return '%2.2d:%2.2d:%06.3f %s' % (
+ self._pmhour, self._minute, self._second, self._pm)
+
+ def yy(self):
+ """Return calendar year as a 2 digit string."""
+ return str(self._year)[-2:]
+
+ def mm(self):
+ """Return month as a 2 digit string."""
+ return '%02d' % self._month
+
+ def dd(self):
+ """Return day as a 2 digit string."""
+ return '%02d' % self._day
+
+ def rfc822(self):
+ """Return the date in RFC 822 format."""
+ tzoffset = _tzoffset2rfc822zone(_tzoffset(self._tz, self._t))
+ return '%s, %2.2d %s %d %2.2d:%2.2d:%2.2d %s' % (
+ self._aday, self._day, self._amon, self._year,
+ self._hour, self._minute, self._nearsec, tzoffset)
+
+ # New formats
+ def fCommon(self):
+ """Return a string representing the object's value
+ in the format: March 1, 1997 1:45 pm.
+ """
+ return '%s %s, %4.4d %s:%2.2d %s' % (
+ self._fmon, self._day, self._year, self._pmhour,
+ self._minute, self._pm)
+
+ def fCommonZ(self):
+ """Return a string representing the object's value
+ in the format: March 1, 1997 1:45 pm US/Eastern.
+ """
+ return '%s %s, %4.4d %d:%2.2d %s %s' % (
+ self._fmon, self._day, self._year, self._pmhour,
+ self._minute, self._pm, self._tz)
+
+ def aCommon(self):
+ """Return a string representing the object's value
+ in the format: Mar 1, 1997 1:45 pm.
+ """
+ return '%s %s, %4.4d %s:%2.2d %s' % (
+ self._amon, self._day, self._year, self._pmhour,
+ self._minute, self._pm)
+
+ def aCommonZ(self):
+ """Return a string representing the object's value
+ in the format: Mar 1, 1997 1:45 pm US/Eastern.
+ """
+ return '%s %s, %4.4d %d:%2.2d %s %s' % (
+ self._amon, self._day, self._year, self._pmhour,
+ self._minute, self._pm, self._tz)
+
+ def pCommon(self):
+ """Return a string representing the object's value
+ in the format: Mar. 1, 1997 1:45 pm.
+ """
+ return '%s %s, %4.4d %s:%2.2d %s' % (
+ self._pmon, self._day, self._year, self._pmhour,
+ self._minute, self._pm)
+
+ def pCommonZ(self):
+ """Return a string representing the object's value
+ in the format: Mar. 1, 1997 1:45 pm US/Eastern.
+ """
+ return '%s %s, %4.4d %d:%2.2d %s %s' % (
+ self._pmon, self._day, self._year, self._pmhour,
+ self._minute, self._pm, self._tz)
+
+ def ISO(self):
+ """Return the object in ISO standard format.
+
+ Note: this is *not* ISO 8601-format! See the ISO8601 and
+ HTML4 methods below for ISO 8601-compliant output.
+
+ Dates are output as: YYYY-MM-DD HH:MM:SS
+ """
+ return "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" % (
+ self._year, self._month, self._day,
+ self._hour, self._minute, self._second)
+
+ def ISO8601(self):
+ """Return the object in ISO 8601-compatible format containing the
+ date, time with seconds-precision and the time zone identifier.
+
+ See: http://www.w3.org/TR/NOTE-datetime
+
+ Dates are output as: YYYY-MM-DDTHH:MM:SSTZD
+ T is a literal character.
+ TZD is Time Zone Designator, format +HH:MM or -HH:MM
+
+ If the instance is timezone naive (it was not specified with a timezone
+ when it was constructed) then the timezone is omitted.
+
+ The HTML4 method below offers the same formatting, but converts
+ to UTC before returning the value and sets the TZD "Z".
+ """
+ if self.timezoneNaive():
+ return "%0.4d-%0.2d-%0.2dT%0.2d:%0.2d:%0.2d" % (
+ self._year, self._month, self._day,
+ self._hour, self._minute, self._second)
+ tzoffset = _tzoffset2iso8601zone(_tzoffset(self._tz, self._t))
+ return "%0.4d-%0.2d-%0.2dT%0.2d:%0.2d:%0.2d%s" % (
+ self._year, self._month, self._day,
+ self._hour, self._minute, self._second, tzoffset)
+
+ def HTML4(self):
+ """Return the object in the format used in the HTML4.0 specification,
+ one of the standard forms in ISO8601.
+
+ See: http://www.w3.org/TR/NOTE-datetime
+
+ Dates are output as: YYYY-MM-DDTHH:MM:SSZ
+ T, Z are literal characters.
+ The time is in UTC.
+ """
+ newdate = self.toZone('UTC')
+ return "%0.4d-%0.2d-%0.2dT%0.2d:%0.2d:%0.2dZ" % (
+ newdate._year, newdate._month, newdate._day,
+ newdate._hour, newdate._minute, newdate._second)
+
+ def asdatetime(self):
+ """Return a standard library datetime.datetime
+ """
+ tznaive = self.timezoneNaive()
+ if tznaive:
+ tzinfo = None
+ else:
+ tzinfo = _TZINFO[self._tz].tzinfo
+ second = int(self._second)
+ microsec = self.micros() % 1000000
+ dt = datetime(self._year, self._month, self._day, self._hour,
+ self._minute, second, microsec, tzinfo)
+ return dt
+
+ def utcdatetime(self):
+ """Convert the time to UTC and return a timezone naive datetime object
+ """
+ utc = self.toZone('UTC')
+ second = int(utc._second)
+ microsec = utc.micros() % 1000000
+ dt = datetime(utc._year, utc._month, utc._day, utc._hour,
+ utc._minute, second, microsec)
+ return dt
+
+ def __add__(self, other):
+ """A DateTime may be added to a number and a number may be
+ added to a DateTime; two DateTimes cannot be added.
+ """
+ if hasattr(other, '_t'):
+ raise DateTimeError('Cannot add two DateTimes')
+ o = float(other)
+ tz = self._tz
+ omicros = round(o * 86400000000)
+ tmicros = self.micros() + omicros
+ t = tmicros / 1000000.0
+ d = (tmicros + long(EPOCH * 1000000)) / 86400000000.0
+ s = d - math.floor(d)
+ ms = t - math.floor(t)
+ x = _calcDependentSecond(tz, t)
+ yr, mo, dy, hr, mn, sc = _calcYMDHMS(x, ms)
+ return self.__class__(yr, mo, dy, hr, mn, sc, self._tz,
+ t, d, s, tmicros, self.timezoneNaive())
+
+ __radd__ = __add__
+
+ def __sub__(self, other):
+ """Either a DateTime or a number may be subtracted from a
+ DateTime, however, a DateTime may not be subtracted from
+ a number.
+ """
+ if hasattr(other, '_d'):
+ return (self.micros() - other.micros()) / 86400000000.0
+ else:
+ return self.__add__(-(other))
+
+ def __repr__(self):
+ """Convert a DateTime to a string that looks like a Python
+ expression.
+ """
+ return '{}(\'{}\')'.format(self.__class__.__name__, str(self))
+
+ def __str__(self):
+ """Convert a DateTime to a string."""
+ y, m, d = self._year, self._month, self._day
+ h, mn, s, t = self._hour, self._minute, self._second, self._tz
+ if s == int(s):
+ # A whole number of seconds -- suppress milliseconds.
+ return '%4.4d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d %s' % (
+ y, m, d, h, mn, s, t)
+ else:
+ # s is already rounded to the nearest microsecond, and
+ # it's not a whole number of seconds. Be sure to print
+ # 2 digits before the decimal point.
+ return '%4.4d/%2.2d/%2.2d %2.2d:%2.2d:%06.6f %s' % (
+ y, m, d, h, mn, s, t)
+
+ def __format__(self, fmt):
+ """Render a DateTime in an f-string."""
+ if not isinstance(fmt, str):
+ raise TypeError("must be str, not %s" % type(fmt).__name__)
+ if len(fmt) != 0:
+ return self.strftime(fmt)
+ return str(self)
+
+ def __hash__(self):
+ """Compute a hash value for a DateTime."""
+ return int(((self._year % 100 * 12 + self._month) * 31 +
+ self._day + self.time) * 100)
+
+ def __int__(self):
+ """Convert to an integer number of seconds since the epoch (gmt)."""
+ return int(self.micros() // 1000000)
+
+ def __long__(self):
+ """Convert to a long-int number of seconds since the epoch (gmt)."""
+ return long(self.micros() // 1000000) # pragma: PY2
+
+ def __float__(self):
+ """Convert to floating-point number of seconds since the epoch (gmt).
+ """
+ return self.micros() / 1000000.0
+
+ @property
+ def _t(self):
+ return self._micros / 1000000.0
+
+ def _parse_iso8601(self, s):
+ # preserve the previously implied contract
+ # who knows where this could be used...
+ return self._parse_iso8601_preserving_tznaive(s)[:7]
+
+ def _parse_iso8601_preserving_tznaive(self, s):
+ try:
+ return self.__parse_iso8601(s)
+ except IndexError:
+ raise SyntaxError(
+ 'Not an ISO 8601 compliant date string: "%s"' % s)
+
+ def __parse_iso8601(self, s):
+ """Parse an ISO 8601 compliant date.
+
+ See: http://en.wikipedia.org/wiki/ISO_8601
+ """
+ month = day = week_day = 1
+ year = hour = minute = seconds = hour_off = min_off = 0
+ tznaive = True
+
+ iso8601 = iso8601Match(s.strip())
+ fields = iso8601 and iso8601.groupdict() or {}
+ if not iso8601 or fields.get('garbage'):
+ raise IndexError
+
+ if fields['year']:
+ year = int(fields['year'])
+ if fields['month']:
+ month = int(fields['month'])
+ if fields['day']:
+ day = int(fields['day'])
+
+ if fields['year_day']:
+ d = DateTime('%s-01-01' % year) + int(fields['year_day']) - 1
+ month = d.month()
+ day = d.day()
+
+ if fields['week']:
+ week = int(fields['week'])
+ if fields['week_day']:
+ week_day = int(fields['week_day'])
+ d = DateTime('%s-01-04' % year)
+ d = d - (d.dow() + 6) % 7 + week * 7 + week_day - 8
+ month = d.month()
+ day = d.day()
+
+ if fields['hour']:
+ hour = int(fields['hour'])
+
+ if fields['minute']:
+ minute = int(fields['minute'])
+ elif fields['fraction']:
+ minute = 60.0 * float('0.%s' % fields['fraction'])
+ seconds, minute = math.modf(minute)
+ minute = int(minute)
+ seconds = 60.0 * seconds
+ # Avoid reprocess when handling seconds, bellow
+ fields['fraction'] = None
+
+ if fields['second']:
+ seconds = int(fields['second'])
+ if fields['fraction']:
+ seconds = seconds + float('0.%s' % fields['fraction'])
+ elif fields['fraction']:
+ seconds = 60.0 * float('0.%s' % fields['fraction'])
+
+ if fields['hour_off']:
+ hour_off = int(fields['hour_off'])
+ if fields['signal'] == '-':
+ hour_off *= -1
+
+ if fields['min_off']:
+ min_off = int(fields['min_off'])
+
+ if fields['signal'] or fields['Z']:
+ tznaive = False
+ else:
+ tznaive = True
+
+ # Differ from the specification here. To preserve backwards
+ # compatibility assume a default timezone == UTC.
+ tz = 'GMT%+03d%02d' % (hour_off, min_off)
+
+ return year, month, day, hour, minute, seconds, tz, tznaive
+
+ def JulianDay(self):
+ """Return the Julian day.
+
+ See: https://www.tondering.dk/claus/cal/julperiod.php#formula
+ """
+ a = (14 - self._month) // 12
+ y = self._year + 4800 - a
+ m = self._month + (12 * a) - 3
+ return (self._day + (153 * m + 2) // 5 + 365 * y +
+ y // 4 - y // 100 + y // 400 - 32045)
+
+ def week(self):
+ """Return the week number according to ISO.
+
+ See: https://www.tondering.dk/claus/cal/week.php#weekno
+ """
+ J = self.JulianDay()
+ d4 = (J + 31741 - (J % 7)) % 146097 % 36524 % 1461
+ L = d4 // 1460
+ d1 = ((d4 - L) % 365) + L
+ return d1 // 7 + 1
+
+ def encode(self, out):
+ """Encode value for XML-RPC."""
+ out.write('')
+ out.write(self.ISO8601())
+ out.write('\n')
+
+
+# Provide the _dt_reconstructor function here, in case something
+# accidentally creates a reference to this function
+
+orig_reconstructor = copy_reg._reconstructor
+
+
+def _dt_reconstructor(cls, base, state):
+ if cls is DateTime:
+ return cls(state)
+ return orig_reconstructor(cls, base, state)
diff --git a/testcline/lib/python3.12/site-packages/DateTime/DateTime.txt b/testcline/lib/python3.12/site-packages/DateTime/DateTime.txt
new file mode 100644
index 0000000..aaa9f8f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/DateTime/DateTime.txt
@@ -0,0 +1,785 @@
+The DateTime package
+====================
+
+Encapsulation of date/time values.
+
+
+Function Timezones()
+--------------------
+
+Returns the list of recognized timezone names:
+
+ >>> from DateTime import Timezones
+ >>> zones = set(Timezones())
+
+Almost all of the standard pytz timezones are included, with the exception
+of some commonly-used but ambiguous abbreviations, where historical Zope
+usage conflicts with the name used by pytz:
+
+ >>> import pytz
+ >>> [x for x in pytz.all_timezones if x not in zones]
+ ['CET', 'EET', 'EST', 'MET', 'MST', 'WET']
+
+Class DateTime
+--------------
+
+DateTime objects represent instants in time and provide interfaces for
+controlling its representation without affecting the absolute value of
+the object.
+
+DateTime objects may be created from a wide variety of string or
+numeric data, or may be computed from other DateTime objects.
+DateTimes support the ability to convert their representations to many
+major timezones, as well as the ability to create a DateTime object
+in the context of a given timezone.
+
+DateTime objects provide partial numerical behavior:
+
+* Two date-time objects can be subtracted to obtain a time, in days
+ between the two.
+
+* A date-time object and a positive or negative number may be added to
+ obtain a new date-time object that is the given number of days later
+ than the input date-time object.
+
+* A positive or negative number and a date-time object may be added to
+ obtain a new date-time object that is the given number of days later
+ than the input date-time object.
+
+* A positive or negative number may be subtracted from a date-time
+ object to obtain a new date-time object that is the given number of
+ days earlier than the input date-time object.
+
+DateTime objects may be converted to integer, long, or float numbers
+of days since January 1, 1901, using the standard int, long, and float
+functions (Compatibility Note: int, long and float return the number
+of days since 1901 in GMT rather than local machine timezone).
+DateTime objects also provide access to their value in a float format
+usable with the Python time module, provided that the value of the
+object falls in the range of the epoch-based time module.
+
+A DateTime object should be considered immutable; all conversion and numeric
+operations return a new DateTime object rather than modify the current object.
+
+A DateTime object always maintains its value as an absolute UTC time,
+and is represented in the context of some timezone based on the
+arguments used to create the object. A DateTime object's methods
+return values based on the timezone context.
+
+Note that in all cases the local machine timezone is used for
+representation if no timezone is specified.
+
+Constructor for DateTime
+------------------------
+
+DateTime() returns a new date-time object. DateTimes may be created
+with from zero to seven arguments:
+
+* If the function is called with no arguments, then the current date/
+ time is returned, represented in the timezone of the local machine.
+
+* If the function is invoked with a single string argument which is a
+ recognized timezone name, an object representing the current time is
+ returned, represented in the specified timezone.
+
+* If the function is invoked with a single string argument
+ representing a valid date/time, an object representing that date/
+ time will be returned.
+
+ As a general rule, any date-time representation that is recognized
+ and unambiguous to a resident of North America is acceptable. (The
+ reason for this qualification is that in North America, a date like:
+ 2/1/1994 is interpreted as February 1, 1994, while in some parts of
+ the world, it is interpreted as January 2, 1994.) A date/ time
+ string consists of two components, a date component and an optional
+ time component, separated by one or more spaces. If the time
+ component is omitted, 12:00am is assumed.
+
+ Any recognized timezone name specified as the final element of the
+ date/time string will be used for computing the date/time value.
+ (If you create a DateTime with the string,
+ "Mar 9, 1997 1:45pm US/Pacific", the value will essentially be the
+ same as if you had captured time.time() at the specified date and
+ time on a machine in that timezone). If no timezone is passed, then
+ the timezone configured on the local machine will be used, **except**
+ that if the date format matches ISO 8601 ('YYYY-MM-DD'), the instance
+ will use UTC / GMT+0 as the timezone.
+
+ o Returns current date/time, represented in US/Eastern:
+
+ >>> from DateTime import DateTime
+ >>> e = DateTime('US/Eastern')
+ >>> e.timezone()
+ 'US/Eastern'
+
+ o Returns specified time, represented in local machine zone:
+
+ >>> x = DateTime('1997/3/9 1:45pm')
+ >>> x.parts() # doctest: +ELLIPSIS
+ (1997, 3, 9, 13, 45, ...)
+
+ o Specified time in local machine zone, verbose format:
+
+ >>> y = DateTime('Mar 9, 1997 13:45:00')
+ >>> y.parts() # doctest: +ELLIPSIS
+ (1997, 3, 9, 13, 45, ...)
+ >>> y == x
+ True
+
+ o Specified time in UTC via ISO 8601 rule:
+
+ >>> z = DateTime('2014-03-24')
+ >>> z.parts() # doctest: +ELLIPSIS
+ (2014, 3, 24, 0, 0, ...)
+ >>> z.timezone()
+ 'GMT+0'
+
+ The date component consists of year, month, and day values. The
+ year value must be a one-, two-, or four-digit integer. If a one-
+ or two-digit year is used, the year is assumed to be in the
+ twentieth century. The month may an integer, from 1 to 12, a month
+ name, or a month abbreviation, where a period may optionally follow
+ the abbreviation. The day must be an integer from 1 to the number of
+ days in the month. The year, month, and day values may be separated
+ by periods, hyphens, forward slashes, or spaces. Extra spaces are
+ permitted around the delimiters. Year, month, and day values may be
+ given in any order as long as it is possible to distinguish the
+ components. If all three components are numbers that are less than
+ 13, then a month-day-year ordering is assumed.
+
+ The time component consists of hour, minute, and second values
+ separated by colons. The hour value must be an integer between 0
+ and 23 inclusively. The minute value must be an integer between 0
+ and 59 inclusively. The second value may be an integer value
+ between 0 and 59.999 inclusively. The second value or both the
+ minute and second values may be omitted. The time may be followed
+ by am or pm in upper or lower case, in which case a 12-hour clock is
+ assumed.
+
+* If the DateTime function is invoked with a single numeric argument,
+ the number is assumed to be either a floating point value such as
+ that returned by time.time(), or a number of days after January 1,
+ 1901 00:00:00 UTC.
+
+ A DateTime object is returned that represents either the GMT value
+ of the time.time() float represented in the local machine's
+ timezone, or that number of days after January 1, 1901. Note that
+ the number of days after 1901 need to be expressed from the
+ viewpoint of the local machine's timezone. A negative argument will
+ yield a date-time value before 1901.
+
+* If the function is invoked with two numeric arguments, then the
+ first is taken to be an integer year and the second argument is
+ taken to be an offset in days from the beginning of the year, in the
+ context of the local machine timezone. The date-time value returned
+ is the given offset number of days from the beginning of the given
+ year, represented in the timezone of the local machine. The offset
+ may be positive or negative. Two-digit years are assumed to be in
+ the twentieth century.
+
+* If the function is invoked with two arguments, the first a float
+ representing a number of seconds past the epoch in GMT (such as
+ those returned by time.time()) and the second a string naming a
+ recognized timezone, a DateTime with a value of that GMT time will
+ be returned, represented in the given timezone.
+
+ >>> import time
+ >>> t = time.time()
+
+ Time t represented as US/Eastern:
+
+ >>> now_east = DateTime(t, 'US/Eastern')
+
+ Time t represented as US/Pacific:
+
+ >>> now_west = DateTime(t, 'US/Pacific')
+
+ Only their representations are different:
+
+ >>> now_east.equalTo(now_west)
+ True
+
+* If the function is invoked with three or more numeric arguments,
+ then the first is taken to be an integer year, the second is taken
+ to be an integer month, and the third is taken to be an integer day.
+ If the combination of values is not valid, then a DateTimeError is
+ raised. One- or two-digit years up to 69 are assumed to be in the
+ 21st century, whereas values 70-99 are assumed to be 20th century.
+ The fourth, fifth, and sixth arguments are floating point, positive
+ or negative offsets in units of hours, minutes, and days, and
+ default to zero if not given. An optional string may be given as
+ the final argument to indicate timezone (the effect of this is as if
+ you had taken the value of time.time() at that time on a machine in
+ the specified timezone).
+
+If a string argument passed to the DateTime constructor cannot be
+parsed, it will raise SyntaxError. Invalid date, time, or
+timezone components will raise a DateTimeError.
+
+The module function Timezones() will return a list of the timezones
+recognized by the DateTime module. Recognition of timezone names is
+case-insensitive.
+
+Instance Methods for DateTime (IDateTime interface)
+---------------------------------------------------
+
+Conversion and comparison methods
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* ``timeTime()`` returns the date/time as a floating-point number in
+ UTC, in the format used by the Python time module. Note that it is
+ possible to create date /time values with DateTime that have no
+ meaningful value to the time module, and in such cases a
+ DateTimeError is raised. A DateTime object's value must generally
+ be between Jan 1, 1970 (or your local machine epoch) and Jan 2038 to
+ produce a valid time.time() style value.
+
+ >>> dt = DateTime('Mar 9, 1997 13:45:00 US/Eastern')
+ >>> dt.timeTime()
+ 857933100.0
+
+ >>> DateTime('2040/01/01 UTC').timeTime()
+ 2208988800.0
+
+ >>> DateTime('1900/01/01 UTC').timeTime()
+ -2208988800.0
+
+* ``toZone(z)`` returns a DateTime with the value as the current
+ object, represented in the indicated timezone:
+
+ >>> dt.toZone('UTC')
+ DateTime('1997/03/09 18:45:00 UTC')
+
+ >>> dt.toZone('UTC').equalTo(dt)
+ True
+
+* ``isFuture()`` returns true if this object represents a date/time
+ later than the time of the call:
+
+ >>> dt.isFuture()
+ False
+ >>> DateTime('Jan 1 3000').isFuture() # not time-machine safe!
+ True
+
+* ``isPast()`` returns true if this object represents a date/time
+ earlier than the time of the call:
+
+ >>> dt.isPast()
+ True
+ >>> DateTime('Jan 1 3000').isPast() # not time-machine safe!
+ False
+
+* ``isCurrentYear()`` returns true if this object represents a
+ date/time that falls within the current year, in the context of this
+ object's timezone representation:
+
+ >>> dt.isCurrentYear()
+ False
+ >>> DateTime().isCurrentYear()
+ True
+
+* ``isCurrentMonth()`` returns true if this object represents a
+ date/time that falls within the current month, in the context of
+ this object's timezone representation:
+
+ >>> dt.isCurrentMonth()
+ False
+ >>> DateTime().isCurrentMonth()
+ True
+
+* ``isCurrentDay()`` returns true if this object represents a
+ date/time that falls within the current day, in the context of this
+ object's timezone representation:
+
+ >>> dt.isCurrentDay()
+ False
+ >>> DateTime().isCurrentDay()
+ True
+
+* ``isCurrentHour()`` returns true if this object represents a
+ date/time that falls within the current hour, in the context of this
+ object's timezone representation:
+
+ >>> dt.isCurrentHour()
+ False
+
+ >>> DateTime().isCurrentHour()
+ True
+
+* ``isCurrentMinute()`` returns true if this object represents a
+ date/time that falls within the current minute, in the context of
+ this object's timezone representation:
+
+ >>> dt.isCurrentMinute()
+ False
+ >>> DateTime().isCurrentMinute()
+ True
+
+* ``isLeapYear()`` returns true if the current year (in the context of
+ the object's timezone) is a leap year:
+
+ >>> dt.isLeapYear()
+ False
+ >>> DateTime('Mar 8 2004').isLeapYear()
+ True
+
+* ``earliestTime()`` returns a new DateTime object that represents the
+ earliest possible time (in whole seconds) that still falls within
+ the current object's day, in the object's timezone context:
+
+ >>> dt.earliestTime()
+ DateTime('1997/03/09 00:00:00 US/Eastern')
+
+* ``latestTime()`` return a new DateTime object that represents the
+ latest possible time (in whole seconds) that still falls within the
+ current object's day, in the object's timezone context
+
+ >>> dt.latestTime()
+ DateTime('1997/03/09 23:59:59 US/Eastern')
+
+Component access
+~~~~~~~~~~~~~~~~
+
+* ``parts()`` returns a tuple containing the calendar year, month,
+ day, hour, minute second and timezone of the object
+
+ >>> dt.parts() # doctest: +ELLIPSIS
+ (1997, 3, 9, 13, 45, ... 'US/Eastern')
+
+* ``timezone()`` returns the timezone in which the object is represented:
+
+ >>> dt.timezone() in Timezones()
+ True
+
+* ``tzoffset()`` returns the timezone offset for the objects timezone:
+
+ >>> dt.tzoffset()
+ -18000
+
+* ``year()`` returns the calendar year of the object:
+
+ >>> dt.year()
+ 1997
+
+* ``month()`` returns the month of the object as an integer:
+
+ >>> dt.month()
+ 3
+
+* ``Month()`` returns the full month name:
+
+ >>> dt.Month()
+ 'March'
+
+* ``aMonth()`` returns the abbreviated month name:
+
+ >>> dt.aMonth()
+ 'Mar'
+
+* ``pMonth()`` returns the abbreviated (with period) month name:
+
+ >>> dt.pMonth()
+ 'Mar.'
+
+* ``day()`` returns the integer day:
+
+ >>> dt.day()
+ 9
+
+* ``Day()`` returns the full name of the day of the week:
+
+ >>> dt.Day()
+ 'Sunday'
+
+* ``dayOfYear()`` returns the day of the year, in context of the
+ timezone representation of the object:
+
+ >>> dt.dayOfYear()
+ 68
+
+* ``aDay()`` returns the abbreviated name of the day of the week:
+
+ >>> dt.aDay()
+ 'Sun'
+
+* ``pDay()`` returns the abbreviated (with period) name of the day of
+ the week:
+
+ >>> dt.pDay()
+ 'Sun.'
+
+* ``dow()`` returns the integer day of the week, where Sunday is 0:
+
+ >>> dt.dow()
+ 0
+
+* ``dow_1()`` returns the integer day of the week, where sunday is 1:
+
+ >>> dt.dow_1()
+ 1
+
+* ``h_12()`` returns the 12-hour clock representation of the hour:
+
+ >>> dt.h_12()
+ 1
+
+* ``h_24()`` returns the 24-hour clock representation of the hour:
+
+ >>> dt.h_24()
+ 13
+
+* ``ampm()`` returns the appropriate time modifier (am or pm):
+
+ >>> dt.ampm()
+ 'pm'
+
+* ``hour()`` returns the 24-hour clock representation of the hour:
+
+ >>> dt.hour()
+ 13
+
+* ``minute()`` returns the minute:
+
+ >>> dt.minute()
+ 45
+
+* ``second()`` returns the second:
+
+ >>> dt.second() == 0
+ True
+
+* ``millis()`` returns the milliseconds since the epoch in GMT.
+
+ >>> dt.millis() == 857933100000
+ True
+
+strftime()
+~~~~~~~~~~
+
+See ``tests/test_datetime.py``.
+
+General formats from previous DateTime
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* ``Date()`` return the date string for the object:
+
+ >>> dt.Date()
+ '1997/03/09'
+
+* ``Time()`` returns the time string for an object to the nearest
+ second:
+
+ >>> dt.Time()
+ '13:45:00'
+
+* ``TimeMinutes()`` returns the time string for an object not showing
+ seconds:
+
+ >>> dt.TimeMinutes()
+ '13:45'
+
+* ``AMPM()`` returns the time string for an object to the nearest second:
+
+ >>> dt.AMPM()
+ '01:45:00 pm'
+
+* ``AMPMMinutes()`` returns the time string for an object not showing
+ seconds:
+
+ >>> dt.AMPMMinutes()
+ '01:45 pm'
+
+* ``PreciseTime()`` returns the time string for the object:
+
+ >>> dt.PreciseTime()
+ '13:45:00.000'
+
+* ``PreciseAMPM()`` returns the time string for the object:
+
+ >>> dt.PreciseAMPM()
+ '01:45:00.000 pm'
+
+* ``yy()`` returns the calendar year as a 2 digit string
+
+ >>> dt.yy()
+ '97'
+
+* ``mm()`` returns the month as a 2 digit string
+
+ >>> dt.mm()
+ '03'
+
+* ``dd()`` returns the day as a 2 digit string:
+
+ >>> dt.dd()
+ '09'
+
+* ``rfc822()`` returns the date in RFC 822 format:
+
+ >>> dt.rfc822()
+ 'Sun, 09 Mar 1997 13:45:00 -0500'
+
+New formats
+~~~~~~~~~~~
+
+* ``fCommon()`` returns a string representing the object's value in
+ the format: March 9, 1997 1:45 pm:
+
+ >>> dt.fCommon()
+ 'March 9, 1997 1:45 pm'
+
+* ``fCommonZ()`` returns a string representing the object's value in
+ the format: March 9, 1997 1:45 pm US/Eastern:
+
+ >>> dt.fCommonZ()
+ 'March 9, 1997 1:45 pm US/Eastern'
+
+* ``aCommon()`` returns a string representing the object's value in
+ the format: Mar 9, 1997 1:45 pm:
+
+ >>> dt.aCommon()
+ 'Mar 9, 1997 1:45 pm'
+
+* ``aCommonZ()`` return a string representing the object's value in
+ the format: Mar 9, 1997 1:45 pm US/Eastern:
+
+ >>> dt.aCommonZ()
+ 'Mar 9, 1997 1:45 pm US/Eastern'
+
+* ``pCommon()`` returns a string representing the object's value in
+ the format Mar. 9, 1997 1:45 pm:
+
+ >>> dt.pCommon()
+ 'Mar. 9, 1997 1:45 pm'
+
+* ``pCommonZ()`` returns a string representing the object's value in
+ the format: Mar. 9, 1997 1:45 pm US/Eastern:
+
+ >>> dt.pCommonZ()
+ 'Mar. 9, 1997 1:45 pm US/Eastern'
+
+* ``ISO()`` returns a string with the date/time in ISO format. Note:
+ this is not ISO 8601-format! See the ISO8601 and HTML4 methods below
+ for ISO 8601-compliant output. Dates are output as: YYYY-MM-DD HH:MM:SS
+
+ >>> dt.ISO()
+ '1997-03-09 13:45:00'
+
+* ``ISO8601()`` returns the object in ISO 8601-compatible format
+ containing the date, time with seconds-precision and the time zone
+ identifier - see http://www.w3.org/TR/NOTE-datetime. Dates are
+ output as: YYYY-MM-DDTHH:MM:SSTZD (T is a literal character, TZD is
+ Time Zone Designator, format +HH:MM or -HH:MM).
+
+ The ``HTML4()`` method below offers the same formatting, but
+ converts to UTC before returning the value and sets the TZD"Z"
+
+ >>> dt.ISO8601()
+ '1997-03-09T13:45:00-05:00'
+
+
+* ``HTML4()`` returns the object in the format used in the HTML4.0
+ specification, one of the standard forms in ISO8601. See
+ http://www.w3.org/TR/NOTE-datetime. Dates are output as:
+ YYYY-MM-DDTHH:MM:SSZ (T, Z are literal characters, the time is in
+ UTC.):
+
+ >>> dt.HTML4()
+ '1997-03-09T18:45:00Z'
+
+* ``JulianDay()`` returns the Julian day according to
+ http://www.tondering.dk/claus/cal/node3.html#sec-calcjd
+
+ >>> dt.JulianDay()
+ 2450517
+
+* ``week()`` returns the week number according to ISO
+ see http://www.tondering.dk/claus/cal/node6.html#SECTION00670000000000000000
+
+ >>> dt.week()
+ 10
+
+Deprecated API
+~~~~~~~~~~~~~~
+
+* DayOfWeek(): see Day()
+
+* Day_(): see pDay()
+
+* Mon(): see aMonth()
+
+* Mon_(): see pMonth
+
+General Services Provided by DateTime
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+DateTimes can be repr()'ed; the result will be a string indicating how
+to make a DateTime object like this:
+
+ >>> repr(dt)
+ "DateTime('1997/03/09 13:45:00 US/Eastern')"
+
+When we convert them into a string, we get a nicer string that could
+actually be shown to a user:
+
+ >>> str(dt)
+ '1997/03/09 13:45:00 US/Eastern'
+
+The hash value of a DateTime is based on the date and time and is
+equal for different representations of the DateTime:
+
+ >>> hash(dt)
+ 3618678
+ >>> hash(dt.toZone('UTC'))
+ 3618678
+
+DateTime objects can be compared to other DateTime objects OR floating
+point numbers such as the ones which are returned by the Python time
+module by using the equalTo method. Using this API, True is returned if the
+object represents a date/time equal to the specified DateTime or time module
+style time:
+
+ >>> dt.equalTo(dt)
+ True
+ >>> dt.equalTo(dt.toZone('UTC'))
+ True
+ >>> dt.equalTo(dt.timeTime())
+ True
+ >>> dt.equalTo(DateTime())
+ False
+
+Same goes for inequalities:
+
+ >>> dt.notEqualTo(dt)
+ False
+ >>> dt.notEqualTo(dt.toZone('UTC'))
+ False
+ >>> dt.notEqualTo(dt.timeTime())
+ False
+ >>> dt.notEqualTo(DateTime())
+ True
+
+Normal equality operations only work with DateTime objects and take the
+timezone setting into account:
+
+ >>> dt == dt
+ True
+ >>> dt == dt.toZone('UTC')
+ False
+ >>> dt == DateTime()
+ False
+
+ >>> dt != dt
+ False
+ >>> dt != dt.toZone('UTC')
+ True
+ >>> dt != DateTime()
+ True
+
+But the other comparison operations compare the referenced moment in time and
+not the representation itself:
+
+ >>> dt > dt
+ False
+ >>> DateTime() > dt
+ True
+ >>> dt > DateTime().timeTime()
+ False
+ >>> DateTime().timeTime() > dt
+ True
+
+ >>> dt.greaterThan(dt)
+ False
+ >>> DateTime().greaterThan(dt)
+ True
+ >>> dt.greaterThan(DateTime().timeTime())
+ False
+
+ >>> dt >= dt
+ True
+ >>> DateTime() >= dt
+ True
+ >>> dt >= DateTime().timeTime()
+ False
+ >>> DateTime().timeTime() >= dt
+ True
+
+ >>> dt.greaterThanEqualTo(dt)
+ True
+ >>> DateTime().greaterThanEqualTo(dt)
+ True
+ >>> dt.greaterThanEqualTo(DateTime().timeTime())
+ False
+
+ >>> dt < dt
+ False
+ >>> DateTime() < dt
+ False
+ >>> dt < DateTime().timeTime()
+ True
+ >>> DateTime().timeTime() < dt
+ False
+
+ >>> dt.lessThan(dt)
+ False
+ >>> DateTime().lessThan(dt)
+ False
+ >>> dt.lessThan(DateTime().timeTime())
+ True
+
+ >>> dt <= dt
+ True
+ >>> DateTime() <= dt
+ False
+ >>> dt <= DateTime().timeTime()
+ True
+ >>> DateTime().timeTime() <= dt
+ False
+
+ >>> dt.lessThanEqualTo(dt)
+ True
+ >>> DateTime().lessThanEqualTo(dt)
+ False
+ >>> dt.lessThanEqualTo(DateTime().timeTime())
+ True
+
+Numeric Services Provided by DateTime
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A DateTime may be added to a number and a number may be added to a
+DateTime:
+
+ >>> dt + 5
+ DateTime('1997/03/14 13:45:00 US/Eastern')
+ >>> 5 + dt
+ DateTime('1997/03/14 13:45:00 US/Eastern')
+
+Two DateTimes cannot be added:
+
+ >>> from DateTime.interfaces import DateTimeError
+ >>> try:
+ ... dt + dt
+ ... print('fail')
+ ... except DateTimeError:
+ ... print('ok')
+ ok
+
+Either a DateTime or a number may be subtracted from a DateTime,
+however, a DateTime may not be subtracted from a number:
+
+ >>> DateTime('1997/03/10 13:45 US/Eastern') - dt
+ 1.0
+ >>> dt - 1
+ DateTime('1997/03/08 13:45:00 US/Eastern')
+ >>> 1 - dt
+ Traceback (most recent call last):
+ ...
+ TypeError: unsupported operand type(s) for -: 'int' and 'DateTime'
+
+DateTimes can also be converted to integers (number of seconds since
+the epoch) and floats:
+
+ >>> int(dt)
+ 857933100
+ >>> float(dt)
+ 857933100.0
diff --git a/testcline/lib/python3.12/site-packages/DateTime/__init__.py b/testcline/lib/python3.12/site-packages/DateTime/__init__.py
new file mode 100644
index 0000000..4e2df6d
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/DateTime/__init__.py
@@ -0,0 +1,18 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Foundation and Contributors.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+from .DateTime import DateTime
+from .DateTime import Timezones
+
+
+__all__ = ('DateTime', 'Timezones')
diff --git a/testcline/lib/python3.12/site-packages/DateTime/__pycache__/DateTime.cpython-312.pyc b/testcline/lib/python3.12/site-packages/DateTime/__pycache__/DateTime.cpython-312.pyc
new file mode 100644
index 0000000..5c1f468
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/DateTime/__pycache__/DateTime.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/DateTime/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/DateTime/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..863698c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/DateTime/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/DateTime/__pycache__/interfaces.cpython-312.pyc b/testcline/lib/python3.12/site-packages/DateTime/__pycache__/interfaces.cpython-312.pyc
new file mode 100644
index 0000000..0be975b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/DateTime/__pycache__/interfaces.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/DateTime/__pycache__/pytz_support.cpython-312.pyc b/testcline/lib/python3.12/site-packages/DateTime/__pycache__/pytz_support.cpython-312.pyc
new file mode 100644
index 0000000..91c5d47
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/DateTime/__pycache__/pytz_support.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/DateTime/interfaces.py b/testcline/lib/python3.12/site-packages/DateTime/interfaces.py
new file mode 100644
index 0000000..80e7707
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/DateTime/interfaces.py
@@ -0,0 +1,375 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Foundation and Contributors.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+from zope.interface import Interface
+
+
+class DateTimeError(Exception):
+ pass
+
+
+class SyntaxError(DateTimeError):
+ pass
+
+
+class DateError(DateTimeError):
+ pass
+
+
+class TimeError(DateTimeError):
+ pass
+
+
+class IDateTime(Interface):
+ # Conversion and comparison methods
+
+ def localZone(ltm=None):
+ """Returns the time zone on the given date. The time zone
+ can change according to daylight savings."""
+
+ def timeTime():
+ """Return the date/time as a floating-point number in UTC, in
+ the format used by the Python time module. Note that it is
+ possible to create date/time values with DateTime that have no
+ meaningful value to the time module."""
+
+ def toZone(z):
+ """Return a DateTime with the value as the current object,
+ represented in the indicated timezone."""
+
+ def isFuture():
+ """Return true if this object represents a date/time later
+ than the time of the call"""
+
+ def isPast():
+ """Return true if this object represents a date/time earlier
+ than the time of the call"""
+
+ def isCurrentYear():
+ """Return true if this object represents a date/time that
+ falls within the current year, in the context of this
+ object's timezone representation"""
+
+ def isCurrentMonth():
+ """Return true if this object represents a date/time that
+ falls within the current month, in the context of this
+ object's timezone representation"""
+
+ def isCurrentDay():
+ """Return true if this object represents a date/time that
+ falls within the current day, in the context of this object's
+ timezone representation"""
+
+ def isCurrentHour():
+ """Return true if this object represents a date/time that
+ falls within the current hour, in the context of this object's
+ timezone representation"""
+
+ def isCurrentMinute():
+ """Return true if this object represents a date/time that
+ falls within the current minute, in the context of this
+ object's timezone representation"""
+
+ def isLeapYear():
+ """Return true if the current year (in the context of the
+ object's timezone) is a leap year"""
+
+ def earliestTime():
+ """Return a new DateTime object that represents the earliest
+ possible time (in whole seconds) that still falls within the
+ current object's day, in the object's timezone context"""
+
+ def latestTime():
+ """Return a new DateTime object that represents the latest
+ possible time (in whole seconds) that still falls within the
+ current object's day, in the object's timezone context"""
+
+ def greaterThan(t):
+ """Compare this DateTime object to another DateTime object OR
+ a floating point number such as that which is returned by the
+ Python time module. Returns true if the object represents a
+ date/time greater than the specified DateTime or time module
+ style time. Revised to give more correct results through
+ comparison of long integer milliseconds."""
+
+ __gt__ = greaterThan
+
+ def greaterThanEqualTo(t):
+ """Compare this DateTime object to another DateTime object OR
+ a floating point number such as that which is returned by the
+ Python time module. Returns true if the object represents a
+ date/time greater than or equal to the specified DateTime or
+ time module style time. Revised to give more correct results
+ through comparison of long integer milliseconds."""
+
+ __ge__ = greaterThanEqualTo
+
+ def equalTo(t):
+ """Compare this DateTime object to another DateTime object OR
+ a floating point number such as that which is returned by the
+ Python time module. Returns true if the object represents a
+ date/time equal to the specified DateTime or time module style
+ time. Revised to give more correct results through comparison
+ of long integer milliseconds."""
+
+ __eq__ = equalTo
+
+ def notEqualTo(t):
+ """Compare this DateTime object to another DateTime object OR
+ a floating point number such as that which is returned by the
+ Python time module. Returns true if the object represents a
+ date/time not equal to the specified DateTime or time module
+ style time. Revised to give more correct results through
+ comparison of long integer milliseconds."""
+
+ __ne__ = notEqualTo
+
+ def lessThan(t):
+ """Compare this DateTime object to another DateTime object OR
+ a floating point number such as that which is returned by the
+ Python time module. Returns true if the object represents a
+ date/time less than the specified DateTime or time module
+ style time. Revised to give more correct results through
+ comparison of long integer milliseconds."""
+
+ __lt__ = lessThan
+
+ def lessThanEqualTo(t):
+ """Compare this DateTime object to another DateTime object OR
+ a floating point number such as that which is returned by the
+ Python time module. Returns true if the object represents a
+ date/time less than or equal to the specified DateTime or time
+ module style time. Revised to give more correct results
+ through comparison of long integer milliseconds."""
+
+ __le__ = lessThanEqualTo
+
+ # Component access
+
+ def parts():
+ """Return a tuple containing the calendar year, month, day,
+ hour, minute second and timezone of the object"""
+
+ def timezone():
+ """Return the timezone in which the object is represented."""
+
+ def tzoffset():
+ """Return the timezone offset for the objects timezone."""
+
+ def year():
+ """Return the calendar year of the object"""
+
+ def month():
+ """Return the month of the object as an integer"""
+
+ def Month():
+ """Return the full month name"""
+
+ def aMonth():
+ """Return the abbreviated month name."""
+
+ def Mon():
+ """Compatibility: see aMonth"""
+
+ def pMonth():
+ """Return the abbreviated (with period) month name."""
+
+ def Mon_():
+ """Compatibility: see pMonth"""
+
+ def day():
+ """Return the integer day"""
+
+ def Day():
+ """Return the full name of the day of the week"""
+
+ def DayOfWeek():
+ """Compatibility: see Day"""
+
+ def dayOfYear():
+ """Return the day of the year, in context of the timezone
+ representation of the object"""
+
+ def aDay():
+ """Return the abbreviated name of the day of the week"""
+
+ def pDay():
+ """Return the abbreviated (with period) name of the day of the
+ week"""
+
+ def Day_():
+ """Compatibility: see pDay"""
+
+ def dow():
+ """Return the integer day of the week, where sunday is 0"""
+
+ def dow_1():
+ """Return the integer day of the week, where sunday is 1"""
+
+ def h_12():
+ """Return the 12-hour clock representation of the hour"""
+
+ def h_24():
+ """Return the 24-hour clock representation of the hour"""
+
+ def ampm():
+ """Return the appropriate time modifier (am or pm)"""
+
+ def hour():
+ """Return the 24-hour clock representation of the hour"""
+
+ def minute():
+ """Return the minute"""
+
+ def second():
+ """Return the second"""
+
+ def millis():
+ """Return the millisecond since the epoch in GMT."""
+
+ def strftime(format):
+ """Format the date/time using the *current timezone representation*."""
+
+ # General formats from previous DateTime
+
+ def Date():
+ """Return the date string for the object."""
+
+ def Time():
+ """Return the time string for an object to the nearest second."""
+
+ def TimeMinutes():
+ """Return the time string for an object not showing seconds."""
+
+ def AMPM():
+ """Return the time string for an object to the nearest second."""
+
+ def AMPMMinutes():
+ """Return the time string for an object not showing seconds."""
+
+ def PreciseTime():
+ """Return the time string for the object."""
+
+ def PreciseAMPM():
+ """Return the time string for the object."""
+
+ def yy():
+ """Return calendar year as a 2 digit string"""
+
+ def mm():
+ """Return month as a 2 digit string"""
+
+ def dd():
+ """Return day as a 2 digit string"""
+
+ def rfc822():
+ """Return the date in RFC 822 format"""
+
+ # New formats
+
+ def fCommon():
+ """Return a string representing the object's value in the
+ format: March 1, 1997 1:45 pm"""
+
+ def fCommonZ():
+ """Return a string representing the object's value in the
+ format: March 1, 1997 1:45 pm US/Eastern"""
+
+ def aCommon():
+ """Return a string representing the object's value in the
+ format: Mar 1, 1997 1:45 pm"""
+
+ def aCommonZ():
+ """Return a string representing the object's value in the
+ format: Mar 1, 1997 1:45 pm US/Eastern"""
+
+ def pCommon():
+ """Return a string representing the object's value in the
+ format: Mar. 1, 1997 1:45 pm"""
+
+ def pCommonZ():
+ """Return a string representing the object's value
+ in the format: Mar. 1, 1997 1:45 pm US/Eastern"""
+
+ def ISO():
+ """Return the object in ISO standard format. Note: this is
+ *not* ISO 8601-format! See the ISO8601 and HTML4 methods below
+ for ISO 8601-compliant output
+
+ Dates are output as: YYYY-MM-DD HH:MM:SS
+ """
+
+ def ISO8601():
+ """Return the object in ISO 8601-compatible format containing
+ the date, time with seconds-precision and the time zone
+ identifier - see http://www.w3.org/TR/NOTE-datetime
+
+ Dates are output as: YYYY-MM-DDTHH:MM:SSTZD
+ T is a literal character.
+ TZD is Time Zone Designator, format +HH:MM or -HH:MM
+
+ The HTML4 method below offers the same formatting, but
+ converts to UTC before returning the value and sets the TZD"Z"
+ """
+
+ def HTML4():
+ """Return the object in the format used in the HTML4.0
+ specification, one of the standard forms in ISO8601. See
+ http://www.w3.org/TR/NOTE-datetime
+
+ Dates are output as: YYYY-MM-DDTHH:MM:SSZ
+ T, Z are literal characters.
+ The time is in UTC.
+ """
+
+ def JulianDay():
+ """Return the Julian day according to
+ https://www.tondering.dk/claus/cal/julperiod.php#formula
+ """
+
+ def week():
+ """Return the week number according to ISO.
+
+ See https://www.tondering.dk/claus/cal/week.php#weekno
+ """
+
+ # Python operator and conversion API
+
+ def __add__(other):
+ """A DateTime may be added to a number and a number may be
+ added to a DateTime; two DateTimes cannot be added."""
+
+ __radd__ = __add__
+
+ def __sub__(other):
+ """Either a DateTime or a number may be subtracted from a
+ DateTime, however, a DateTime may not be subtracted from a
+ number."""
+
+ def __repr__():
+ """Convert a DateTime to a string that looks like a Python
+ expression."""
+
+ def __str__():
+ """Convert a DateTime to a string."""
+
+ def __hash__():
+ """Compute a hash value for a DateTime"""
+
+ def __int__():
+ """Convert to an integer number of seconds since the epoch (gmt)"""
+
+ def __long__():
+ """Convert to a long-int number of seconds since the epoch (gmt)"""
+
+ def __float__():
+ """Convert to floating-point number of seconds since the epoch (gmt)"""
diff --git a/testcline/lib/python3.12/site-packages/DateTime/pytz.txt b/testcline/lib/python3.12/site-packages/DateTime/pytz.txt
new file mode 100644
index 0000000..3a87338
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/DateTime/pytz.txt
@@ -0,0 +1,192 @@
+Pytz Support
+============
+
+Allows the pytz package to be used for time zone information. The
+advantage of using pytz is that it has a more complete and up to date
+time zone and daylight savings time database.
+
+Usage
+-----
+You don't have to do anything special to make it work.
+
+ >>> from DateTime import DateTime, Timezones
+ >>> d = DateTime('March 11, 2007 US/Eastern')
+
+Daylight Savings
+----------------
+In 2007 daylight savings time in the US was changed. The Energy Policy
+Act of 2005 mandates that DST will start on the second Sunday in March
+and end on the first Sunday in November.
+
+In 2007, the start and stop dates are March 11 and November 4,
+respectively. These dates are different from previous DST start and
+stop dates. In 2006, the dates were the first Sunday in April (April
+2, 2006) and the last Sunday in October (October 29, 2006).
+
+Let's make sure that DateTime can deal with this, since the primary
+motivation to use pytz for time zone information is the fact that it
+is kept up to date with daylight savings changes.
+
+ >>> DateTime('March 11, 2007 US/Eastern').tzoffset()
+ -18000
+ >>> DateTime('March 12, 2007 US/Eastern').tzoffset()
+ -14400
+ >>> DateTime('November 4, 2007 US/Eastern').tzoffset()
+ -14400
+ >>> DateTime('November 5, 2007 US/Eastern').tzoffset()
+ -18000
+
+Let's compare this to 2006.
+
+ >>> DateTime('April 2, 2006 US/Eastern').tzoffset()
+ -18000
+ >>> DateTime('April 3, 2006 US/Eastern').tzoffset()
+ -14400
+ >>> DateTime('October 29, 2006 US/Eastern').tzoffset()
+ -14400
+ >>> DateTime('October 30, 2006 US/Eastern').tzoffset()
+ -18000
+
+Time Zones
+---------
+DateTime can use pytz's large database of time zones. Here are some
+examples:
+
+ >>> d = DateTime('Pacific/Kwajalein')
+ >>> d = DateTime('America/Shiprock')
+ >>> d = DateTime('Africa/Ouagadougou')
+
+Of course pytz doesn't know about everything.
+
+ >>> from DateTime.interfaces import SyntaxError
+ >>> try:
+ ... d = DateTime('July 21, 1969 Moon/Eastern')
+ ... print('fail')
+ ... except SyntaxError:
+ ... print('ok')
+ ok
+
+You can still use zone names that DateTime defines that aren't part of
+the pytz database.
+
+ >>> d = DateTime('eet')
+ >>> d = DateTime('iceland')
+
+These time zones use DateTimes database. So it's preferable to use the
+official time zone name.
+
+One trickiness is that DateTime supports some zone name
+abbreviations. Some of these map to pytz names, so these abbreviations
+will give you time zone date from pytz. Notable among abbreviations
+that work this way are 'est', 'cst', 'mst', and 'pst'.
+
+Let's verify that 'est' picks up the 2007 daylight savings time changes.
+
+ >>> DateTime('March 11, 2007 est').tzoffset()
+ -18000
+ >>> DateTime('March 12, 2007 est').tzoffset()
+ -14400
+ >>> DateTime('November 4, 2007 est').tzoffset()
+ -14400
+ >>> DateTime('November 5, 2007 est').tzoffset()
+ -18000
+
+You can get a list of time zones supported by calling the Timezones() function.
+
+ >>> Timezones() #doctest: +ELLIPSIS
+ ['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', ...]
+
+Note that you can mess with this list without hurting things.
+
+ >>> t = Timezones()
+ >>> t.remove('US/Eastern')
+ >>> d = DateTime('US/Eastern')
+
+
+Internal Components
+-------------------
+
+The following are tests of internal components.
+
+Cache
+~~~~~
+
+The DateTime class uses a new time zone cache.
+
+ >>> from DateTime.DateTime import _TZINFO
+ >>> _TZINFO #doctest: +ELLIPSIS
+
+
+The cache maps time zone names to time zone instances.
+
+ >>> cache = _TZINFO
+ >>> tz = cache['GMT+730']
+ >>> tz = cache['US/Mountain']
+
+The cache also must provide a few attributes for use by the DateTime
+class.
+
+The _zlst attribute is a list of supported time zone names.
+
+ >>> cache._zlst #doctest: +ELLIPSIS
+ ['Africa/Abidjan'... 'Africa/Accra'... 'IDLE'... 'NZST'... 'NZT'...]
+
+The _zidx attribute is a list of lower-case and possibly abbreviated
+time zone names that can be mapped to official zone names.
+
+ >>> 'australia/yancowinna' in cache._zidx
+ True
+ >>> 'europe/isle_of_man' in cache._zidx
+ True
+ >>> 'gmt+0500' in cache._zidx
+ True
+
+Note that there are more items in _zidx than in _zlst since there are
+multiple names for some time zones.
+
+ >>> len(cache._zidx) > len(cache._zlst)
+ True
+
+Each entry in _zlst should also be present in _zidx in lower case form.
+
+ >>> for name in cache._zlst:
+ ... if not name.lower() in cache._zidx:
+ ... print("Error %s not in _zidx" % name.lower())
+
+The _zmap attribute maps the names in _zidx to official names in _zlst.
+
+ >>> cache._zmap['africa/abidjan']
+ 'Africa/Abidjan'
+ >>> cache._zmap['gmt+1']
+ 'GMT+1'
+ >>> cache._zmap['gmt+0100']
+ 'GMT+1'
+ >>> cache._zmap['utc']
+ 'UTC'
+
+Let's make sure that _zmap and _zidx agree.
+
+ >>> idx = set(cache._zidx)
+ >>> keys = set(cache._zmap.keys())
+ >>> idx == keys
+ True
+
+Timezone objects
+~~~~~~~~~~~~~~~~
+The timezone instances have only one public method info(). It returns
+a tuple of (offset, is_dst, name). The method takes a timestamp, which
+is used to determine dst information.
+
+ >>> t1 = DateTime('November 4, 00:00 2007 US/Mountain').timeTime()
+ >>> t2 = DateTime('November 4, 02:00 2007 US/Mountain').timeTime()
+ >>> tz.info(t1)
+ (-21600, 1, 'MDT')
+ >>> tz.info(t2)
+ (-25200, 0, 'MST')
+
+If you don't pass any arguments to info it provides daylight savings
+time information as of today.
+
+ >>> tz.info() in ((-21600, 1, 'MDT'), (-25200, 0, 'MST'))
+ True
+
diff --git a/testcline/lib/python3.12/site-packages/DateTime/pytz_support.py b/testcline/lib/python3.12/site-packages/DateTime/pytz_support.py
new file mode 100644
index 0000000..4acf324
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/DateTime/pytz_support.py
@@ -0,0 +1,269 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+from datetime import datetime
+from datetime import timedelta
+
+import pytz
+import pytz.reference
+from pytz.tzinfo import StaticTzInfo
+from pytz.tzinfo import memorized_timedelta
+
+from .interfaces import DateTimeError
+
+
+EPOCH = datetime.fromtimestamp(0, tz=pytz.utc)
+
+_numeric_timezone_data = {
+ 'GMT': ('GMT', 0, 1, [], '', [(0, 0, 0)], 'GMT\000'),
+ 'GMT+0': ('GMT+0', 0, 1, [], '', [(0, 0, 0)], 'GMT+0000\000'),
+ 'GMT+1': ('GMT+1', 0, 1, [], '', [(3600, 0, 0)], 'GMT+0100\000'),
+ 'GMT+2': ('GMT+2', 0, 1, [], '', [(7200, 0, 0)], 'GMT+0200\000'),
+ 'GMT+3': ('GMT+3', 0, 1, [], '', [(10800, 0, 0)], 'GMT+0300\000'),
+ 'GMT+4': ('GMT+4', 0, 1, [], '', [(14400, 0, 0)], 'GMT+0400\000'),
+ 'GMT+5': ('GMT+5', 0, 1, [], '', [(18000, 0, 0)], 'GMT+0500\000'),
+ 'GMT+6': ('GMT+6', 0, 1, [], '', [(21600, 0, 0)], 'GMT+0600\000'),
+ 'GMT+7': ('GMT+7', 0, 1, [], '', [(25200, 0, 0)], 'GMT+0700\000'),
+ 'GMT+8': ('GMT+8', 0, 1, [], '', [(28800, 0, 0)], 'GMT+0800\000'),
+ 'GMT+9': ('GMT+9', 0, 1, [], '', [(32400, 0, 0)], 'GMT+0900\000'),
+ 'GMT+10': ('GMT+10', 0, 1, [], '', [(36000, 0, 0)], 'GMT+1000\000'),
+ 'GMT+11': ('GMT+11', 0, 1, [], '', [(39600, 0, 0)], 'GMT+1100\000'),
+ 'GMT+12': ('GMT+12', 0, 1, [], '', [(43200, 0, 0)], 'GMT+1200\000'),
+ 'GMT+13': ('GMT+13', 0, 1, [], '', [(46800, 0, 0)], 'GMT+1300\000'),
+
+ 'GMT-1': ('GMT-1', 0, 1, [], '', [(-3600, 0, 0)], 'GMT-0100\000'),
+ 'GMT-2': ('GMT-2', 0, 1, [], '', [(-7200, 0, 0)], 'GMT-0200\000'),
+ 'GMT-3': ('GMT-3', 0, 1, [], '', [(-10800, 0, 0)], 'GMT-0300\000'),
+ 'GMT-4': ('GMT-4', 0, 1, [], '', [(-14400, 0, 0)], 'GMT-0400\000'),
+ 'GMT-5': ('GMT-5', 0, 1, [], '', [(-18000, 0, 0)], 'GMT-0500\000'),
+ 'GMT-6': ('GMT-6', 0, 1, [], '', [(-21600, 0, 0)], 'GMT-0600\000'),
+ 'GMT-7': ('GMT-7', 0, 1, [], '', [(-25200, 0, 0)], 'GMT-0700\000'),
+ 'GMT-8': ('GMT-8', 0, 1, [], '', [(-28800, 0, 0)], 'GMT-0800\000'),
+ 'GMT-9': ('GMT-9', 0, 1, [], '', [(-32400, 0, 0)], 'GMT-0900\000'),
+ 'GMT-10': ('GMT-10', 0, 1, [], '', [(-36000, 0, 0)], 'GMT-1000\000'),
+ 'GMT-11': ('GMT-11', 0, 1, [], '', [(-39600, 0, 0)], 'GMT-1100\000'),
+ 'GMT-12': ('GMT-12', 0, 1, [], '', [(-43200, 0, 0)], 'GMT-1200\000'),
+
+ 'GMT+0130': ('GMT+0130', 0, 1, [], '', [(5400, 0, 0)], 'GMT+0130\000'),
+ 'GMT+0230': ('GMT+0230', 0, 1, [], '', [(9000, 0, 0)], 'GMT+0230\000'),
+ 'GMT+0330': ('GMT+0330', 0, 1, [], '', [(12600, 0, 0)], 'GMT+0330\000'),
+ 'GMT+0430': ('GMT+0430', 0, 1, [], '', [(16200, 0, 0)], 'GMT+0430\000'),
+ 'GMT+0530': ('GMT+0530', 0, 1, [], '', [(19800, 0, 0)], 'GMT+0530\000'),
+ 'GMT+0630': ('GMT+0630', 0, 1, [], '', [(23400, 0, 0)], 'GMT+0630\000'),
+ 'GMT+0730': ('GMT+0730', 0, 1, [], '', [(27000, 0, 0)], 'GMT+0730\000'),
+ 'GMT+0830': ('GMT+0830', 0, 1, [], '', [(30600, 0, 0)], 'GMT+0830\000'),
+ 'GMT+0930': ('GMT+0930', 0, 1, [], '', [(34200, 0, 0)], 'GMT+0930\000'),
+ 'GMT+1030': ('GMT+1030', 0, 1, [], '', [(37800, 0, 0)], 'GMT+1030\000'),
+ 'GMT+1130': ('GMT+1130', 0, 1, [], '', [(41400, 0, 0)], 'GMT+1130\000'),
+ 'GMT+1230': ('GMT+1230', 0, 1, [], '', [(45000, 0, 0)], 'GMT+1230\000'),
+
+ 'GMT-0130': ('GMT-0130', 0, 1, [], '', [(-5400, 0, 0)], 'GMT-0130\000'),
+ 'GMT-0230': ('GMT-0230', 0, 1, [], '', [(-9000, 0, 0)], 'GMT-0230\000'),
+ 'GMT-0330': ('GMT-0330', 0, 1, [], '', [(-12600, 0, 0)], 'GMT-0330\000'),
+ 'GMT-0430': ('GMT-0430', 0, 1, [], '', [(-16200, 0, 0)], 'GMT-0430\000'),
+ 'GMT-0530': ('GMT-0530', 0, 1, [], '', [(-19800, 0, 0)], 'GMT-0530\000'),
+ 'GMT-0630': ('GMT-0630', 0, 1, [], '', [(-23400, 0, 0)], 'GMT-0630\000'),
+ 'GMT-0730': ('GMT-0730', 0, 1, [], '', [(-27000, 0, 0)], 'GMT-0730\000'),
+ 'GMT-0830': ('GMT-0830', 0, 1, [], '', [(-30600, 0, 0)], 'GMT-0830\000'),
+ 'GMT-0930': ('GMT-0930', 0, 1, [], '', [(-34200, 0, 0)], 'GMT-0930\000'),
+ 'GMT-1030': ('GMT-1030', 0, 1, [], '', [(-37800, 0, 0)], 'GMT-1030\000'),
+ 'GMT-1130': ('GMT-1130', 0, 1, [], '', [(-41400, 0, 0)], 'GMT-1130\000'),
+ 'GMT-1230': ('GMT-1230', 0, 1, [], '', [(-45000, 0, 0)], 'GMT-1230\000'),
+}
+
+# These are the timezones not in pytz.common_timezones
+_old_zlst = [
+ 'AST', 'AT', 'BST', 'BT', 'CCT',
+ 'CET', 'CST', 'Cuba', 'EADT', 'EAST',
+ 'EEST', 'EET', 'EST', 'Egypt', 'FST',
+ 'FWT', 'GB-Eire', 'GMT+0100', 'GMT+0130', 'GMT+0200',
+ 'GMT+0230', 'GMT+0300', 'GMT+0330', 'GMT+0400', 'GMT+0430',
+ 'GMT+0500', 'GMT+0530', 'GMT+0600', 'GMT+0630', 'GMT+0700',
+ 'GMT+0730', 'GMT+0800', 'GMT+0830', 'GMT+0900', 'GMT+0930',
+ 'GMT+1', 'GMT+1000', 'GMT+1030', 'GMT+1100', 'GMT+1130',
+ 'GMT+1200', 'GMT+1230', 'GMT+1300', 'GMT-0100', 'GMT-0130',
+ 'GMT-0200', 'GMT-0300', 'GMT-0400', 'GMT-0500', 'GMT-0600',
+ 'GMT-0630', 'GMT-0700', 'GMT-0730', 'GMT-0800', 'GMT-0830',
+ 'GMT-0900', 'GMT-0930', 'GMT-1000', 'GMT-1030', 'GMT-1100',
+ 'GMT-1130', 'GMT-1200', 'GMT-1230', 'GST', 'Greenwich',
+ 'Hongkong', 'IDLE', 'IDLW', 'Iceland', 'Iran',
+ 'Israel', 'JST', 'Jamaica', 'Japan', 'MEST',
+ 'MET', 'MEWT', 'MST', 'NT', 'NZDT',
+ 'NZST', 'NZT', 'PST', 'Poland', 'SST',
+ 'SWT', 'Singapore', 'Turkey', 'UCT', 'UT',
+ 'Universal', 'WADT', 'WAST', 'WAT', 'WET',
+ 'ZP4', 'ZP5', 'ZP6',
+]
+
+_old_zmap = {
+ 'aest': 'GMT+10', 'aedt': 'GMT+11',
+ 'aus eastern standard time': 'GMT+10',
+ 'sydney standard time': 'GMT+10',
+ 'tasmania standard time': 'GMT+10',
+ 'e. australia standard time': 'GMT+10',
+ 'aus central standard time': 'GMT+0930',
+ 'cen. australia standard time': 'GMT+0930',
+ 'w. australia standard time': 'GMT+8',
+
+ 'central europe standard time': 'GMT+1',
+ 'eastern standard time': 'US/Eastern',
+ 'us eastern standard time': 'US/Eastern',
+ 'central standard time': 'US/Central',
+ 'mountain standard time': 'US/Mountain',
+ 'pacific standard time': 'US/Pacific',
+ 'mst': 'US/Mountain', 'pst': 'US/Pacific',
+ 'cst': 'US/Central', 'est': 'US/Eastern',
+
+ 'gmt+0000': 'GMT+0', 'gmt+0': 'GMT+0',
+
+ 'gmt+0100': 'GMT+1', 'gmt+0200': 'GMT+2', 'gmt+0300': 'GMT+3',
+ 'gmt+0400': 'GMT+4', 'gmt+0500': 'GMT+5', 'gmt+0600': 'GMT+6',
+ 'gmt+0700': 'GMT+7', 'gmt+0800': 'GMT+8', 'gmt+0900': 'GMT+9',
+ 'gmt+1000': 'GMT+10', 'gmt+1100': 'GMT+11', 'gmt+1200': 'GMT+12',
+ 'gmt+1300': 'GMT+13',
+ 'gmt-0100': 'GMT-1', 'gmt-0200': 'GMT-2', 'gmt-0300': 'GMT-3',
+ 'gmt-0400': 'GMT-4', 'gmt-0500': 'GMT-5', 'gmt-0600': 'GMT-6',
+ 'gmt-0700': 'GMT-7', 'gmt-0800': 'GMT-8', 'gmt-0900': 'GMT-9',
+ 'gmt-1000': 'GMT-10', 'gmt-1100': 'GMT-11', 'gmt-1200': 'GMT-12',
+
+ 'gmt+1': 'GMT+1', 'gmt+2': 'GMT+2', 'gmt+3': 'GMT+3',
+ 'gmt+4': 'GMT+4', 'gmt+5': 'GMT+5', 'gmt+6': 'GMT+6',
+ 'gmt+7': 'GMT+7', 'gmt+8': 'GMT+8', 'gmt+9': 'GMT+9',
+ 'gmt+10': 'GMT+10', 'gmt+11': 'GMT+11', 'gmt+12': 'GMT+12',
+ 'gmt+13': 'GMT+13',
+ 'gmt-1': 'GMT-1', 'gmt-2': 'GMT-2', 'gmt-3': 'GMT-3',
+ 'gmt-4': 'GMT-4', 'gmt-5': 'GMT-5', 'gmt-6': 'GMT-6',
+ 'gmt-7': 'GMT-7', 'gmt-8': 'GMT-8', 'gmt-9': 'GMT-9',
+ 'gmt-10': 'GMT-10', 'gmt-11': 'GMT-11', 'gmt-12': 'GMT-12',
+
+ 'gmt+130': 'GMT+0130', 'gmt+0130': 'GMT+0130',
+ 'gmt+230': 'GMT+0230', 'gmt+0230': 'GMT+0230',
+ 'gmt+330': 'GMT+0330', 'gmt+0330': 'GMT+0330',
+ 'gmt+430': 'GMT+0430', 'gmt+0430': 'GMT+0430',
+ 'gmt+530': 'GMT+0530', 'gmt+0530': 'GMT+0530',
+ 'gmt+630': 'GMT+0630', 'gmt+0630': 'GMT+0630',
+ 'gmt+730': 'GMT+0730', 'gmt+0730': 'GMT+0730',
+ 'gmt+830': 'GMT+0830', 'gmt+0830': 'GMT+0830',
+ 'gmt+930': 'GMT+0930', 'gmt+0930': 'GMT+0930',
+ 'gmt+1030': 'GMT+1030',
+ 'gmt+1130': 'GMT+1130',
+ 'gmt+1230': 'GMT+1230',
+
+ 'gmt-130': 'GMT-0130', 'gmt-0130': 'GMT-0130',
+ 'gmt-230': 'GMT-0230', 'gmt-0230': 'GMT-0230',
+ 'gmt-330': 'GMT-0330', 'gmt-0330': 'GMT-0330',
+ 'gmt-430': 'GMT-0430', 'gmt-0430': 'GMT-0430',
+ 'gmt-530': 'GMT-0530', 'gmt-0530': 'GMT-0530',
+ 'gmt-630': 'GMT-0630', 'gmt-0630': 'GMT-0630',
+ 'gmt-730': 'GMT-0730', 'gmt-0730': 'GMT-0730',
+ 'gmt-830': 'GMT-0830', 'gmt-0830': 'GMT-0830',
+ 'gmt-930': 'GMT-0930', 'gmt-0930': 'GMT-0930',
+ 'gmt-1030': 'GMT-1030',
+ 'gmt-1130': 'GMT-1130',
+ 'gmt-1230': 'GMT-1230',
+
+ 'ut': 'Universal',
+ 'bst': 'GMT+1', 'mest': 'GMT+2', 'sst': 'GMT+2',
+ 'fst': 'GMT+2', 'wadt': 'GMT+8', 'eadt': 'GMT+11', 'nzdt': 'GMT+13',
+ 'wet': 'GMT', 'wat': 'GMT+1', 'at': 'GMT-2', 'ast': 'GMT-4',
+ 'nt': 'GMT-11', 'idlw': 'GMT-12', 'cet': 'GMT+1', 'cest': 'GMT+2',
+ 'met': 'GMT+1',
+ 'mewt': 'GMT+1', 'swt': 'GMT+1', 'fwt': 'GMT+1', 'eet': 'GMT+2',
+ 'eest': 'GMT+3',
+ 'bt': 'GMT+3', 'zp4': 'GMT+4', 'zp5': 'GMT+5', 'zp6': 'GMT+6',
+ 'wast': 'GMT+7', 'cct': 'GMT+8', 'jst': 'GMT+9', 'east': 'GMT+10',
+ 'gst': 'GMT+10', 'nzt': 'GMT+12', 'nzst': 'GMT+12', 'idle': 'GMT+12',
+ 'ret': 'GMT+4', 'ist': 'GMT+0530', 'edt': 'GMT-4',
+
+}
+
+
+# some timezone definitions of the "-0400" are not working
+# when upgrading
+for hour in range(0, 13):
+ hour = hour
+ fhour = str(hour)
+ if len(fhour) == 1:
+ fhour = '0' + fhour
+ _old_zmap['-%s00' % fhour] = 'GMT-%i' % hour
+ _old_zmap['+%s00' % fhour] = 'GMT+%i' % hour
+
+
+def _p(zone):
+ return _numeric_timezones[zone]
+
+
+def _static_timezone_factory(data):
+ zone = data[0]
+ cls = type(zone, (StaticTzInfo,), dict(
+ __reduce__=lambda _: (_p, (zone, )),
+ zone=zone,
+ _utcoffset=memorized_timedelta(data[5][0][0]),
+ _tzname=data[6][:-1])) # strip the trailing null
+ return cls()
+
+
+_numeric_timezones = {key: _static_timezone_factory(data)
+ for key, data in _numeric_timezone_data.items()}
+
+
+class Timezone:
+ """
+ Timezone information returned by PytzCache.__getitem__
+ Adapts datetime.tzinfo object to DateTime._timezone interface
+ """
+
+ def __init__(self, tzinfo):
+ self.tzinfo = tzinfo
+
+ def info(self, t=None):
+ if t is None:
+ dt = datetime.now(tz=pytz.utc)
+ else:
+ # can't use utcfromtimestamp past 2038
+ dt = EPOCH + timedelta(0, t)
+
+ # need to normalize tzinfo for the datetime to deal with
+ # daylight savings time.
+ normalized_dt = self.tzinfo.normalize(dt.astimezone(self.tzinfo))
+ normalized_tzinfo = normalized_dt.tzinfo
+
+ offset = normalized_tzinfo.utcoffset(normalized_dt)
+ secs = offset.days * 24 * 60 * 60 + offset.seconds
+ dst = normalized_tzinfo.dst(normalized_dt)
+ if dst == timedelta(0):
+ is_dst = 0
+ else:
+ is_dst = 1
+ return secs, is_dst, normalized_tzinfo.tzname(normalized_dt)
+
+
+class PytzCache:
+ """
+ Reimplementation of the DateTime._cache class that uses for timezone info
+ """
+
+ _zlst = pytz.common_timezones + _old_zlst # used by DateTime.TimeZones
+ _zmap = {name.lower(): name for name in pytz.all_timezones}
+ _zmap.update(_old_zmap) # These must take priority
+ _zidx = _zmap.keys()
+
+ def __getitem__(self, key):
+ name = self._zmap.get(key.lower(), key) # fallback to key
+ try:
+ return Timezone(pytz.timezone(name))
+ except pytz.UnknownTimeZoneError:
+ try:
+ return Timezone(_numeric_timezones[name])
+ except KeyError:
+ raise DateTimeError('Unrecognized timezone: %s' % key)
diff --git a/testcline/lib/python3.12/site-packages/DateTime/tests/__init__.py b/testcline/lib/python3.12/site-packages/DateTime/tests/__init__.py
new file mode 100644
index 0000000..e67bcb6
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/DateTime/tests/__init__.py
@@ -0,0 +1,15 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+# This file is needed to make this a package.
diff --git a/testcline/lib/python3.12/site-packages/DateTime/tests/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/DateTime/tests/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..5026122
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/DateTime/tests/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/DateTime/tests/__pycache__/test_datetime.cpython-312.pyc b/testcline/lib/python3.12/site-packages/DateTime/tests/__pycache__/test_datetime.cpython-312.pyc
new file mode 100644
index 0000000..6c8011e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/DateTime/tests/__pycache__/test_datetime.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/DateTime/tests/julian_testdata.txt b/testcline/lib/python3.12/site-packages/DateTime/tests/julian_testdata.txt
new file mode 100644
index 0000000..386c3da
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/DateTime/tests/julian_testdata.txt
@@ -0,0 +1,57 @@
+1970-01-01 (1970, 1, 4)
+1970-01-02 (1970, 1, 5)
+1970-01-30 (1970, 5, 5)
+1970-01-31 (1970, 5, 6)
+1970-02-01 (1970, 5, 7)
+1970-02-02 (1970, 6, 1)
+1970-02-28 (1970, 9, 6)
+1970-03-01 (1970, 9, 7)
+1970-03-30 (1970, 14, 1)
+1970-03-31 (1970, 14, 2)
+1970-04-01 (1970, 14, 3)
+1970-09-30 (1970, 40, 3)
+1970-10-01 (1970, 40, 4)
+1970-10-02 (1970, 40, 5)
+1970-10-03 (1970, 40, 6)
+1970-10-04 (1970, 40, 7)
+1970-10-05 (1970, 41, 1)
+1971-01-02 (1970, 53, 6)
+1971-01-03 (1970, 53, 7)
+1971-01-04 (1971, 1, 1)
+1971-01-05 (1971, 1, 2)
+1971-12-31 (1971, 52, 5)
+1972-01-01 (1971, 52, 6)
+1972-01-02 (1971, 52, 7)
+1972-01-03 (1972, 1, 1)
+1972-01-04 (1972, 1, 2)
+1972-12-30 (1972, 52, 6)
+1972-12-31 (1972, 52, 7)
+1973-01-01 (1973, 1, 1)
+1973-01-02 (1973, 1, 2)
+1973-12-29 (1973, 52, 6)
+1973-12-30 (1973, 52, 7)
+1973-12-31 (1974, 1, 1)
+1974-01-01 (1974, 1, 2)
+1998-12-30 (1998, 53, 3)
+1998-12-31 (1998, 53, 4)
+1999-01-01 (1998, 53, 5)
+1999-01-02 (1998, 53, 6)
+1999-01-03 (1998, 53, 7)
+1999-01-04 (1999, 1, 1)
+1999-01-05 (1999, 1, 2)
+1999-12-30 (1999, 52, 4)
+1999-12-31 (1999, 52, 5)
+2000-01-01 (1999, 52, 6)
+2000-01-02 (1999, 52, 7)
+2000-01-03 (2000, 1, 1)
+2000-01-04 (2000, 1, 2)
+2000-01-05 (2000, 1, 3)
+2000-01-06 (2000, 1, 4)
+2000-01-07 (2000, 1, 5)
+2000-01-08 (2000, 1, 6)
+2000-01-09 (2000, 1, 7)
+2000-01-10 (2000, 2, 1)
+2019-12-28 (2019, 52, 6)
+2019-12-29 (2019, 52, 7)
+2019-12-30 (2020, 1, 1)
+2019-12-31 (2020, 1, 2)
diff --git a/testcline/lib/python3.12/site-packages/DateTime/tests/test_datetime.py b/testcline/lib/python3.12/site-packages/DateTime/tests/test_datetime.py
new file mode 100644
index 0000000..f4c2644
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/DateTime/tests/test_datetime.py
@@ -0,0 +1,764 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import math
+import os
+import pickle
+import platform
+import sys
+import time
+import unittest
+from datetime import date
+from datetime import datetime
+from datetime import timedelta
+from datetime import tzinfo
+
+import pytz
+
+from DateTime import DateTime
+from DateTime.DateTime import _findLocalTimeZoneName
+
+
+try:
+ __file__
+except NameError: # pragma: no cover
+ f = sys.argv[0]
+else:
+ f = __file__
+
+IS_PYPY = getattr(platform, 'python_implementation', lambda: None)() == 'PyPy'
+
+DATADIR = os.path.dirname(os.path.abspath(f))
+del f
+
+ZERO = timedelta(0)
+
+
+class FixedOffset(tzinfo):
+ """Fixed offset in minutes east from UTC."""
+
+ def __init__(self, offset, name):
+ self.__offset = timedelta(minutes=offset)
+ self.__name = name
+
+ def utcoffset(self, dt):
+ return self.__offset
+
+ def tzname(self, dt):
+ return self.__name
+
+ def dst(self, dt):
+ return ZERO
+
+
+class DateTimeTests(unittest.TestCase):
+
+ def _compare(self, dt1, dt2):
+ '''Compares the internal representation of dt1 with
+ the representation in dt2. Allows sub-millisecond variations.
+ Primarily for testing.'''
+ self.assertEqual(round(dt1._t, 3), round(dt2._t, 3))
+ self.assertEqual(round(dt1._d, 9), round(dt2._d, 9))
+ self.assertEqual(round(dt1.time, 9), round(dt2.time, 9))
+ self.assertEqual(dt1.millis(), dt2.millis())
+ self.assertEqual(dt1._micros, dt2._micros)
+
+ def testBug1203(self):
+ # 01:59:60 occurred in old DateTime
+ dt = DateTime(7200, 'GMT')
+ self.assertTrue(str(dt).find('60') < 0, dt)
+
+ def testDSTInEffect(self):
+ # Checks GMT offset for a DST date in the US/Eastern time zone
+ dt = DateTime(2000, 5, 9, 15, 0, 0, 'US/Eastern')
+ self.assertEqual(dt.toZone('GMT').hour(), 19,
+ (dt, dt.toZone('GMT')))
+
+ def testDSTNotInEffect(self):
+ # Checks GMT offset for a non-DST date in the US/Eastern time zone
+ dt = DateTime(2000, 11, 9, 15, 0, 0, 'US/Eastern')
+ self.assertEqual(dt.toZone('GMT').hour(), 20,
+ (dt, dt.toZone('GMT')))
+
+ def testAddPrecision(self):
+ # Precision of serial additions
+ dt = DateTime()
+ self.assertEqual(str(dt + 0.10 + 3.14 + 6.76 - 10), str(dt),
+ dt)
+ # checks problem reported in
+ # https://github.com/zopefoundation/DateTime/issues/41
+ dt = DateTime(2038, 10, 7, 8, 52, 44.959840, "UTC")
+ self.assertEqual(str(dt + 0.10 + 3.14 + 6.76 - 10), str(dt),
+ dt)
+
+ def testConsistentSecondMicroRounding(self):
+ dt = DateTime(2038, 10, 7, 8, 52, 44.9598398, "UTC")
+ self.assertEqual(int(dt.second() * 1000000),
+ dt.micros() % 60000000)
+
+ def testConstructor3(self):
+ # Constructor from date/time string
+ dt = DateTime()
+ dt1s = '%d/%d/%d %d:%d:%f %s' % (
+ dt.year(),
+ dt.month(),
+ dt.day(),
+ dt.hour(),
+ dt.minute(),
+ dt.second(),
+ dt.timezone())
+ dt1 = DateTime(dt1s)
+ # Compare representations as it's the
+ # only way to compare the dates to the same accuracy
+ self.assertEqual(repr(dt), repr(dt1))
+
+ def testConstructor4(self):
+ # Constructor from time float
+ dt = DateTime()
+ dt1 = DateTime(float(dt))
+ self._compare(dt, dt1)
+
+ def testConstructor5(self):
+ # Constructor from time float and timezone
+ dt = DateTime()
+ dt1 = DateTime(float(dt), dt.timezone())
+ self.assertEqual(str(dt), str(dt1), (dt, dt1))
+ dt1 = DateTime(float(dt), str(dt.timezone()))
+ self.assertEqual(str(dt), str(dt1), (dt, dt1))
+
+ def testConstructor6(self):
+ # Constructor from year and julian date
+ # This test must normalize the time zone, or it *will* break when
+ # DST changes!
+ dt1 = DateTime(2000, 5.500000578705)
+ dt = DateTime('2000/1/5 12:00:00.050 pm %s' % dt1.localZone())
+ self._compare(dt, dt1)
+
+ def testConstructor7(self):
+ # Constructor from parts
+ dt = DateTime()
+ dt1 = DateTime(
+ dt.year(),
+ dt.month(),
+ dt.day(),
+ dt.hour(),
+ dt.minute(),
+ dt.second(),
+ dt.timezone())
+ # Compare representations as it's the
+ # only way to compare the dates to the same accuracy
+ self.assertEqual(repr(dt), repr(dt1))
+
+ def testDayOfWeek(self):
+ # Compare to the datetime.date value to make it locale independent
+ expected = date(2000, 6, 16).strftime('%A')
+ # strftime() used to always be passed a day of week of 0
+ dt = DateTime('2000/6/16')
+ s = dt.strftime('%A')
+ self.assertEqual(s, expected, (dt, s))
+
+ def testOldDate(self):
+ # Fails when an 1800 date is displayed with negative signs
+ dt = DateTime('1830/5/6 12:31:46.213 pm')
+ dt1 = dt.toZone('GMT+6')
+ self.assertTrue(str(dt1).find('-') < 0, (dt, dt1))
+
+ def testSubtraction(self):
+ # Reconstruction of a DateTime from its parts, with subtraction
+ # this also tests the accuracy of addition and reconstruction
+ dt = DateTime()
+ dt1 = dt - 3.141592653
+ dt2 = DateTime(
+ dt.year(),
+ dt.month(),
+ dt.day(),
+ dt.hour(),
+ dt.minute(),
+ dt.second())
+ dt3 = dt2 - 3.141592653
+ self.assertEqual(dt1, dt3, (dt, dt1, dt2, dt3))
+
+ def testTZ1add(self):
+ # Time zone manipulation: add to a date
+ dt = DateTime('1997/3/8 1:45am GMT-4')
+ dt1 = DateTime('1997/3/9 1:45pm GMT+8')
+ self.assertTrue((dt + 1.0).equalTo(dt1))
+
+ def testTZ1sub(self):
+ # Time zone manipulation: subtract from a date
+ dt = DateTime('1997/3/8 1:45am GMT-4')
+ dt1 = DateTime('1997/3/9 1:45pm GMT+8')
+ self.assertTrue((dt1 - 1.0).equalTo(dt))
+
+ def testTZ1diff(self):
+ # Time zone manipulation: diff two dates
+ dt = DateTime('1997/3/8 1:45am GMT-4')
+ dt1 = DateTime('1997/3/9 1:45pm GMT+8')
+ self.assertEqual(dt1 - dt, 1.0, (dt, dt1))
+
+ def test_compare_methods(self):
+ # Compare two dates using several methods
+ dt = DateTime('1997/1/1')
+ dt1 = DateTime('1997/2/2')
+ self.assertTrue(dt1.greaterThan(dt))
+ self.assertTrue(dt1.greaterThanEqualTo(dt))
+ self.assertTrue(dt.lessThan(dt1))
+ self.assertTrue(dt.lessThanEqualTo(dt1))
+ self.assertTrue(dt.notEqualTo(dt1))
+ self.assertFalse(dt.equalTo(dt1))
+ # Compare a date to float
+ dt = DateTime(1.0)
+ self.assertTrue(dt == DateTime(1.0)) # testing __eq__
+ self.assertFalse(dt != DateTime(1.0)) # testing __ne__
+ self.assertFalse(dt.greaterThan(1.0))
+ self.assertTrue(dt.greaterThanEqualTo(1.0))
+ self.assertFalse(dt.lessThan(1.0))
+ self.assertTrue(dt.lessThanEqualTo(1.0))
+ self.assertFalse(dt.notEqualTo(1.0))
+ self.assertTrue(dt.equalTo(1.0))
+ # Compare a date to int
+ dt = DateTime(1)
+ self.assertEqual(dt, DateTime(1.0))
+ self.assertTrue(dt == DateTime(1)) # testing __eq__
+ self.assertFalse(dt != DateTime(1)) # testing __ne__
+ self.assertFalse(dt.greaterThan(1))
+ self.assertTrue(dt.greaterThanEqualTo(1))
+ self.assertFalse(dt.lessThan(1))
+ self.assertTrue(dt.lessThanEqualTo(1))
+ self.assertFalse(dt.notEqualTo(1))
+ self.assertTrue(dt.equalTo(1))
+ # Compare a date to string; there is no implicit type conversion
+ # but behavior if consistent as when comparing, for example, an int
+ # and a string.
+ dt = DateTime("2023")
+ self.assertFalse(dt == "2023") # testing __eq__
+ self.assertTrue(dt != "2023") # testing __ne__
+ self.assertRaises(TypeError, dt.greaterThan, "2023")
+ self.assertRaises(TypeError, dt.greaterThanEqualTo, "2023")
+ self.assertRaises(TypeError, dt.lessThan, "2023")
+ self.assertRaises(TypeError, dt.lessThanEqualTo, "2023")
+ self.assertTrue(dt.notEqualTo("2023"))
+ self.assertFalse(dt.equalTo("2023"))
+
+ def test_compare_methods_none(self):
+ # Compare a date to None
+ for dt in (DateTime('1997/1/1'), DateTime(0)):
+ self.assertTrue(dt.greaterThan(None))
+ self.assertTrue(dt.greaterThanEqualTo(None))
+ self.assertFalse(dt.lessThan(None))
+ self.assertFalse(dt.lessThanEqualTo(None))
+ self.assertTrue(dt.notEqualTo(None))
+ self.assertFalse(dt.equalTo(None))
+
+ def test_pickle(self):
+ dt = DateTime()
+ data = pickle.dumps(dt, 1)
+ new = pickle.loads(data)
+ for key in DateTime.__slots__:
+ self.assertEqual(getattr(dt, key), getattr(new, key))
+
+ def test_pickle_with_tz(self):
+ dt = DateTime('2002/5/2 8:00am GMT+8')
+ data = pickle.dumps(dt, 1)
+ new = pickle.loads(data)
+ for key in DateTime.__slots__:
+ self.assertEqual(getattr(dt, key), getattr(new, key))
+
+ def test_pickle_asdatetime_with_tz(self):
+ dt = DateTime('2002/5/2 8:00am GMT+8')
+ data = pickle.dumps(dt.asdatetime(), 1)
+ new = DateTime(pickle.loads(data))
+ for key in DateTime.__slots__:
+ self.assertEqual(getattr(dt, key), getattr(new, key))
+
+ def test_pickle_with_numerical_tz(self):
+ for dt_str in ('2007/01/02 12:34:56.789 +0300',
+ '2007/01/02 12:34:56.789 +0430',
+ '2007/01/02 12:34:56.789 -1234'):
+ dt = DateTime(dt_str)
+ data = pickle.dumps(dt, 1)
+ new = pickle.loads(data)
+ for key in DateTime.__slots__:
+ self.assertEqual(getattr(dt, key), getattr(new, key))
+
+ def test_pickle_with_micros(self):
+ dt = DateTime('2002/5/2 8:00:14.123 GMT+8')
+ data = pickle.dumps(dt, 1)
+ new = pickle.loads(data)
+ for key in DateTime.__slots__:
+ self.assertEqual(getattr(dt, key), getattr(new, key))
+
+ def test_pickle_old(self):
+ dt = DateTime('2002/5/2 8:00am GMT+0')
+ data = (
+ '(cDateTime.DateTime\nDateTime\nq\x01Noq\x02}q\x03(U\x05'
+ '_amonq\x04U\x03Mayq\x05U\x05_adayq\x06U\x03Thuq\x07U\x05_pmonq'
+ '\x08h\x05U\x05_hourq\tK\x08U\x05_fmonq\nh\x05U\x05_pdayq\x0bU'
+ '\x04Thu.q\x0cU\x05_fdayq\rU\x08Thursdayq\x0eU\x03_pmq\x0fU\x02amq'
+ '\x10U\x02_tq\x11GA\xcehy\x00\x00\x00\x00U\x07_minuteq\x12K\x00U'
+ '\x07_microsq\x13L1020326400000000L\nU\x02_dq\x14G@\xe2\x12j\xaa'
+ '\xaa\xaa\xabU\x07_secondq\x15G\x00\x00\x00\x00\x00\x00\x00\x00U'
+ '\x03_tzq\x16U\x05GMT+0q\x17U\x06_monthq\x18K\x05U'
+ '\x0f_timezone_naiveq\x19I00\nU\x04_dayq\x1aK\x02U\x05_yearq'
+ '\x1bM\xd2\x07U\x08_nearsecq\x1cG\x00\x00\x00\x00\x00\x00\x00'
+ '\x00U\x07_pmhourq\x1dK\x08U\n_dayoffsetq\x1eK\x04U\x04timeq'
+ '\x1fG?\xd5UUUV\x00\x00ub.')
+ data = data.encode('latin-1')
+ new = pickle.loads(data)
+ for key in DateTime.__slots__:
+ self.assertEqual(getattr(dt, key), getattr(new, key))
+
+ def test_pickle_old_without_micros(self):
+ dt = DateTime('2002/5/2 8:00am GMT+0')
+ data = (
+ '(cDateTime.DateTime\nDateTime\nq\x01Noq\x02}q\x03(U\x05'
+ '_amonq\x04U\x03Mayq\x05U\x05_adayq\x06U\x03Thuq\x07U\x05_pmonq'
+ '\x08h\x05U\x05_hourq\tK\x08U\x05_fmonq\nh\x05U\x05_pdayq\x0bU'
+ '\x04Thu.q\x0cU\x05_fdayq\rU\x08Thursdayq\x0eU\x03_pmq\x0fU'
+ '\x02amq\x10U\x02_tq\x11GA\xcehy\x00\x00\x00\x00U\x07_minuteq'
+ '\x12K\x00U\x02_dq\x13G@\xe2\x12j\xaa\xaa\xaa\xabU\x07_secondq'
+ '\x14G\x00\x00\x00\x00\x00\x00\x00\x00U\x03_tzq\x15U\x05GMT+0q'
+ '\x16U\x06_monthq\x17K\x05U\x0f_timezone_naiveq\x18I00\nU'
+ '\x04_dayq\x19K\x02U\x05_yearq\x1aM\xd2\x07U\x08_nearsecq'
+ '\x1bG\x00\x00\x00\x00\x00\x00\x00\x00U\x07_pmhourq\x1cK\x08U'
+ '\n_dayoffsetq\x1dK\x04U\x04timeq\x1eG?\xd5UUUV\x00\x00ub.')
+ data = data.encode('latin-1')
+ new = pickle.loads(data)
+ for key in DateTime.__slots__:
+ self.assertEqual(getattr(dt, key), getattr(new, key))
+
+ def test_pickle_dates_after_2038(self):
+ dt = DateTime('2039/09/02 07:07:6.235027 GMT+1')
+ data = pickle.dumps(dt, 1)
+ new = pickle.loads(data)
+ for key in DateTime.__slots__:
+ self.assertEqual(getattr(dt, key), getattr(new, key))
+
+ def test_pickle_old_with_micros_as_float(self):
+ dt = DateTime('2002/5/2 8:00am GMT+0')
+ data = (
+ 'ccopy_reg\n_reconstructor\nq\x00(cDateTime.DateTime\nDateTime'
+ '\nq\x01c__builtin__\nobject\nq\x02Ntq\x03Rq\x04(GA\xcehy\x00\x00'
+ '\x00\x00I00\nX\x05\x00\x00\x00GMT+0q\x05tq\x06b.')
+ data = data.encode('latin-1')
+ new = pickle.loads(data)
+ for key in DateTime.__slots__:
+ self.assertEqual(getattr(dt, key), getattr(new, key))
+
+ def testTZ2(self):
+ # Time zone manipulation test 2
+ dt = DateTime()
+ dt1 = dt.toZone('GMT')
+ s = dt.second()
+ s1 = dt1.second()
+ self.assertEqual(s, s1, (dt, dt1, s, s1))
+
+ def testTZDiffDaylight(self):
+ # Diff dates across daylight savings dates
+ dt = DateTime('2000/6/8 1:45am US/Eastern')
+ dt1 = DateTime('2000/12/8 12:45am US/Eastern')
+ self.assertEqual(dt1 - dt, 183, (dt, dt1, dt1 - dt))
+
+ def testY10KDate(self):
+ # Comparison of a Y10K date and a Y2K date
+ dt = DateTime('10213/09/21')
+ dt1 = DateTime(2000, 1, 1)
+
+ dsec = (dt.millis() - dt1.millis()) / 1000.0
+ ddays = math.floor((dsec / 86400.0) + 0.5)
+
+ self.assertEqual(ddays, 3000000, ddays)
+
+ def test_tzoffset(self):
+ # Test time-zone given as an offset
+
+ # GMT
+ dt = DateTime('Tue, 10 Sep 2001 09:41:03 GMT')
+ self.assertEqual(dt.tzoffset(), 0)
+
+ # Timezone by name, a timezone that hasn't got daylightsaving.
+ dt = DateTime('Tue, 2 Mar 2001 09:41:03 GMT+3')
+ self.assertEqual(dt.tzoffset(), 10800)
+
+ # Timezone by name, has daylightsaving but is not in effect.
+ dt = DateTime('Tue, 21 Jan 2001 09:41:03 PST')
+ self.assertEqual(dt.tzoffset(), -28800)
+
+ # Timezone by name, with daylightsaving in effect
+ dt = DateTime('Tue, 24 Aug 2001 09:41:03 PST')
+ self.assertEqual(dt.tzoffset(), -25200)
+
+ # A negative numerical timezone
+ dt = DateTime('Tue, 24 Jul 2001 09:41:03 -0400')
+ self.assertEqual(dt.tzoffset(), -14400)
+
+ # A positive numerical timzone
+ dt = DateTime('Tue, 6 Dec 1966 01:41:03 +0200')
+ self.assertEqual(dt.tzoffset(), 7200)
+
+ # A negative numerical timezone with minutes.
+ dt = DateTime('Tue, 24 Jul 2001 09:41:03 -0637')
+ self.assertEqual(dt.tzoffset(), -23820)
+
+ # A positive numerical timezone with minutes.
+ dt = DateTime('Tue, 24 Jul 2001 09:41:03 +0425')
+ self.assertEqual(dt.tzoffset(), 15900)
+
+ def testISO8601(self):
+ # ISO8601 reference dates
+ ref0 = DateTime('2002/5/2 8:00am GMT')
+ ref1 = DateTime('2002/5/2 8:00am US/Eastern')
+ ref2 = DateTime('2006/11/6 10:30 GMT')
+ ref3 = DateTime('2004/06/14 14:30:15 GMT-3')
+ ref4 = DateTime('2006/01/01 GMT')
+
+ # Basic tests
+ # Though this is timezone naive and according to specification should
+ # be interpreted in the local timezone, to preserve backwards
+ # compatibility with previously expected behaviour.
+ isoDt = DateTime('2002-05-02T08:00:00')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('2002-05-02T08:00:00Z')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('2002-05-02T08:00:00+00:00')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('2002-05-02T08:00:00-04:00')
+ self.assertTrue(ref1.equalTo(isoDt))
+ isoDt = DateTime('2002-05-02 08:00:00-04:00')
+ self.assertTrue(ref1.equalTo(isoDt))
+
+ # Bug 1386: the colon in the timezone offset is optional
+ isoDt = DateTime('2002-05-02T08:00:00-0400')
+ self.assertTrue(ref1.equalTo(isoDt))
+
+ # Bug 2191: date reduced formats
+ isoDt = DateTime('2006-01-01')
+ self.assertTrue(ref4.equalTo(isoDt))
+ isoDt = DateTime('200601-01')
+ self.assertTrue(ref4.equalTo(isoDt))
+ isoDt = DateTime('20060101')
+ self.assertTrue(ref4.equalTo(isoDt))
+ isoDt = DateTime('2006-01')
+ self.assertTrue(ref4.equalTo(isoDt))
+ isoDt = DateTime('200601')
+ self.assertTrue(ref4.equalTo(isoDt))
+ isoDt = DateTime('2006')
+ self.assertTrue(ref4.equalTo(isoDt))
+
+ # Bug 2191: date/time separators are also optional
+ isoDt = DateTime('20020502T08:00:00')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('2002-05-02T080000')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('20020502T080000')
+ self.assertTrue(ref0.equalTo(isoDt))
+
+ # Bug 2191: timezones with only one digit for hour
+ isoDt = DateTime('20020502T080000+0')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('20020502 080000-4')
+ self.assertTrue(ref1.equalTo(isoDt))
+ isoDt = DateTime('20020502T080000-400')
+ self.assertTrue(ref1.equalTo(isoDt))
+ isoDt = DateTime('20020502T080000-4:00')
+ self.assertTrue(ref1.equalTo(isoDt))
+
+ # Bug 2191: optional seconds/minutes
+ isoDt = DateTime('2002-05-02T0800')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('2002-05-02T08')
+ self.assertTrue(ref0.equalTo(isoDt))
+
+ # Bug 2191: week format
+ isoDt = DateTime('2002-W18-4T0800')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('2002-W184T0800')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('2002W18-4T0800')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('2002W184T08')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('2004-W25-1T14:30:15-03:00')
+ self.assertTrue(ref3.equalTo(isoDt))
+ isoDt = DateTime('2004-W25T14:30:15-03:00')
+ self.assertTrue(ref3.equalTo(isoDt))
+
+ # Bug 2191: day of year format
+ isoDt = DateTime('2002-122T0800')
+ self.assertTrue(ref0.equalTo(isoDt))
+ isoDt = DateTime('2002122T0800')
+ self.assertTrue(ref0.equalTo(isoDt))
+
+ # Bug 2191: hours/minutes fractions
+ isoDt = DateTime('2006-11-06T10.5')
+ self.assertTrue(ref2.equalTo(isoDt))
+ isoDt = DateTime('2006-11-06T10,5')
+ self.assertTrue(ref2.equalTo(isoDt))
+ isoDt = DateTime('20040614T1430.25-3')
+ self.assertTrue(ref3.equalTo(isoDt))
+ isoDt = DateTime('2004-06-14T1430,25-3')
+ self.assertTrue(ref3.equalTo(isoDt))
+ isoDt = DateTime('2004-06-14T14:30.25-3')
+ self.assertTrue(ref3.equalTo(isoDt))
+ isoDt = DateTime('20040614T14:30,25-3')
+ self.assertTrue(ref3.equalTo(isoDt))
+
+ # ISO8601 standard format
+ iso8601_string = '2002-05-02T08:00:00-04:00'
+ iso8601DT = DateTime(iso8601_string)
+ self.assertEqual(iso8601_string, iso8601DT.ISO8601())
+
+ # ISO format with no timezone
+ isoDt = DateTime('2006-01-01 00:00:00')
+ self.assertTrue(ref4.equalTo(isoDt))
+
+ def testJulianWeek(self):
+ # Check JulianDayWeek function
+ fn = os.path.join(DATADIR, 'julian_testdata.txt')
+ with open(fn) as fd:
+ lines = fd.readlines()
+ for line in lines:
+ d = DateTime(line[:10])
+ result_from_mx = tuple(map(int, line[12:-2].split(',')))
+ self.assertEqual(result_from_mx[1], d.week())
+
+ def testCopyConstructor(self):
+ d = DateTime('2004/04/04')
+ self.assertEqual(DateTime(d), d)
+ self.assertEqual(str(DateTime(d)), str(d))
+ d2 = DateTime('1999/04/12 01:00:00')
+ self.assertEqual(DateTime(d2), d2)
+ self.assertEqual(str(DateTime(d2)), str(d2))
+
+ def testCopyConstructorPreservesTimezone(self):
+ # test for https://bugs.launchpad.net/zope2/+bug/200007
+ # This always worked in the local timezone, so we need at least
+ # two tests with different zones to be sure at least one of them
+ # is not local.
+ d = DateTime('2004/04/04')
+ self.assertEqual(DateTime(d).timezone(), d.timezone())
+ d2 = DateTime('2008/04/25 12:00:00 EST')
+ self.assertEqual(DateTime(d2).timezone(), d2.timezone())
+ self.assertEqual(str(DateTime(d2)), str(d2))
+ d3 = DateTime('2008/04/25 12:00:00 PST')
+ self.assertEqual(DateTime(d3).timezone(), d3.timezone())
+ self.assertEqual(str(DateTime(d3)), str(d3))
+
+ def testRFC822(self):
+ # rfc822 conversion
+ dt = DateTime('2002-05-02T08:00:00+00:00')
+ self.assertEqual(dt.rfc822(), 'Thu, 02 May 2002 08:00:00 +0000')
+
+ dt = DateTime('2002-05-02T08:00:00+02:00')
+ self.assertEqual(dt.rfc822(), 'Thu, 02 May 2002 08:00:00 +0200')
+
+ dt = DateTime('2002-05-02T08:00:00-02:00')
+ self.assertEqual(dt.rfc822(), 'Thu, 02 May 2002 08:00:00 -0200')
+
+ # Checking that conversion from local time is working.
+ dt = DateTime()
+ dts = dt.rfc822().split(' ')
+ times = dts[4].split(':')
+ _isDST = time.localtime(time.time())[8]
+ if _isDST:
+ offset = time.altzone
+ else:
+ offset = time.timezone
+ self.assertEqual(dts[0], dt.aDay() + ',')
+ self.assertEqual(int(dts[1]), dt.day())
+ self.assertEqual(dts[2], dt.aMonth())
+ self.assertEqual(int(dts[3]), dt.year())
+ self.assertEqual(int(times[0]), dt.h_24())
+ self.assertEqual(int(times[1]), dt.minute())
+ self.assertEqual(int(times[2]), int(dt.second()))
+ self.assertEqual(dts[5], "%+03d%02d" % divmod((-offset / 60), 60))
+
+ def testInternationalDateformat(self):
+ for year in (1990, 2001, 2020):
+ for month in (1, 12):
+ for day in (1, 12, 28, 31):
+ try:
+ d_us = DateTime("%d/%d/%d" % (year, month, day))
+ except Exception:
+ continue
+
+ d_int = DateTime("%d.%d.%d" % (day, month, year),
+ datefmt="international")
+ self.assertEqual(d_us, d_int)
+
+ d_int = DateTime("%d/%d/%d" % (day, month, year),
+ datefmt="international")
+ self.assertEqual(d_us, d_int)
+
+ def test_intl_format_hyphen(self):
+ d_jan = DateTime('2011-01-11 GMT')
+ d_nov = DateTime('2011-11-01 GMT')
+ d_us = DateTime('11-01-2011 GMT')
+ d_int = DateTime('11-01-2011 GMT', datefmt="international")
+ self.assertNotEqual(d_us, d_int)
+ self.assertEqual(d_us, d_nov)
+ self.assertEqual(d_int, d_jan)
+
+ def test_calcTimezoneName(self):
+ from DateTime.interfaces import TimeError
+ timezone_dependent_epoch = 2177452800
+ try:
+ DateTime()._calcTimezoneName(timezone_dependent_epoch, 0)
+ except TimeError:
+ self.fail('Zope Collector issue #484 (negative time bug): '
+ 'TimeError raised')
+
+ def testStrftimeTZhandling(self):
+ # strftime timezone testing
+ # This is a test for collector issue #1127
+ format = '%Y-%m-%d %H:%M %Z'
+ dt = DateTime('Wed, 19 Nov 2003 18:32:07 -0215')
+ dt_string = dt.strftime(format)
+ dt_local = dt.toZone(_findLocalTimeZoneName(0))
+ dt_localstring = dt_local.strftime(format)
+ self.assertEqual(dt_string, dt_localstring)
+
+ def testStrftimeFarDates(self):
+ # Checks strftime in dates <= 1900 or >= 2038
+ dt = DateTime('1900/01/30')
+ self.assertEqual(dt.strftime('%d/%m/%Y'), '30/01/1900')
+ dt = DateTime('2040/01/30')
+ self.assertEqual(dt.strftime('%d/%m/%Y'), '30/01/2040')
+
+ def testZoneInFarDates(self):
+ # Checks time zone in dates <= 1900 or >= 2038
+ dt1 = DateTime('2040/01/30 14:33 GMT+1')
+ dt2 = DateTime('2040/01/30 11:33 GMT-2')
+ self.assertEqual(dt1.strftime('%d/%m/%Y %H:%M'),
+ dt2.strftime('%d/%m/%Y %H:%M'))
+
+ @unittest.skipIf(
+ IS_PYPY,
+ "Using Non-Ascii characters for strftime doesn't work in PyPy"
+ "https://bitbucket.org/pypy/pypy/issues/2161/pypy3-strftime-does-not-accept-unicode" # noqa: E501 line too long
+ )
+ def testStrftimeStr(self):
+ dt = DateTime('2002-05-02T08:00:00+00:00')
+ uchar = b'\xc3\xa0'.decode('utf-8')
+ ok = dt.strftime('Le %d/%m/%Y a %Hh%M').replace('a', uchar)
+ ustr = b'Le %d/%m/%Y \xc3\xa0 %Hh%M'.decode('utf-8')
+ self.assertEqual(dt.strftime(ustr), ok)
+
+ def testTimezoneNaiveHandling(self):
+ # checks that we assign timezone naivity correctly
+ dt = DateTime('2007-10-04T08:00:00+00:00')
+ self.assertFalse(dt.timezoneNaive(),
+ 'error with naivity handling in __parse_iso8601')
+ dt = DateTime('2007-10-04T08:00:00Z')
+ self.assertFalse(dt.timezoneNaive(),
+ 'error with naivity handling in __parse_iso8601')
+ dt = DateTime('2007-10-04T08:00:00')
+ self.assertTrue(dt.timezoneNaive(),
+ 'error with naivity handling in __parse_iso8601')
+ dt = DateTime('2007/10/04 15:12:33.487618 GMT+1')
+ self.assertFalse(dt.timezoneNaive(),
+ 'error with naivity handling in _parse')
+ dt = DateTime('2007/10/04 15:12:33.487618')
+ self.assertTrue(dt.timezoneNaive(),
+ 'error with naivity handling in _parse')
+ dt = DateTime()
+ self.assertFalse(dt.timezoneNaive(),
+ 'error with naivity for current time')
+ s = '2007-10-04T08:00:00'
+ dt = DateTime(s)
+ self.assertEqual(s, dt.ISO8601())
+ s = '2007-10-04T08:00:00+00:00'
+ dt = DateTime(s)
+ self.assertEqual(s, dt.ISO8601())
+
+ def testConversions(self):
+ sdt0 = datetime.now() # this is a timezone naive datetime
+ dt0 = DateTime(sdt0)
+ self.assertTrue(dt0.timezoneNaive(), (sdt0, dt0))
+ sdt1 = datetime(2007, 10, 4, 18, 14, 42, 580, pytz.utc)
+ dt1 = DateTime(sdt1)
+ self.assertFalse(dt1.timezoneNaive(), (sdt1, dt1))
+
+ # convert back
+ sdt2 = dt0.asdatetime()
+ self.assertEqual(sdt0, sdt2)
+ sdt3 = dt1.utcdatetime() # this returns a timezone naive datetime
+ self.assertEqual(sdt1.hour, sdt3.hour)
+
+ dt4 = DateTime('2007-10-04T10:00:00+05:00')
+ sdt4 = datetime(2007, 10, 4, 5, 0)
+ self.assertEqual(dt4.utcdatetime(), sdt4)
+ self.assertEqual(dt4.asdatetime(), sdt4.replace(tzinfo=pytz.utc))
+
+ dt5 = DateTime('2007-10-23 10:00:00 US/Eastern')
+ tz = pytz.timezone('US/Eastern')
+ sdt5 = datetime(2007, 10, 23, 10, 0, tzinfo=tz)
+ dt6 = DateTime(sdt5)
+ self.assertEqual(dt5.asdatetime(), sdt5)
+ self.assertEqual(dt6.asdatetime(), sdt5)
+ self.assertEqual(dt5, dt6)
+ self.assertEqual(dt5.asdatetime().tzinfo, tz)
+ self.assertEqual(dt6.asdatetime().tzinfo, tz)
+
+ def testBasicTZ(self):
+ # psycopg2 supplies it's own tzinfo instances, with no `zone` attribute
+ tz = FixedOffset(60, 'GMT+1')
+ dt1 = datetime(2008, 8, 5, 12, 0, tzinfo=tz)
+ DT = DateTime(dt1)
+ dt2 = DT.asdatetime()
+ offset1 = dt1.tzinfo.utcoffset(dt1)
+ offset2 = dt2.tzinfo.utcoffset(dt2)
+ self.assertEqual(offset1, offset2)
+
+ def testEDTTimezone(self):
+ # should be able to parse EDT timezones: see lp:599856.
+ dt = DateTime("Mon, 28 Jun 2010 10:12:25 EDT")
+ self.assertEqual(dt.Day(), 'Monday')
+ self.assertEqual(dt.day(), 28)
+ self.assertEqual(dt.Month(), 'June')
+ self.assertEqual(dt.timezone(), 'GMT-4')
+
+ def testParseISO8601(self):
+ parsed = DateTime()._parse_iso8601('2010-10-10')
+ self.assertEqual(parsed, (2010, 10, 10, 0, 0, 0, 'GMT+0000'))
+
+ def test_interface(self):
+ from DateTime.interfaces import IDateTime
+ self.assertTrue(IDateTime.providedBy(DateTime()))
+
+ def test_security(self):
+ dt = DateTime()
+ self.assertEqual(dt.__roles__, None)
+ self.assertEqual(dt.__allow_access_to_unprotected_subobjects__, 1)
+
+ def test_format(self):
+ dt = DateTime(1968, 3, 10, 23, 45, 0, 'Europe/Vienna')
+ fmt = '%d.%m.%Y %H:%M'
+ result = dt.strftime(fmt)
+ unformatted_result = '1968/03/10 23:45:00 Europe/Vienna'
+ self.assertEqual(result, f'{dt:%d.%m.%Y %H:%M}')
+ self.assertEqual(unformatted_result, f'{dt}')
+ self.assertEqual(unformatted_result, f'{dt}')
+ self.assertEqual(result, f'{dt:{fmt}}')
+ self.assertEqual(unformatted_result, f'{dt:}')
+ self.assertEqual(unformatted_result, f'{dt}')
+
+
+def test_suite():
+ import doctest
+ return unittest.TestSuite([
+ unittest.defaultTestLoader.loadTestsFromTestCase(DateTimeTests),
+ doctest.DocFileSuite('DateTime.txt', package='DateTime'),
+ doctest.DocFileSuite('pytz.txt', package='DateTime'),
+ ])
diff --git a/testcline/lib/python3.12/site-packages/_distutils_hack/__init__.py b/testcline/lib/python3.12/site-packages/_distutils_hack/__init__.py
new file mode 100644
index 0000000..94f71b9
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/_distutils_hack/__init__.py
@@ -0,0 +1,239 @@
+# don't import any costly modules
+import os
+import sys
+
+report_url = (
+ "https://github.com/pypa/setuptools/issues/new?template=distutils-deprecation.yml"
+)
+
+
+def warn_distutils_present():
+ if 'distutils' not in sys.modules:
+ return
+ import warnings
+
+ warnings.warn(
+ "Distutils was imported before Setuptools, but importing Setuptools "
+ "also replaces the `distutils` module in `sys.modules`. This may lead "
+ "to undesirable behaviors or errors. To avoid these issues, avoid "
+ "using distutils directly, ensure that setuptools is installed in the "
+ "traditional way (e.g. not an editable install), and/or make sure "
+ "that setuptools is always imported before distutils."
+ )
+
+
+def clear_distutils():
+ if 'distutils' not in sys.modules:
+ return
+ import warnings
+
+ warnings.warn(
+ "Setuptools is replacing distutils. Support for replacing "
+ "an already imported distutils is deprecated. In the future, "
+ "this condition will fail. "
+ f"Register concerns at {report_url}"
+ )
+ mods = [
+ name
+ for name in sys.modules
+ if name == "distutils" or name.startswith("distutils.")
+ ]
+ for name in mods:
+ del sys.modules[name]
+
+
+def enabled():
+ """
+ Allow selection of distutils by environment variable.
+ """
+ which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'local')
+ if which == 'stdlib':
+ import warnings
+
+ warnings.warn(
+ "Reliance on distutils from stdlib is deprecated. Users "
+ "must rely on setuptools to provide the distutils module. "
+ "Avoid importing distutils or import setuptools first, "
+ "and avoid setting SETUPTOOLS_USE_DISTUTILS=stdlib. "
+ f"Register concerns at {report_url}"
+ )
+ return which == 'local'
+
+
+def ensure_local_distutils():
+ import importlib
+
+ clear_distutils()
+
+ # With the DistutilsMetaFinder in place,
+ # perform an import to cause distutils to be
+ # loaded from setuptools._distutils. Ref #2906.
+ with shim():
+ importlib.import_module('distutils')
+
+ # check that submodules load as expected
+ core = importlib.import_module('distutils.core')
+ assert '_distutils' in core.__file__, core.__file__
+ assert 'setuptools._distutils.log' not in sys.modules
+
+
+def do_override():
+ """
+ Ensure that the local copy of distutils is preferred over stdlib.
+
+ See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401
+ for more motivation.
+ """
+ if enabled():
+ warn_distutils_present()
+ ensure_local_distutils()
+
+
+class _TrivialRe:
+ def __init__(self, *patterns) -> None:
+ self._patterns = patterns
+
+ def match(self, string):
+ return all(pat in string for pat in self._patterns)
+
+
+class DistutilsMetaFinder:
+ def find_spec(self, fullname, path, target=None):
+ # optimization: only consider top level modules and those
+ # found in the CPython test suite.
+ if path is not None and not fullname.startswith('test.'):
+ return None
+
+ method_name = 'spec_for_{fullname}'.format(**locals())
+ method = getattr(self, method_name, lambda: None)
+ return method()
+
+ def spec_for_distutils(self):
+ if self.is_cpython():
+ return None
+
+ import importlib
+ import importlib.abc
+ import importlib.util
+
+ try:
+ mod = importlib.import_module('setuptools._distutils')
+ except Exception:
+ # There are a couple of cases where setuptools._distutils
+ # may not be present:
+ # - An older Setuptools without a local distutils is
+ # taking precedence. Ref #2957.
+ # - Path manipulation during sitecustomize removes
+ # setuptools from the path but only after the hook
+ # has been loaded. Ref #2980.
+ # In either case, fall back to stdlib behavior.
+ return None
+
+ class DistutilsLoader(importlib.abc.Loader):
+ def create_module(self, spec):
+ mod.__name__ = 'distutils'
+ return mod
+
+ def exec_module(self, module):
+ pass
+
+ return importlib.util.spec_from_loader(
+ 'distutils', DistutilsLoader(), origin=mod.__file__
+ )
+
+ @staticmethod
+ def is_cpython():
+ """
+ Suppress supplying distutils for CPython (build and tests).
+ Ref #2965 and #3007.
+ """
+ return os.path.isfile('pybuilddir.txt')
+
+ def spec_for_pip(self):
+ """
+ Ensure stdlib distutils when running under pip.
+ See pypa/pip#8761 for rationale.
+ """
+ if sys.version_info >= (3, 12) or self.pip_imported_during_build():
+ return
+ clear_distutils()
+ self.spec_for_distutils = lambda: None
+
+ @classmethod
+ def pip_imported_during_build(cls):
+ """
+ Detect if pip is being imported in a build script. Ref #2355.
+ """
+ import traceback
+
+ return any(
+ cls.frame_file_is_setup(frame) for frame, line in traceback.walk_stack(None)
+ )
+
+ @staticmethod
+ def frame_file_is_setup(frame):
+ """
+ Return True if the indicated frame suggests a setup.py file.
+ """
+ # some frames may not have __file__ (#2940)
+ return frame.f_globals.get('__file__', '').endswith('setup.py')
+
+ def spec_for_sensitive_tests(self):
+ """
+ Ensure stdlib distutils when running select tests under CPython.
+
+ python/cpython#91169
+ """
+ clear_distutils()
+ self.spec_for_distutils = lambda: None
+
+ sensitive_tests = (
+ [
+ 'test.test_distutils',
+ 'test.test_peg_generator',
+ 'test.test_importlib',
+ ]
+ if sys.version_info < (3, 10)
+ else [
+ 'test.test_distutils',
+ ]
+ )
+
+
+for name in DistutilsMetaFinder.sensitive_tests:
+ setattr(
+ DistutilsMetaFinder,
+ f'spec_for_{name}',
+ DistutilsMetaFinder.spec_for_sensitive_tests,
+ )
+
+
+DISTUTILS_FINDER = DistutilsMetaFinder()
+
+
+def add_shim():
+ DISTUTILS_FINDER in sys.meta_path or insert_shim()
+
+
+class shim:
+ def __enter__(self) -> None:
+ insert_shim()
+
+ def __exit__(self, exc: object, value: object, tb: object) -> None:
+ _remove_shim()
+
+
+def insert_shim():
+ sys.meta_path.insert(0, DISTUTILS_FINDER)
+
+
+def _remove_shim():
+ try:
+ sys.meta_path.remove(DISTUTILS_FINDER)
+ except ValueError:
+ pass
+
+
+if sys.version_info < (3, 12):
+ # DistutilsMetaFinder can only be disabled in Python < 3.12 (PEP 632)
+ remove_shim = _remove_shim
diff --git a/testcline/lib/python3.12/site-packages/_distutils_hack/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/_distutils_hack/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..494a718
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/_distutils_hack/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/_distutils_hack/__pycache__/override.cpython-312.pyc b/testcline/lib/python3.12/site-packages/_distutils_hack/__pycache__/override.cpython-312.pyc
new file mode 100644
index 0000000..a92f6e8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/_distutils_hack/__pycache__/override.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/_distutils_hack/override.py b/testcline/lib/python3.12/site-packages/_distutils_hack/override.py
new file mode 100644
index 0000000..2cc433a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/_distutils_hack/override.py
@@ -0,0 +1 @@
+__import__('_distutils_hack').do_override()
diff --git a/AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/INSTALLER
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/top_level.txt
rename to testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/INSTALLER
diff --git a/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/LICENSE
new file mode 100644
index 0000000..62b076c
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/LICENSE
@@ -0,0 +1,20 @@
+This package contains a modified version of ca-bundle.crt:
+
+ca-bundle.crt -- Bundle of CA Root Certificates
+
+This is a bundle of X.509 certificates of public Certificate Authorities
+(CA). These were automatically extracted from Mozilla's root certificates
+file (certdata.txt). This file can be found in the mozilla source tree:
+https://hg.mozilla.org/mozilla-central/file/tip/security/nss/lib/ckfw/builtins/certdata.txt
+It contains the certificates in PEM format and therefore
+can be directly used with curl / libcurl / php_curl, or with
+an Apache+mod_ssl webserver for SSL client authentication.
+Just configure this file as the SSLCACertificateFile.#
+
+***** BEGIN LICENSE BLOCK *****
+This Source Code Form is subject to the terms of the Mozilla Public License,
+v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain
+one at http://mozilla.org/MPL/2.0/.
+
+***** END LICENSE BLOCK *****
+@(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $
diff --git a/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/METADATA b/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/METADATA
new file mode 100644
index 0000000..50af144
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/METADATA
@@ -0,0 +1,77 @@
+Metadata-Version: 2.2
+Name: certifi
+Version: 2025.1.31
+Summary: Python package for providing Mozilla's CA Bundle.
+Home-page: https://github.com/certifi/python-certifi
+Author: Kenneth Reitz
+Author-email: me@kennethreitz.com
+License: MPL-2.0
+Project-URL: Source, https://github.com/certifi/python-certifi
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
+Classifier: Natural Language :: English
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+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 :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3.13
+Requires-Python: >=3.6
+License-File: LICENSE
+Dynamic: author
+Dynamic: author-email
+Dynamic: classifier
+Dynamic: description
+Dynamic: home-page
+Dynamic: license
+Dynamic: project-url
+Dynamic: requires-python
+Dynamic: summary
+
+Certifi: Python SSL Certificates
+================================
+
+Certifi provides Mozilla's carefully curated collection of Root Certificates for
+validating the trustworthiness of SSL certificates while verifying the identity
+of TLS hosts. It has been extracted from the `Requests`_ project.
+
+Installation
+------------
+
+``certifi`` is available on PyPI. Simply install it with ``pip``::
+
+ $ pip install certifi
+
+Usage
+-----
+
+To reference the installed certificate authority (CA) bundle, you can use the
+built-in function::
+
+ >>> import certifi
+
+ >>> certifi.where()
+ '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem'
+
+Or from the command line::
+
+ $ python -m certifi
+ /usr/local/lib/python3.7/site-packages/certifi/cacert.pem
+
+Enjoy!
+
+.. _`Requests`: https://requests.readthedocs.io/en/master/
+
+Addition/Removal of Certificates
+--------------------------------
+
+Certifi does not support any addition/removal or other modification of the
+CA trust store content. This project is intended to provide a reliable and
+highly portable root of trust to python deployments. Look to upstream projects
+for methods to use alternate trust.
diff --git a/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/RECORD b/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/RECORD
new file mode 100644
index 0000000..e554dc5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/RECORD
@@ -0,0 +1,14 @@
+certifi-2025.1.31.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+certifi-2025.1.31.dist-info/LICENSE,sha256=6TcW2mucDVpKHfYP5pWzcPBpVgPSH2-D8FPkLPwQyvc,989
+certifi-2025.1.31.dist-info/METADATA,sha256=t5kcT5aGu0dQ6_psUNZYTqnC0uCRnponewm3uYjeHbg,2451
+certifi-2025.1.31.dist-info/RECORD,,
+certifi-2025.1.31.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
+certifi-2025.1.31.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8
+certifi/__init__.py,sha256=neIaAf7BM36ygmQCmy-ZsSyjnvjWghFeu13wwEAnjj0,94
+certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243
+certifi/__pycache__/__init__.cpython-312.pyc,,
+certifi/__pycache__/__main__.cpython-312.pyc,,
+certifi/__pycache__/core.cpython-312.pyc,,
+certifi/cacert.pem,sha256=xVsh-Qf3-G1IrdCTVS-1ZRdJ_1-GBQjMu0I9bB-9gMc,297255
+certifi/core.py,sha256=qRDDFyXVJwTB_EmoGppaXU_R9qCZvhl-EzxPMuV3nTA,4426
+certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
diff --git a/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/WHEEL
new file mode 100644
index 0000000..505164b
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: setuptools (75.8.0)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/top_level.txt
new file mode 100644
index 0000000..963eac5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/top_level.txt
@@ -0,0 +1 @@
+certifi
diff --git a/testcline/lib/python3.12/site-packages/certifi/__init__.py b/testcline/lib/python3.12/site-packages/certifi/__init__.py
new file mode 100644
index 0000000..177082e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/certifi/__init__.py
@@ -0,0 +1,4 @@
+from .core import contents, where
+
+__all__ = ["contents", "where"]
+__version__ = "2025.01.31"
diff --git a/testcline/lib/python3.12/site-packages/certifi/__main__.py b/testcline/lib/python3.12/site-packages/certifi/__main__.py
new file mode 100644
index 0000000..8945b5d
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/certifi/__main__.py
@@ -0,0 +1,12 @@
+import argparse
+
+from certifi import contents, where
+
+parser = argparse.ArgumentParser()
+parser.add_argument("-c", "--contents", action="store_true")
+args = parser.parse_args()
+
+if args.contents:
+ print(contents())
+else:
+ print(where())
diff --git a/testcline/lib/python3.12/site-packages/certifi/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/certifi/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..012fd9a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/certifi/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/certifi/__pycache__/__main__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/certifi/__pycache__/__main__.cpython-312.pyc
new file mode 100644
index 0000000..a77fa40
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/certifi/__pycache__/__main__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/certifi/__pycache__/core.cpython-312.pyc b/testcline/lib/python3.12/site-packages/certifi/__pycache__/core.cpython-312.pyc
new file mode 100644
index 0000000..3d8cae2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/certifi/__pycache__/core.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/certifi/cacert.pem b/testcline/lib/python3.12/site-packages/certifi/cacert.pem
new file mode 100644
index 0000000..860f259
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/certifi/cacert.pem
@@ -0,0 +1,4897 @@
+
+# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Label: "GlobalSign Root CA"
+# Serial: 4835703278459707669005204
+# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a
+# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c
+# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Label: "Entrust.net Premium 2048 Secure Server CA"
+# Serial: 946069240
+# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90
+# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31
+# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
+MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
+j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
+U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
+u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
+bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
+fF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Label: "Baltimore CyberTrust Root"
+# Serial: 33554617
+# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4
+# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74
+# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Label: "Entrust Root Certification Authority"
+# Serial: 1164660820
+# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4
+# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9
+# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
+0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+# Issuer: CN=AAA Certificate Services O=Comodo CA Limited
+# Subject: CN=AAA Certificate Services O=Comodo CA Limited
+# Label: "Comodo AAA Services root"
+# Serial: 1
+# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0
+# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49
+# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited
+# Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited
+# Label: "QuoVadis Root CA 2"
+# Serial: 1289
+# MD5 Fingerprint: 5e:39:7b:dd:f8:ba:ec:82:e9:ac:62:ba:0c:54:00:2b
+# SHA1 Fingerprint: ca:3a:fb:cf:12:40:36:4b:44:b2:16:20:88:80:48:39:19:93:7c:f7
+# SHA256 Fingerprint: 85:a0:dd:7d:d7:20:ad:b7:ff:05:f8:3d:54:2b:20:9d:c7:ff:45:28:f7:d6:77:b1:83:89:fe:a5:e5:c4:9e:86
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa
+GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg
+Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J
+WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB
+rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp
++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1
+ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i
+Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz
+PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og
+/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH
+oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI
+yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud
+EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2
+A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL
+MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f
+BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn
+g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl
+fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K
+WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha
+B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc
+hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR
+TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD
+mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z
+ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y
+4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza
+8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+
+# Issuer: CN=QuoVadis Root CA 3 O=QuoVadis Limited
+# Subject: CN=QuoVadis Root CA 3 O=QuoVadis Limited
+# Label: "QuoVadis Root CA 3"
+# Serial: 1478
+# MD5 Fingerprint: 31:85:3c:62:94:97:63:b9:aa:fd:89:4e:af:6f:e0:cf
+# SHA1 Fingerprint: 1f:49:14:f7:d8:74:95:1d:dd:ae:02:c0:be:fd:3a:2d:82:75:51:85
+# SHA256 Fingerprint: 18:f1:fc:7f:20:5d:f8:ad:dd:eb:7f:e0:07:dd:57:e3:af:37:5a:9c:4d:8d:73:54:6b:f4:f1:fe:d1:e1:8d:35
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM
+V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB
+4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr
+H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd
+8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv
+vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT
+mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe
+btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc
+T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt
+WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ
+c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A
+4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD
+VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG
+CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0
+aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu
+dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw
+czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G
+A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg
+Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0
+7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem
+d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd
++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B
+4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN
+t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x
+DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57
+k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s
+zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j
+Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT
+mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK
+4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
+
+# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com
+# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com
+# Label: "XRamp Global CA Root"
+# Serial: 107108908803651509692980124233745014957
+# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1
+# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6
+# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB
+gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk
+MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY
+UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx
+NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3
+dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy
+dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6
+38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP
+KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q
+DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4
+qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa
+JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi
+PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P
+BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs
+jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0
+eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD
+ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR
+vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa
+IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy
+i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ
+O+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
+
+# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Label: "Go Daddy Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67
+# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4
+# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
+
+# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Label: "Starfield Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24
+# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a
+# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root CA"
+# Serial: 17154717934120587862167794914071425081
+# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72
+# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43
+# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root CA"
+# Serial: 10944719598952040374951832963794454346
+# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e
+# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36
+# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert High Assurance EV Root CA"
+# Serial: 3553400076410547919724730734378100087
+# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a
+# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25
+# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
+
+# Issuer: CN=SwissSign Gold CA - G2 O=SwissSign AG
+# Subject: CN=SwissSign Gold CA - G2 O=SwissSign AG
+# Label: "SwissSign Gold CA - G2"
+# Serial: 13492815561806991280
+# MD5 Fingerprint: 24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93
+# SHA1 Fingerprint: d8:c5:38:8a:b7:30:1b:1b:6e:d4:7a:e6:45:25:3a:6f:9f:1a:27:61
+# SHA256 Fingerprint: 62:dd:0b:e9:b9:f5:0a:16:3e:a0:f8:e7:5c:05:3b:1e:ca:57:ea:55:c8:68:8f:64:7c:68:81:f2:c8:35:7b:95
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln
+biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF
+MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT
+d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8
+76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+
+bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c
+6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE
+emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd
+MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt
+MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y
+MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y
+FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi
+aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM
+gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB
+qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7
+lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn
+8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6
+45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO
+UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5
+O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC
+bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv
+GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a
+77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC
+hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3
+92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp
+Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w
+ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt
+Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureTrust CA O=SecureTrust Corporation
+# Subject: CN=SecureTrust CA O=SecureTrust Corporation
+# Label: "SecureTrust CA"
+# Serial: 17199774589125277788362757014266862032
+# MD5 Fingerprint: dc:32:c3:a7:6d:25:57:c7:68:09:9d:ea:2d:a9:a2:d1
+# SHA1 Fingerprint: 87:82:c6:c3:04:35:3b:cf:d2:96:92:d2:59:3e:7d:44:d9:34:ff:11
+# SHA256 Fingerprint: f1:c1:b5:0a:e5:a2:0d:d8:03:0e:c9:f6:bc:24:82:3d:d3:67:b5:25:57:59:b4:e7:1b:61:fc:e9:f7:37:5d:73
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
+MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
+cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
+Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
+0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
+wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
+7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
+8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
+BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
+JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
+6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
+3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
+D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
+CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Secure Global CA O=SecureTrust Corporation
+# Subject: CN=Secure Global CA O=SecureTrust Corporation
+# Label: "Secure Global CA"
+# Serial: 9751836167731051554232119481456978597
+# MD5 Fingerprint: cf:f4:27:0d:d4:ed:dc:65:16:49:6d:3d:da:bf:6e:de
+# SHA1 Fingerprint: 3a:44:73:5a:e5:81:90:1f:24:86:61:46:1e:3b:9c:c4:5f:f5:3a:1b
+# SHA256 Fingerprint: 42:00:f5:04:3a:c8:59:0e:bb:52:7d:20:9e:d1:50:30:29:fb:cb:d4:1c:a1:b5:06:ec:27:f1:5a:de:7d:ac:69
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx
+MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg
+Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ
+iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa
+/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ
+jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI
+HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7
+sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w
+gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw
+KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG
+AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L
+URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO
+H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm
+I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY
+iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
+
+# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO Certification Authority O=COMODO CA Limited
+# Label: "COMODO Certification Authority"
+# Serial: 104350513648249232941998508985834464573
+# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75
+# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b
+# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Label: "COMODO ECC Certification Authority"
+# Serial: 41578283867086692638256921589707938090
+# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23
+# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11
+# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certigna O=Dhimyotis
+# Subject: CN=Certigna O=Dhimyotis
+# Label: "Certigna"
+# Serial: 18364802974209362175
+# MD5 Fingerprint: ab:57:a6:5b:7d:42:82:19:b5:d8:58:26:28:5e:fd:ff
+# SHA1 Fingerprint: b1:2e:13:63:45:86:a4:6f:1a:b2:60:68:37:58:2d:c4:ac:fd:94:97
+# SHA256 Fingerprint: e3:b6:a2:db:2e:d7:ce:48:84:2f:7a:c5:32:41:c7:b7:1d:54:14:4b:fb:40:c1:1f:3f:1d:0b:42:f5:ee:a1:2d
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV
+BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X
+DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ
+BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4
+QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny
+gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw
+zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q
+130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2
+JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw
+ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT
+AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj
+AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG
+9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h
+bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc
+fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu
+HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w
+t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
+
+# Issuer: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority
+# Subject: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority
+# Label: "ePKI Root Certification Authority"
+# Serial: 28956088682735189655030529057352760477
+# MD5 Fingerprint: 1b:2e:00:ca:26:06:90:3d:ad:fe:6f:15:68:d3:6b:b3
+# SHA1 Fingerprint: 67:65:0d:f1:7e:8e:7e:5b:82:40:a4:f4:56:4b:cf:e2:3d:69:c6:f0
+# SHA256 Fingerprint: c0:a6:f4:dc:63:a2:4b:fd:cf:54:ef:2a:6a:08:2a:0a:72:de:35:80:3e:2f:f5:ff:52:7a:e5:d8:72:06:df:d5
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe
+MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
+ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw
+IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL
+SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH
+SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh
+ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X
+DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1
+TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ
+fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA
+sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU
+WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS
+nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH
+dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip
+NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC
+AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF
+MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB
+uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl
+PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP
+JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/
+gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2
+j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6
+5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB
+o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS
+/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z
+Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE
+W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D
+hNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
+
+# Issuer: O=certSIGN OU=certSIGN ROOT CA
+# Subject: O=certSIGN OU=certSIGN ROOT CA
+# Label: "certSIGN ROOT CA"
+# Serial: 35210227249154
+# MD5 Fingerprint: 18:98:c0:d6:e9:3a:fc:f9:b0:f5:0c:f7:4b:01:44:17
+# SHA1 Fingerprint: fa:b7:ee:36:97:26:62:fb:2d:b0:2a:f6:bf:03:fd:e8:7c:4b:2f:9b
+# SHA256 Fingerprint: ea:a9:62:c4:fa:4a:6b:af:eb:e4:15:19:6d:35:1c:cd:88:8d:4f:53:f3:fa:8a:e6:d7:c4:66:a9:4e:60:42:bb
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT
+AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD
+QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP
+MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do
+0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ
+UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d
+RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ
+OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv
+JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C
+AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O
+BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ
+LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY
+MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ
+44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I
+Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw
+i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN
+9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
+
+# Issuer: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services)
+# Subject: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services)
+# Label: "NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny"
+# Serial: 80544274841616
+# MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88
+# SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91
+# SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG
+EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3
+MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl
+cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR
+dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB
+pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM
+b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm
+aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz
+IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT
+lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz
+AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5
+VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG
+ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2
+BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG
+AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M
+U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh
+bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C
++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F
+uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2
+XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd.
+# Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd.
+# Label: "Microsec e-Szigno Root CA 2009"
+# Serial: 14014712776195784473
+# MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1
+# SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e
+# SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
+VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0
+ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G
+CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y
+OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx
+FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp
+Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP
+kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc
+cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U
+fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7
+N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC
+xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1
++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM
+Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG
+SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h
+mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk
+ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c
+2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t
+HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Label: "GlobalSign Root CA - R3"
+# Serial: 4835703278459759426209954
+# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28
+# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad
+# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
+
+# Issuer: CN=Izenpe.com O=IZENPE S.A.
+# Subject: CN=Izenpe.com O=IZENPE S.A.
+# Label: "Izenpe.com"
+# Serial: 917563065490389241595536686991402621
+# MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73
+# SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19
+# SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4
+MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6
+ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD
+VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j
+b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq
+scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO
+xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H
+LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX
+uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD
+yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+
+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q
+rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN
+BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L
+hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB
+QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+
+HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu
+Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg
+QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB
+BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA
+A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb
+laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56
+awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo
+JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw
+LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT
+VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk
+LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb
+UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/
+QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+
+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls
+QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Label: "Go Daddy Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01
+# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b
+# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Label: "Starfield Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96
+# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e
+# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Label: "Starfield Services Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2
+# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f
+# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
+ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
+VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
+ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
+dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
+OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
+8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
+Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
+hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
+6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
+AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
+bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
+ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
+qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
+0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
+sSi6
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Commercial O=AffirmTrust
+# Subject: CN=AffirmTrust Commercial O=AffirmTrust
+# Label: "AffirmTrust Commercial"
+# Serial: 8608355977964138876
+# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7
+# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7
+# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Networking O=AffirmTrust
+# Subject: CN=AffirmTrust Networking O=AffirmTrust
+# Label: "AffirmTrust Networking"
+# Serial: 8957382827206547757
+# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f
+# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f
+# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Premium O=AffirmTrust
+# Subject: CN=AffirmTrust Premium O=AffirmTrust
+# Label: "AffirmTrust Premium"
+# Serial: 7893706540734352110
+# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57
+# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27
+# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
+KeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Label: "AffirmTrust Premium ECC"
+# Serial: 8401224907861490260
+# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d
+# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb
+# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority
+# Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority
+# Label: "Certum Trusted Network CA"
+# Serial: 279744
+# MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78
+# SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e
+# SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM
+MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D
+ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU
+cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3
+WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg
+Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw
+IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH
+UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM
+TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU
+BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM
+kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x
+AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y
+sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL
+I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8
+J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY
+VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
+
+# Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA
+# Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA
+# Label: "TWCA Root Certification Authority"
+# Serial: 1
+# MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79
+# SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48
+# SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES
+MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU
+V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz
+WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO
+LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE
+AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH
+K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX
+RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z
+rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx
+3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq
+hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC
+MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls
+XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D
+lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn
+aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ
+YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
+
+# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2
+# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2
+# Label: "Security Communication RootCA2"
+# Serial: 0
+# MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43
+# SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74
+# SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl
+MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe
+U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX
+DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy
+dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj
+YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV
+OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr
+zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM
+VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ
+hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO
+ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw
+awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs
+OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF
+coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc
+okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8
+t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy
+1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/
+SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
+
+# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967
+# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967
+# Label: "Actalis Authentication Root CA"
+# Serial: 6271844772424770508
+# MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6
+# SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac
+# SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE
+BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w
+MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC
+SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1
+ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv
+UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX
+4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9
+KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/
+gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb
+rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ
+51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F
+be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe
+KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F
+v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn
+fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7
+jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz
+ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL
+e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70
+jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz
+WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V
+SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j
+pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX
+X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok
+fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R
+K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU
+ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU
+LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT
+LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327
+# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327
+# Label: "Buypass Class 2 Root CA"
+# Serial: 2
+# MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29
+# SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99
+# SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr
+6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV
+L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91
+1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx
+MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ
+QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB
+arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr
+Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi
+FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS
+P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN
+9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz
+uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h
+9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t
+OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo
++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7
+KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2
+DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us
+H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ
+I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7
+5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h
+3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz
+Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327
+# Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327
+# Label: "Buypass Class 3 Root CA"
+# Serial: 2
+# MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec
+# SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57
+# SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y
+ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E
+N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9
+tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX
+0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c
+/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X
+KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY
+zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS
+O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D
+34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP
+K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv
+Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj
+QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS
+IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2
+HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa
+O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv
+033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u
+dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE
+kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41
+3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD
+u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq
+4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc=
+-----END CERTIFICATE-----
+
+# Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center
+# Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center
+# Label: "T-TeleSec GlobalRoot Class 3"
+# Serial: 1
+# MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef
+# SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1
+# SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN
+8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/
+RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4
+hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5
+ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM
+EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1
+A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy
+WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ
+1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30
+6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT
+91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p
+TpPDpFQUWw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH
+# Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH
+# Label: "D-TRUST Root Class 3 CA 2 2009"
+# Serial: 623603
+# MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f
+# SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0
+# SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha
+ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM
+HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03
+UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42
+tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R
+ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM
+lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp
+/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G
+A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy
+MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl
+cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js
+L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL
+BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni
+acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
+o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K
+zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8
+PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y
+Johw1+qRzT65ysCQblrGXnRl11z+o+I=
+-----END CERTIFICATE-----
+
+# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH
+# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH
+# Label: "D-TRUST Root Class 3 CA 2 EV 2009"
+# Serial: 623604
+# MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6
+# SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83
+# SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw
+NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV
+BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn
+ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0
+3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z
+qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR
+p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8
+HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw
+ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea
+HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw
+Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh
+c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E
+RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt
+dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku
+Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp
+3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
+nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF
+CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na
+xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX
+KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1
+-----END CERTIFICATE-----
+
+# Issuer: CN=CA Disig Root R2 O=Disig a.s.
+# Subject: CN=CA Disig Root R2 O=Disig a.s.
+# Label: "CA Disig Root R2"
+# Serial: 10572350602393338211
+# MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03
+# SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71
+# SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV
+BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu
+MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy
+MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx
+EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe
+NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH
+PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I
+x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe
+QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR
+yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO
+QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912
+H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ
+QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD
+i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs
+nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1
+rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI
+hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf
+GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb
+lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka
++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal
+TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i
+nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3
+gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr
+G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os
+zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x
+L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL
+-----END CERTIFICATE-----
+
+# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV
+# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV
+# Label: "ACCVRAIZ1"
+# Serial: 6828503384748696800
+# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02
+# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17
+# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13
+-----BEGIN CERTIFICATE-----
+MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE
+AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw
+CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ
+BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND
+VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb
+qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY
+HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo
+G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA
+lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr
+IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/
+0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH
+k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47
+4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO
+m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa
+cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl
+uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI
+KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls
+ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG
+AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
+VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT
+VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG
+CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA
+cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA
+QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA
+7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA
+cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA
+QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA
+czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu
+aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt
+aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud
+DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF
+BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp
+D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU
+JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m
+AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD
+vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms
+tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH
+7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
+I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA
+h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF
+d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H
+pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7
+-----END CERTIFICATE-----
+
+# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA
+# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA
+# Label: "TWCA Global Root CA"
+# Serial: 3262
+# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96
+# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65
+# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx
+EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT
+VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5
+NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT
+B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF
+10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz
+0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh
+MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH
+zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc
+46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2
+yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi
+laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP
+oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA
+BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE
+qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm
+4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL
+1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
+LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF
+H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo
+RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+
+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh
+15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW
+6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW
+nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j
+wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz
+aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy
+KwbQBM0=
+-----END CERTIFICATE-----
+
+# Issuer: CN=TeliaSonera Root CA v1 O=TeliaSonera
+# Subject: CN=TeliaSonera Root CA v1 O=TeliaSonera
+# Label: "TeliaSonera Root CA v1"
+# Serial: 199041966741090107964904287217786801558
+# MD5 Fingerprint: 37:41:49:1b:18:56:9a:26:f5:ad:c2:66:fb:40:a5:4c
+# SHA1 Fingerprint: 43:13:bb:96:f1:d5:86:9b:c1:4e:6a:92:f6:cf:f6:34:69:87:82:37
+# SHA256 Fingerprint: dd:69:36:fe:21:f8:f0:77:c1:23:a1:a5:21:c1:22:24:f7:22:55:b7:3e:03:a7:26:06:93:e8:a2:4b:0f:a3:89
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw
+NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv
+b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD
+VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F
+VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1
+7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X
+Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+
+/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs
+81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm
+dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe
+Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu
+sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4
+pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs
+slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ
+arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD
+VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG
+9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl
+dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
+0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj
+TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed
+Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7
+Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI
+OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7
+vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW
+t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn
+HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx
+SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
+-----END CERTIFICATE-----
+
+# Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center
+# Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center
+# Label: "T-TeleSec GlobalRoot Class 2"
+# Serial: 1
+# MD5 Fingerprint: 2b:9b:9e:e4:7b:6c:1f:00:72:1a:cc:c1:77:79:df:6a
+# SHA1 Fingerprint: 59:0d:2d:7d:88:4f:40:2e:61:7e:a5:62:32:17:65:cf:17:d8:94:e9
+# SHA256 Fingerprint: 91:e2:f5:78:8d:58:10:eb:a7:ba:58:73:7d:e1:54:8a:8e:ca:cd:01:45:98:bc:0b:14:3e:04:1b:17:05:25:52
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd
+AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC
+FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi
+1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq
+jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ
+wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/
+WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy
+NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC
+uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw
+IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6
+g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
+9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP
+BSeOE6Fuwg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Atos TrustedRoot 2011 O=Atos
+# Subject: CN=Atos TrustedRoot 2011 O=Atos
+# Label: "Atos TrustedRoot 2011"
+# Serial: 6643877497813316402
+# MD5 Fingerprint: ae:b9:c4:32:4b:ac:7f:5d:66:cc:77:94:bb:2a:77:56
+# SHA1 Fingerprint: 2b:b1:f5:3e:55:0c:1d:c5:f1:d4:e6:b7:6a:46:4b:55:06:02:ac:21
+# SHA256 Fingerprint: f3:56:be:a2:44:b7:a9:1e:b3:5d:53:ca:9a:d7:86:4a:ce:01:8e:2d:35:d5:f8:f9:6d:df:68:a6:f4:1a:a4:74
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
+
+# Issuer: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited
+# Subject: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited
+# Label: "QuoVadis Root CA 1 G3"
+# Serial: 687049649626669250736271037606554624078720034195
+# MD5 Fingerprint: a4:bc:5b:3f:fe:37:9a:fa:64:f0:e2:fa:05:3d:0b:ab
+# SHA1 Fingerprint: 1b:8e:ea:57:96:29:1a:c9:39:ea:b8:0a:81:1a:73:73:c0:93:79:67
+# SHA256 Fingerprint: 8a:86:6f:d1:b2:76:b5:7e:57:8e:92:1c:65:82:8a:2b:ed:58:e9:f2:f2:88:05:41:34:b7:f1:f4:bf:c9:cc:74
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00
+MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV
+wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe
+rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341
+68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh
+4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp
+UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o
+abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc
+3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G
+KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt
+hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO
+Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt
+zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD
+ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
+MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2
+cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN
+qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5
+YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv
+b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2
+8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k
+NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj
+ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp
+q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt
+nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD
+-----END CERTIFICATE-----
+
+# Issuer: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited
+# Subject: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited
+# Label: "QuoVadis Root CA 2 G3"
+# Serial: 390156079458959257446133169266079962026824725800
+# MD5 Fingerprint: af:0c:86:6e:bf:40:2d:7f:0b:3e:12:50:ba:12:3d:06
+# SHA1 Fingerprint: 09:3c:61:f3:8b:8b:dc:7d:55:df:75:38:02:05:00:e1:25:f5:c8:36
+# SHA256 Fingerprint: 8f:e4:fb:0a:f9:3a:4d:0d:67:db:0b:eb:b2:3e:37:c7:1b:f3:25:dc:bc:dd:24:0e:a0:4d:af:58:b4:7e:18:40
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00
+MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf
+qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW
+n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym
+c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+
+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1
+o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j
+IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq
+IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz
+8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh
+vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l
+7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG
+cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD
+ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
+AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC
+roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga
+W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n
+lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE
++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV
+csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd
+dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg
+KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM
+HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4
+WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M
+-----END CERTIFICATE-----
+
+# Issuer: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited
+# Subject: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited
+# Label: "QuoVadis Root CA 3 G3"
+# Serial: 268090761170461462463995952157327242137089239581
+# MD5 Fingerprint: df:7d:b9:ad:54:6f:68:a1:df:89:57:03:97:43:b0:d7
+# SHA1 Fingerprint: 48:12:bd:92:3c:a8:c4:39:06:e7:30:6d:27:96:e6:a4:cf:22:2e:7d
+# SHA256 Fingerprint: 88:ef:81:de:20:2e:b0:18:45:2e:43:f8:64:72:5c:ea:5f:bd:1f:c2:d9:d2:05:73:07:09:c5:d8:b8:69:0f:46
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00
+MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR
+/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu
+FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR
+U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c
+ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR
+FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k
+A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw
+eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl
+sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp
+VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q
+A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+
+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD
+ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
+KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI
+FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv
+oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg
+u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP
+0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf
+3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl
+8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+
+DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN
+PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/
+ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root G2"
+# Serial: 15385348160840213938643033620894905419
+# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d
+# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f
+# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA
+n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc
+biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp
+EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA
+bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu
+YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB
+AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW
+BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI
+QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I
+0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni
+lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9
+B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv
+ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
+IhNzbM8m9Yop5w==
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root G3"
+# Serial: 15459312981008553731928384953135426796
+# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb
+# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89
+# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2
+-----BEGIN CERTIFICATE-----
+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
+RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf
+Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q
+RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD
+AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY
+JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv
+6pZjamVFkpUBtA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root G2"
+# Serial: 4293743540046975378534879503202253541
+# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44
+# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4
+# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
+MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
+2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
+1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
+q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
+tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
+vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
+5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
+1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
+NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
+Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
+8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
+pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
+MrY=
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root G3"
+# Serial: 7089244469030293291760083333884364146
+# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca
+# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e
+# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
+Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw
+EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
+IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG
+fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO
+Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd
+BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx
+AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/
+oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8
+sycX
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Trusted Root G4"
+# Serial: 7451500558977370777930084869016614236
+# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49
+# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4
+# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
+RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y
+ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If
+xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV
+ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO
+DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ
+jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/
+CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi
+EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM
+fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY
+uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK
+chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t
+9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2
+SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd
++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc
+fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa
+sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N
+cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N
+0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie
+4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI
+r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1
+/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm
+gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+
+-----END CERTIFICATE-----
+
+# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited
+# Label: "COMODO RSA Certification Authority"
+# Serial: 101909084537582093308941363524873193117
+# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18
+# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4
+# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
+NVOFBkpdn627G190
+-----END CERTIFICATE-----
+
+# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
+# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
+# Label: "USERTrust RSA Certification Authority"
+# Serial: 2645093764781058787591871645665788717
+# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5
+# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e
+# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
+MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
+BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
+3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
+tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
+Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
+VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
+79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
+c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
+Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
+c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
+UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
+Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
+Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
+VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
+ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
+8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
+iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
+Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
+XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
+qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
+VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
+L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
+jjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
+
+# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
+# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
+# Label: "USERTrust ECC Certification Authority"
+# Serial: 123013823720199481456569720443997572134
+# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1
+# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0
+# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl
+eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT
+JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
+Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg
+VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo
+I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng
+o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G
+A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB
+zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW
+RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
+# Label: "GlobalSign ECC Root CA - R5"
+# Serial: 32785792099990507226680698011560947931244
+# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08
+# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa
+# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc
+8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke
+hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI
+KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg
+515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO
+xwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
+
+# Issuer: CN=IdenTrust Commercial Root CA 1 O=IdenTrust
+# Subject: CN=IdenTrust Commercial Root CA 1 O=IdenTrust
+# Label: "IdenTrust Commercial Root CA 1"
+# Serial: 13298821034946342390520003877796839426
+# MD5 Fingerprint: b3:3e:77:73:75:ee:a0:d3:e3:7e:49:63:49:59:bb:c7
+# SHA1 Fingerprint: df:71:7e:aa:4a:d9:4e:c9:55:84:99:60:2d:48:de:5f:bc:f0:3a:25
+# SHA256 Fingerprint: 5d:56:49:9b:e4:d2:e0:8b:cf:ca:d0:8a:3e:38:72:3d:50:50:3b:de:70:69:48:e4:2f:55:60:30:19:e5:28:ae
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu
+VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw
+MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw
+JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT
+3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU
++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp
+S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1
+bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi
+T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL
+vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK
+Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK
+dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT
+c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv
+l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N
+iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD
+ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
+6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt
+LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93
+nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3
++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK
+W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT
+AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq
+l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG
+4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ
+mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A
+7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H
+-----END CERTIFICATE-----
+
+# Issuer: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust
+# Subject: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust
+# Label: "IdenTrust Public Sector Root CA 1"
+# Serial: 13298821034946342390521976156843933698
+# MD5 Fingerprint: 37:06:a5:b0:fc:89:9d:ba:f4:6b:8c:1a:64:cd:d5:ba
+# SHA1 Fingerprint: ba:29:41:60:77:98:3f:f4:f3:ef:f2:31:05:3b:2e:ea:6d:4d:45:fd
+# SHA256 Fingerprint: 30:d0:89:5a:9a:44:8a:26:20:91:63:55:22:d1:f5:20:10:b5:86:7a:ca:e1:2c:78:ef:95:8f:d4:f4:38:9f:2f
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu
+VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN
+MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0
+MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7
+ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy
+RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS
+bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF
+/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R
+3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw
+EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy
+9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V
+GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ
+2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV
+WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD
+W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN
+AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
+t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV
+DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9
+TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G
+lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW
+mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df
+WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5
++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ
+tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA
+GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv
+8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c
+-----END CERTIFICATE-----
+
+# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
+# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
+# Label: "Entrust Root Certification Authority - G2"
+# Serial: 1246989352
+# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2
+# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4
+# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39
+-----BEGIN CERTIFICATE-----
+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50
+cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs
+IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz
+dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy
+NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu
+dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt
+dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0
+aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T
+RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN
+cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW
+wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1
+U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0
+jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN
+BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/
+jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v
+1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R
+nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH
+VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
+# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
+# Label: "Entrust Root Certification Authority - EC1"
+# Serial: 51543124481930649114116133369
+# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc
+# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47
+# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG
+A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3
+d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu
+dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq
+RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy
+MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD
+VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g
+Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi
+A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt
+ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH
+Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC
+R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX
+hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
+
+# Issuer: CN=CFCA EV ROOT O=China Financial Certification Authority
+# Subject: CN=CFCA EV ROOT O=China Financial Certification Authority
+# Label: "CFCA EV ROOT"
+# Serial: 407555286
+# MD5 Fingerprint: 74:e1:b6:ed:26:7a:7a:44:30:33:94:ab:7b:27:81:30
+# SHA1 Fingerprint: e2:b8:29:4b:55:84:ab:6b:58:c2:90:46:6c:ac:3f:b8:39:8f:84:83
+# SHA256 Fingerprint: 5c:c3:d7:8e:4e:1d:5e:45:54:7a:04:e6:87:3e:64:f9:0c:f9:53:6d:1c:cc:2e:f8:00:f3:55:c4:c5:fd:70:fd
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD
+TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx
+MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j
+aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP
+T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03
+sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL
+TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5
+/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp
+7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz
+EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt
+hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP
+a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot
+aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg
+TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV
+PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv
+cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL
+tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd
+BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
+ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT
+ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL
+jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS
+ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy
+P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19
+xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d
+Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN
+5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe
+/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z
+AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ
+5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
+-----END CERTIFICATE-----
+
+# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed
+# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed
+# Label: "OISTE WISeKey Global Root GB CA"
+# Serial: 157768595616588414422159278966750757568
+# MD5 Fingerprint: a4:eb:b9:61:28:2e:b7:2f:98:b0:35:26:90:99:51:1d
+# SHA1 Fingerprint: 0f:f9:40:76:18:d3:d7:6a:4b:98:f0:a8:35:9e:0c:fd:27:ac:cc:ed
+# SHA256 Fingerprint: 6b:9c:08:e8:6e:b0:f7:67:cf:ad:65:cd:98:b6:21:49:e5:49:4a:67:f5:84:5e:7b:d1:ed:01:9f:27:b8:6b:d6
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt
+MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg
+Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i
+YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x
+CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG
+b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
+bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3
+HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx
+WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX
+1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk
+u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P
+99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r
+M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB
+BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh
+cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5
+gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO
+ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf
+aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
+Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
+-----END CERTIFICATE-----
+
+# Issuer: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A.
+# Subject: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A.
+# Label: "SZAFIR ROOT CA2"
+# Serial: 357043034767186914217277344587386743377558296292
+# MD5 Fingerprint: 11:64:c1:89:b0:24:b1:8c:b1:07:7e:89:9e:51:9e:99
+# SHA1 Fingerprint: e2:52:fa:95:3f:ed:db:24:60:bd:6e:28:f3:9c:cc:cf:5e:b3:3f:de
+# SHA256 Fingerprint: a1:33:9d:33:28:1a:0b:56:e5:57:d3:d3:2b:1c:e7:f9:36:7e:b0:94:bd:5f:a7:2a:7e:50:04:c8:de:d7:ca:fe
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL
+BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6
+ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw
+NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L
+cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg
+Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN
+QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT
+3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw
+3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6
+3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5
+BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN
+XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF
+AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw
+8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG
+nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP
+oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy
+d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg
+LvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority
+# Subject: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority
+# Label: "Certum Trusted Network CA 2"
+# Serial: 44979900017204383099463764357512596969
+# MD5 Fingerprint: 6d:46:9e:d9:25:6d:08:23:5b:5e:74:7d:1e:27:db:f2
+# SHA1 Fingerprint: d3:dd:48:3e:2b:bf:4c:05:e8:af:10:f5:fa:76:26:cf:d3:dc:30:92
+# SHA256 Fingerprint: b6:76:f2:ed:da:e8:77:5c:d3:6c:b0:f6:3c:d1:d4:60:39:61:f4:9e:62:65:ba:01:3a:2f:03:07:b6:d0:b8:04
+-----BEGIN CERTIFICATE-----
+MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB
+gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu
+QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG
+A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz
+OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ
+VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3
+b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA
+DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn
+0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB
+OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE
+fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E
+Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m
+o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i
+sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW
+OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez
+Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS
+adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n
+3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ
+F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf
+CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29
+XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm
+djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/
+WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb
+AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq
+P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko
+b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj
+XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P
+5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi
+DrW5viSP
+-----END CERTIFICATE-----
+
+# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority
+# Subject: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority
+# Label: "Hellenic Academic and Research Institutions RootCA 2015"
+# Serial: 0
+# MD5 Fingerprint: ca:ff:e2:db:03:d9:cb:4b:e9:0f:ad:84:fd:7b:18:ce
+# SHA1 Fingerprint: 01:0c:06:95:a6:98:19:14:ff:bf:5f:c6:b0:b6:95:ea:29:e9:12:a6
+# SHA256 Fingerprint: a0:40:92:9a:02:ce:53:b4:ac:f4:f2:ff:c6:98:1c:e4:49:6f:75:5e:6d:45:fe:0b:2a:69:2b:cd:52:52:3f:36
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix
+DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k
+IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT
+N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v
+dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG
+A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh
+ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx
+QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
+dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA
+4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0
+AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10
+4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C
+ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV
+9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD
+gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6
+Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq
+NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko
+LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
+Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd
+ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I
+XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI
+M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot
+9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V
+Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea
+j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh
+X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ
+l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf
+bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4
+pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK
+e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0
+vm9qp/UsQu0yrbYhnr68
+-----END CERTIFICATE-----
+
+# Issuer: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority
+# Subject: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority
+# Label: "Hellenic Academic and Research Institutions ECC RootCA 2015"
+# Serial: 0
+# MD5 Fingerprint: 81:e5:b4:17:eb:c2:f5:e1:4b:0d:41:7b:49:92:fe:ef
+# SHA1 Fingerprint: 9f:f1:71:8d:92:d5:9a:f3:7d:74:97:b4:bc:6f:84:68:0b:ba:b6:66
+# SHA256 Fingerprint: 44:b5:45:aa:8a:25:e6:5a:73:ca:15:dc:27:fc:36:d2:4c:1c:b9:95:3a:06:65:39:b1:15:82:dc:48:7b:48:33
+-----BEGIN CERTIFICATE-----
+MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN
+BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl
+bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv
+b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ
+BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj
+YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5
+MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0
+dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg
+QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa
+jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi
+C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep
+lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof
+TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
+-----END CERTIFICATE-----
+
+# Issuer: CN=ISRG Root X1 O=Internet Security Research Group
+# Subject: CN=ISRG Root X1 O=Internet Security Research Group
+# Label: "ISRG Root X1"
+# Serial: 172886928669790476064670243504169061120
+# MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e
+# SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8
+# SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
+WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
+ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
+h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
+A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
+T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
+B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
+B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
+KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
+OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
+jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
+qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
+rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
+hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
+ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
+3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
+NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
+ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
+TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
+jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
+oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
+4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
+mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
+emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
+-----END CERTIFICATE-----
+
+# Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM
+# Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM
+# Label: "AC RAIZ FNMT-RCM"
+# Serial: 485876308206448804701554682760554759
+# MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d
+# SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20
+# SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx
+CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ
+WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ
+BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG
+Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/
+yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf
+BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz
+WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF
+tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z
+374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC
+IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL
+mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7
+wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS
+MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2
+ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet
+UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H
+YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3
+LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
+nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1
+RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM
+LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf
+77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N
+JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm
+fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp
+6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp
+1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B
+9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok
+RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv
+uu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 1 O=Amazon
+# Subject: CN=Amazon Root CA 1 O=Amazon
+# Label: "Amazon Root CA 1"
+# Serial: 143266978916655856878034712317230054538369994
+# MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6
+# SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16
+# SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
+ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
+9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
+IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
+VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
+93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
+jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
+A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
+U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
+N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
+o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
+5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
+rqXRfboQnoZsG4q5WTP468SQvvG5
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 2 O=Amazon
+# Subject: CN=Amazon Root CA 2 O=Amazon
+# Label: "Amazon Root CA 2"
+# Serial: 143266982885963551818349160658925006970653239
+# MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66
+# SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a
+# SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK
+gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ
+W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg
+1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K
+8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r
+2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me
+z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR
+8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj
+mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz
+7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6
++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI
+0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm
+UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2
+LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS
+k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl
+7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm
+btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl
+urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+
+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63
+n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE
+76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H
+9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT
+4PsJYGw=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 3 O=Amazon
+# Subject: CN=Amazon Root CA 3 O=Amazon
+# Label: "Amazon Root CA 3"
+# Serial: 143266986699090766294700635381230934788665930
+# MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87
+# SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e
+# SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4
+-----BEGIN CERTIFICATE-----
+MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
+ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
+ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
+BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
+YyRIHN8wfdVoOw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 4 O=Amazon
+# Subject: CN=Amazon Root CA 4 O=Amazon
+# Label: "Amazon Root CA 4"
+# Serial: 143266989758080763974105200630763877849284878
+# MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd
+# SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be
+# SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
+9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
+M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
+MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
+CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
+1KyLa2tJElMzrdfkviT8tQp21KW8EA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM
+# Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM
+# Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1"
+# Serial: 1
+# MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49
+# SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca
+# SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16
+-----BEGIN CERTIFICATE-----
+MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx
+GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp
+bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w
+KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0
+BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy
+dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG
+EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll
+IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU
+QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT
+TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg
+LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7
+a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr
+LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr
+N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X
+YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/
+iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f
+AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH
+V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
+AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf
+IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4
+lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c
+8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf
+lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
+-----END CERTIFICATE-----
+
+# Issuer: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD.
+# Subject: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD.
+# Label: "GDCA TrustAUTH R5 ROOT"
+# Serial: 9009899650740120186
+# MD5 Fingerprint: 63:cc:d9:3d:34:35:5c:6f:53:a3:e2:08:70:48:1f:b4
+# SHA1 Fingerprint: 0f:36:38:5b:81:1a:25:c3:9b:31:4e:83:ca:e9:34:66:70:cc:74:b4
+# SHA256 Fingerprint: bf:ff:8f:d0:44:33:48:7d:6a:8a:a6:0c:1a:29:76:7a:9f:c2:bb:b0:5e:42:0f:71:3a:13:b9:92:89:1d:38:93
+-----BEGIN CERTIFICATE-----
+MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE
+BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
+IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0
+MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV
+BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w
+HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj
+Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj
+TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u
+KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj
+qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm
+MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12
+ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP
+zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk
+L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC
+jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA
+HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC
+AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
+p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm
+DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5
+COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry
+L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf
+JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg
+IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io
+2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV
+09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ
+XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq
+T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe
+MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
+-----END CERTIFICATE-----
+
+# Issuer: CN=SSL.com Root Certification Authority RSA O=SSL Corporation
+# Subject: CN=SSL.com Root Certification Authority RSA O=SSL Corporation
+# Label: "SSL.com Root Certification Authority RSA"
+# Serial: 8875640296558310041
+# MD5 Fingerprint: 86:69:12:c0:70:f1:ec:ac:ac:c2:d5:bc:a5:5b:a1:29
+# SHA1 Fingerprint: b7:ab:33:08:d1:ea:44:77:ba:14:80:12:5a:6f:bd:a9:36:49:0c:bb
+# SHA256 Fingerprint: 85:66:6a:56:2e:e0:be:5c:e9:25:c1:d8:89:0a:6f:76:a8:7e:c1:6d:4d:7d:5f:29:ea:74:19:cf:20:12:3b:69
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE
+BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK
+DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz
+OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
+bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R
+xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX
+qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC
+C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3
+6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh
+/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF
+YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E
+JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc
+US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8
+ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm
++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi
+M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G
+A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV
+cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc
+Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs
+PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/
+q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0
+cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr
+a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I
+H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y
+K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu
+nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf
+oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY
+Ic2wBlX7Jz9TkHCpBB5XJ7k=
+-----END CERTIFICATE-----
+
+# Issuer: CN=SSL.com Root Certification Authority ECC O=SSL Corporation
+# Subject: CN=SSL.com Root Certification Authority ECC O=SSL Corporation
+# Label: "SSL.com Root Certification Authority ECC"
+# Serial: 8495723813297216424
+# MD5 Fingerprint: 2e:da:e4:39:7f:9c:8f:37:d1:70:9f:26:17:51:3a:8e
+# SHA1 Fingerprint: c3:19:7c:39:24:e6:54:af:1b:c4:ab:20:95:7a:e2:c3:0e:13:02:6a
+# SHA256 Fingerprint: 34:17:bb:06:cc:60:07:da:1b:96:1c:92:0b:8a:b4:ce:3f:ad:82:0e:4a:a3:0b:9a:cb:c4:a7:4e:bd:ce:bc:65
+-----BEGIN CERTIFICATE-----
+MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz
+WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0
+b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS
+b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI
+7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg
+CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud
+EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD
+VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T
+kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+
+gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
+-----END CERTIFICATE-----
+
+# Issuer: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation
+# Subject: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation
+# Label: "SSL.com EV Root Certification Authority RSA R2"
+# Serial: 6248227494352943350
+# MD5 Fingerprint: e1:1e:31:58:1a:ae:54:53:02:f6:17:6a:11:7b:4d:95
+# SHA1 Fingerprint: 74:3a:f0:52:9b:d0:32:a0:f4:4a:83:cd:d4:ba:a9:7b:7c:2e:c4:9a
+# SHA256 Fingerprint: 2e:7b:f1:6c:c2:24:85:a7:bb:e2:aa:86:96:75:07:61:b0:ae:39:be:3b:2f:e9:d0:cc:6d:4e:f7:34:91:42:5c
+-----BEGIN CERTIFICATE-----
+MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV
+BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE
+CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy
+MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G
+A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD
+DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq
+M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf
+OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa
+4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9
+HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR
+aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA
+b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ
+Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV
+PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO
+pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu
+UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY
+MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
+HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4
+9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW
+s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5
+Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg
+cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM
+79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz
+/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt
+ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm
+Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK
+QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ
+w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi
+S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07
+mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
+-----END CERTIFICATE-----
+
+# Issuer: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation
+# Subject: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation
+# Label: "SSL.com EV Root Certification Authority ECC"
+# Serial: 3182246526754555285
+# MD5 Fingerprint: 59:53:22:65:83:42:01:54:c0:ce:42:b9:5a:7c:f2:90
+# SHA1 Fingerprint: 4c:dd:51:a3:d1:f5:20:32:14:b0:c6:c5:32:23:03:91:c7:46:42:6d
+# SHA256 Fingerprint: 22:a2:c1:f7:bd:ed:70:4c:c1:e7:01:b5:f4:08:c3:10:88:0f:e9:56:b5:de:2a:4a:44:f9:9c:87:3a:25:a7:c8
+-----BEGIN CERTIFICATE-----
+MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx
+NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv
+bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49
+AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA
+VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku
+WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP
+MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX
+5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ
+ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg
+h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6
+# Label: "GlobalSign Root CA - R6"
+# Serial: 1417766617973444989252670301619537
+# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae
+# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1
+# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg
+MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx
+MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET
+MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI
+xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k
+ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD
+aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw
+LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw
+1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX
+k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2
+SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h
+bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n
+WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY
+rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce
+MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu
+bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt
+Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61
+55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj
+vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf
+cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz
+oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp
+nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs
+pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v
+JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R
+8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4
+5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
+
+# Issuer: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed
+# Subject: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed
+# Label: "OISTE WISeKey Global Root GC CA"
+# Serial: 44084345621038548146064804565436152554
+# MD5 Fingerprint: a9:d6:b9:2d:2f:93:64:f8:a5:69:ca:91:e9:68:07:23
+# SHA1 Fingerprint: e0:11:84:5e:34:de:be:88:81:b9:9c:f6:16:26:d1:96:1f:c3:b9:31
+# SHA256 Fingerprint: 85:60:f9:1c:36:24:da:ba:95:70:b5:fe:a0:db:e3:6f:f1:1a:83:23:be:94:86:85:4f:b3:f3:4a:55:71:19:8d
+-----BEGIN CERTIFICATE-----
+MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw
+CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91
+bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg
+Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ
+BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu
+ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS
+b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni
+eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W
+p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T
+rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV
+57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg
+Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
+-----END CERTIFICATE-----
+
+# Issuer: CN=UCA Global G2 Root O=UniTrust
+# Subject: CN=UCA Global G2 Root O=UniTrust
+# Label: "UCA Global G2 Root"
+# Serial: 124779693093741543919145257850076631279
+# MD5 Fingerprint: 80:fe:f0:c4:4a:f0:5c:62:32:9f:1c:ba:78:a9:50:f8
+# SHA1 Fingerprint: 28:f9:78:16:19:7a:ff:18:25:18:aa:44:fe:c1:a0:ce:5c:b6:4c:8a
+# SHA256 Fingerprint: 9b:ea:11:c9:76:fe:01:47:64:c1:be:56:a6:f9:14:b5:a5:60:31:7a:bd:99:88:39:33:82:e5:16:1a:a0:49:3c
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9
+MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH
+bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x
+CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds
+b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr
+b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9
+kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm
+VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R
+VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc
+C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj
+tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY
+D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv
+j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl
+NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6
+iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP
+O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/
+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV
+ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj
+L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
+1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl
+1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU
+b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV
+PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj
+y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb
+EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg
+DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI
++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy
+YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX
+UB+K+wb1whnw0A==
+-----END CERTIFICATE-----
+
+# Issuer: CN=UCA Extended Validation Root O=UniTrust
+# Subject: CN=UCA Extended Validation Root O=UniTrust
+# Label: "UCA Extended Validation Root"
+# Serial: 106100277556486529736699587978573607008
+# MD5 Fingerprint: a1:f3:5f:43:c6:34:9b:da:bf:8c:7e:05:53:ad:96:e2
+# SHA1 Fingerprint: a3:a1:b0:6f:24:61:23:4a:e3:36:a5:c2:37:fc:a6:ff:dd:f0:d7:3a
+# SHA256 Fingerprint: d4:3a:f9:b3:54:73:75:5c:96:84:fc:06:d7:d8:cb:70:ee:5c:28:e7:73:fb:29:4e:b4:1e:e7:17:22:92:4d:24
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH
+MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF
+eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx
+MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV
+BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog
+D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS
+sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop
+O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk
+sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi
+c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj
+VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz
+KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/
+TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G
+sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs
+1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD
+fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN
+l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
+ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ
+VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5
+c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp
+4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s
+t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj
+2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO
+vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C
+xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx
+cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM
+fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036
+# Subject: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036
+# Label: "Certigna Root CA"
+# Serial: 269714418870597844693661054334862075617
+# MD5 Fingerprint: 0e:5c:30:62:27:eb:5b:bc:d7:ae:62:ba:e9:d5:df:77
+# SHA1 Fingerprint: 2d:0d:52:14:ff:9e:ad:99:24:01:74:20:47:6e:6c:85:27:27:f5:43
+# SHA256 Fingerprint: d4:8d:3d:23:ee:db:50:a4:59:e5:51:97:60:1c:27:77:4b:9d:7b:18:c9:4d:5a:05:95:11:a1:02:50:b9:31:68
+-----BEGIN CERTIFICATE-----
+MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw
+WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw
+MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x
+MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD
+VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX
+BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO
+ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M
+CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu
+I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm
+TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh
+C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf
+ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz
+IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT
+Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k
+JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5
+hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB
+GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
+1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov
+L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo
+dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr
+aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq
+hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L
+6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG
+HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6
+0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB
+lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi
+o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1
+gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v
+faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63
+Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh
+jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw
+3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
+-----END CERTIFICATE-----
+
+# Issuer: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI
+# Subject: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI
+# Label: "emSign Root CA - G1"
+# Serial: 235931866688319308814040
+# MD5 Fingerprint: 9c:42:84:57:dd:cb:0b:a7:2e:95:ad:b6:f3:da:bc:ac
+# SHA1 Fingerprint: 8a:c7:ad:8f:73:ac:4e:c1:b5:75:4d:a5:40:f4:fc:cf:7c:b5:8e:8c
+# SHA256 Fingerprint: 40:f6:af:03:46:a9:9a:a1:cd:1d:55:5a:4e:9c:ce:62:c7:f9:63:46:03:ee:40:66:15:83:3d:c8:c8:d0:03:67
+-----BEGIN CERTIFICATE-----
+MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD
+VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU
+ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH
+MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO
+MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv
+Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz
+f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO
+8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq
+d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM
+tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt
+Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB
+o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD
+AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x
+PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM
+wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d
+GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH
+6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby
+RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
+iN66zB+Afko=
+-----END CERTIFICATE-----
+
+# Issuer: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI
+# Subject: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI
+# Label: "emSign ECC Root CA - G3"
+# Serial: 287880440101571086945156
+# MD5 Fingerprint: ce:0b:72:d1:9f:88:8e:d0:50:03:e8:e3:b8:8b:67:40
+# SHA1 Fingerprint: 30:43:fa:4f:f2:57:dc:a0:c3:80:ee:2e:58:ea:78:b2:3f:e6:bb:c1
+# SHA256 Fingerprint: 86:a1:ec:ba:08:9c:4a:8d:3b:be:27:34:c6:12:ba:34:1d:81:3e:04:3c:f9:e8:a8:62:cd:5c:57:a3:6b:be:6b
+-----BEGIN CERTIFICATE-----
+MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG
+EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo
+bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
+RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ
+TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s
+b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw
+djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0
+WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS
+fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB
+zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq
+hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB
+CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD
++JbNR6iC8hZVdyR+EhCVBCyj
+-----END CERTIFICATE-----
+
+# Issuer: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI
+# Subject: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI
+# Label: "emSign Root CA - C1"
+# Serial: 825510296613316004955058
+# MD5 Fingerprint: d8:e3:5d:01:21:fa:78:5a:b0:df:ba:d2:ee:2a:5f:68
+# SHA1 Fingerprint: e7:2e:f1:df:fc:b2:09:28:cf:5d:d4:d5:67:37:b1:51:cb:86:4f:01
+# SHA256 Fingerprint: 12:56:09:aa:30:1d:a0:a2:49:b9:7a:82:39:cb:6a:34:21:6f:44:dc:ac:9f:39:54:b1:42:92:f2:e8:c8:60:8f
+-----BEGIN CERTIFICATE-----
+MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG
+A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg
+SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw
+MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln
+biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v
+dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ
+BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ
+HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH
+3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH
+GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c
+xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1
+aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq
+TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87
+/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4
+kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG
+YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT
++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo
+WXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
+-----END CERTIFICATE-----
+
+# Issuer: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI
+# Subject: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI
+# Label: "emSign ECC Root CA - C3"
+# Serial: 582948710642506000014504
+# MD5 Fingerprint: 3e:53:b3:a3:81:ee:d7:10:f8:d3:b0:1d:17:92:f5:d5
+# SHA1 Fingerprint: b6:af:43:c2:9b:81:53:7d:f6:ef:6b:c3:1f:1f:60:15:0c:ee:48:66
+# SHA256 Fingerprint: bc:4d:80:9b:15:18:9d:78:db:3e:1d:8c:f4:f9:72:6a:79:5d:a1:64:3c:a5:f1:35:8e:1d:db:0e:dc:0d:7e:b3
+-----BEGIN CERTIFICATE-----
+MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG
+EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx
+IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw
+MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln
+biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND
+IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci
+MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti
+sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O
+BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
+Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c
+3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J
+0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Hongkong Post Root CA 3 O=Hongkong Post
+# Subject: CN=Hongkong Post Root CA 3 O=Hongkong Post
+# Label: "Hongkong Post Root CA 3"
+# Serial: 46170865288971385588281144162979347873371282084
+# MD5 Fingerprint: 11:fc:9f:bd:73:30:02:8a:fd:3f:f3:58:b9:cb:20:f0
+# SHA1 Fingerprint: 58:a2:d0:ec:20:52:81:5b:c1:f3:f8:64:02:24:4e:c2:8e:02:4b:02
+# SHA256 Fingerprint: 5a:2f:c0:3f:0c:83:b0:90:bb:fa:40:60:4b:09:88:44:6c:76:36:18:3d:f9:84:6e:17:10:1a:44:7f:b8:ef:d6
+-----BEGIN CERTIFICATE-----
+MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQEL
+BQAwbzELMAkGA1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJ
+SG9uZyBLb25nMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25n
+a29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2MDMwMjI5NDZaFw00MjA2MDMwMjI5
+NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxEjAQBgNVBAcT
+CUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMXSG9u
+Z2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCziNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFO
+dem1p+/l6TWZ5Mwc50tfjTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mI
+VoBc+L0sPOFMV4i707mV78vH9toxdCim5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV
+9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOesL4jpNrcyCse2m5FHomY
+2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj0mRiikKY
+vLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+Tt
+bNe/JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZb
+x39ri1UbSsUgYT2uy1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+
+l2oBlKN8W4UdKjk60FSh0Tlxnf0h+bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YK
+TE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsGxVd7GYYKecsAyVKvQv83j+Gj
+Hno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwIDAQABo2MwYTAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
+i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEw
+DQYJKoZIhvcNAQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG
+7BJ8dNVI0lkUmcDrudHr9EgwW62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCk
+MpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWldy8joRTnU+kLBEUx3XZL7av9YROXr
+gZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov+BS5gLNdTaqX4fnk
+GMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDceqFS
+3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJm
+Ozj/2ZQw9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+
+l6mc1X5VTMbeRRAc6uk7nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6c
+JfTzPV4e0hz5sy229zdcxsshTrD3mUcYhcErulWuBurQB7Lcq9CClnXO0lD+mefP
+L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa
+LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG
+mpv0
+-----END CERTIFICATE-----
+
+# Issuer: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation
+# Subject: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation
+# Label: "Microsoft ECC Root Certificate Authority 2017"
+# Serial: 136839042543790627607696632466672567020
+# MD5 Fingerprint: dd:a1:03:e6:4a:93:10:d1:bf:f0:19:42:cb:fe:ed:67
+# SHA1 Fingerprint: 99:9a:64:c3:7f:f4:7d:9f:ab:95:f1:47:69:89:14:60:ee:c4:c3:c5
+# SHA256 Fingerprint: 35:8d:f3:9d:76:4a:f9:e1:b7:66:e9:c9:72:df:35:2e:e1:5c:fa:c2:27:af:6a:d1:d7:0e:8e:4a:6e:dc:ba:02
+-----BEGIN CERTIFICATE-----
+MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD
+VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw
+MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV
+UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy
+b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR
+ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb
+hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3
+FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV
+L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB
+iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation
+# Subject: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation
+# Label: "Microsoft RSA Root Certificate Authority 2017"
+# Serial: 40975477897264996090493496164228220339
+# MD5 Fingerprint: 10:ff:00:ff:cf:c9:f8:c7:7a:c0:ee:35:8e:c9:0f:47
+# SHA1 Fingerprint: 73:a5:e6:4a:3b:ff:83:16:ff:0e:dc:cc:61:8a:90:6e:4e:ae:4d:74
+# SHA256 Fingerprint: c7:41:f7:0f:4b:2a:8d:88:bf:2e:71:c1:41:22:ef:53:ef:10:eb:a0:cf:a5:e6:4c:fa:20:f4:18:85:30:73:e0
+-----BEGIN CERTIFICATE-----
+MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl
+MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw
+NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
+IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG
+EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N
+aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ
+Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0
+ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1
+HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm
+gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ
+jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc
+aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG
+YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6
+W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K
+UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH
++FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q
+W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC
+LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC
+gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6
+tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh
+SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2
+TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3
+pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR
+xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp
+GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9
+dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN
+AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB
+RA+GsCyRxj3qrg+E
+-----END CERTIFICATE-----
+
+# Issuer: CN=e-Szigno Root CA 2017 O=Microsec Ltd.
+# Subject: CN=e-Szigno Root CA 2017 O=Microsec Ltd.
+# Label: "e-Szigno Root CA 2017"
+# Serial: 411379200276854331539784714
+# MD5 Fingerprint: de:1f:f6:9e:84:ae:a7:b4:21:ce:1e:58:7d:d1:84:98
+# SHA1 Fingerprint: 89:d4:83:03:4f:9e:9a:48:80:5f:72:37:d4:a9:a6:ef:cb:7c:1f:d1
+# SHA256 Fingerprint: be:b0:0b:30:83:9b:9b:c3:2c:32:e4:44:79:05:95:06:41:f2:64:21:b1:5e:d0:89:19:8b:51:8a:e2:ea:1b:99
+-----BEGIN CERTIFICATE-----
+MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV
+BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk
+LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv
+b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ
+BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg
+THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v
+IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv
+xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H
+Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB
+eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo
+jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ
++efcMQ==
+-----END CERTIFICATE-----
+
+# Issuer: O=CERTSIGN SA OU=certSIGN ROOT CA G2
+# Subject: O=CERTSIGN SA OU=certSIGN ROOT CA G2
+# Label: "certSIGN Root CA G2"
+# Serial: 313609486401300475190
+# MD5 Fingerprint: 8c:f1:75:8a:c6:19:cf:94:b7:f7:65:20:87:c3:97:c7
+# SHA1 Fingerprint: 26:f9:93:b4:ed:3d:28:27:b0:b9:4b:a7:e9:15:1d:a3:8d:92:e5:32
+# SHA256 Fingerprint: 65:7c:fe:2f:a7:3f:aa:38:46:25:71:f3:32:a2:36:3a:46:fc:e7:02:09:51:71:07:02:cd:fb:b6:ee:da:33:05
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV
+BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g
+Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ
+BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ
+R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF
+dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw
+vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ
+uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp
+n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs
+cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW
+xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P
+rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF
+DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx
+DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy
+LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C
+eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ
+d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq
+kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC
+b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl
+qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0
+OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c
+NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk
+ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO
+pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj
+03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk
+PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE
+1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX
+QRBdJ3NghVdJIgc=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc.
+# Subject: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc.
+# Label: "Trustwave Global Certification Authority"
+# Serial: 1846098327275375458322922162
+# MD5 Fingerprint: f8:1c:18:2d:2f:ba:5f:6d:a1:6c:bc:c7:ab:91:c7:0e
+# SHA1 Fingerprint: 2f:8f:36:4f:e1:58:97:44:21:59:87:a5:2a:9a:d0:69:95:26:7f:b5
+# SHA256 Fingerprint: 97:55:20:15:f5:dd:fc:3c:87:88:c0:06:94:45:55:40:88:94:45:00:84:f1:00:86:70:86:bc:1a:2b:b5:8d:c8
+-----BEGIN CERTIFICATE-----
+MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw
+CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x
+ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1
+c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx
+OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI
+SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI
+b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn
+swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu
+7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8
+1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW
+80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP
+JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l
+RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw
+hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10
+coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc
+BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n
+twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud
+DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W
+0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe
+uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q
+lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB
+aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE
+sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT
+MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe
+qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh
+VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8
+h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9
+EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK
+yeC2nOnOcXHebD8WpHk=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc.
+# Subject: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc.
+# Label: "Trustwave Global ECC P256 Certification Authority"
+# Serial: 4151900041497450638097112925
+# MD5 Fingerprint: 5b:44:e3:8d:5d:36:86:26:e8:0d:05:d2:59:a7:83:54
+# SHA1 Fingerprint: b4:90:82:dd:45:0c:be:8b:5b:b1:66:d3:e2:a4:08:26:cd:ed:42:cf
+# SHA256 Fingerprint: 94:5b:bc:82:5e:a5:54:f4:89:d1:fd:51:a7:3d:df:2e:a6:24:ac:70:19:a0:52:05:22:5c:22:a7:8c:cf:a8:b4
+-----BEGIN CERTIFICATE-----
+MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf
+BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3
+YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x
+NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G
+A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0
+d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF
+Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG
+SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN
+FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w
+DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw
+CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh
+DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7
+-----END CERTIFICATE-----
+
+# Issuer: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc.
+# Subject: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc.
+# Label: "Trustwave Global ECC P384 Certification Authority"
+# Serial: 2704997926503831671788816187
+# MD5 Fingerprint: ea:cf:60:c4:3b:b9:15:29:40:a1:97:ed:78:27:93:d6
+# SHA1 Fingerprint: e7:f3:a3:c8:cf:6f:c3:04:2e:6d:0e:67:32:c5:9e:68:95:0d:5e:d2
+# SHA256 Fingerprint: 55:90:38:59:c8:c0:c3:eb:b8:75:9e:ce:4e:25:57:22:5f:f5:75:8b:bd:38:eb:d4:82:76:60:1e:1b:d5:80:97
+-----BEGIN CERTIFICATE-----
+MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf
+BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3
+YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x
+NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G
+A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0
+d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF
+Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ
+j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF
+1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G
+A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3
+AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC
+MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu
+Sw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp.
+# Subject: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp.
+# Label: "NAVER Global Root Certification Authority"
+# Serial: 9013692873798656336226253319739695165984492813
+# MD5 Fingerprint: c8:7e:41:f6:25:3b:f5:09:b3:17:e8:46:3d:bf:d0:9b
+# SHA1 Fingerprint: 8f:6b:f2:a9:27:4a:da:14:a0:c4:f4:8e:61:27:f9:c0:1e:78:5d:d1
+# SHA256 Fingerprint: 88:f4:38:dc:f8:ff:d1:fa:8f:42:91:15:ff:e5:f8:2a:e1:e0:6e:0c:70:c3:75:fa:ad:71:7b:34:a4:9e:72:65
+-----BEGIN CERTIFICATE-----
+MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM
+BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG
+T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4NDJaFw0zNzA4MTgyMzU5NTlaMGkx
+CzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVTUyBQTEFURk9STSBD
+b3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVA
+iQqrDZBbUGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH
+38dq6SZeWYp34+hInDEW+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lE
+HoSTGEq0n+USZGnQJoViAbbJAh2+g1G7XNr4rRVqmfeSVPc0W+m/6imBEtRTkZaz
+kVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2aacp+yPOiNgSnABIqKYP
+szuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4Yb8Obtoq
+vC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHf
+nZ3zVHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaG
+YQ5fG8Ir4ozVu53BA0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo
+0es+nPxdGoMuK8u180SdOqcXYZaicdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3a
+CJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejyYhbLgGvtPe31HzClrkvJE+2K
+AQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNVHQ4EFgQU0p+I
+36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB
+Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoN
+qo0hV4/GPnrK21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatj
+cu3cvuzHV+YwIHHW1xDBE1UBjCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm
++LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bxhYTeodoS76TiEJd6eN4MUZeoIUCL
+hr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTgE34h5prCy8VCZLQe
+lHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTHD8z7
+p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8
+piKCk5XQA76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLR
+LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX
+5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oGI/hGoiLtk/bdmuYqh7GYVPEi92tF4+KO
+dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul
+9XXeifdy
+-----END CERTIFICATE-----
+
+# Issuer: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres
+# Subject: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres
+# Label: "AC RAIZ FNMT-RCM SERVIDORES SEGUROS"
+# Serial: 131542671362353147877283741781055151509
+# MD5 Fingerprint: 19:36:9c:52:03:2f:d2:d1:bb:23:cc:dd:1e:12:55:bb
+# SHA1 Fingerprint: 62:ff:d9:9e:c0:65:0d:03:ce:75:93:d2:ed:3f:2d:32:c9:e3:e5:4a
+# SHA256 Fingerprint: 55:41:53:b1:3d:2c:f9:dd:b7:53:bf:be:1a:4e:0a:e0:8d:0a:a4:18:70:58:fe:60:a2:b8:62:b2:e4:b8:7b:cb
+-----BEGIN CERTIFICATE-----
+MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw
+CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw
+FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S
+Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5
+MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL
+DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS
+QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH
+sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK
+Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu
+SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC
+MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy
+v+c=
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign Root R46 O=GlobalSign nv-sa
+# Subject: CN=GlobalSign Root R46 O=GlobalSign nv-sa
+# Label: "GlobalSign Root R46"
+# Serial: 1552617688466950547958867513931858518042577
+# MD5 Fingerprint: c4:14:30:e4:fa:66:43:94:2a:6a:1b:24:5f:19:d0:ef
+# SHA1 Fingerprint: 53:a2:b0:4b:ca:6b:d6:45:e6:39:8a:8e:c4:0d:d2:bf:77:c3:a2:90
+# SHA256 Fingerprint: 4f:a3:12:6d:8d:3a:11:d1:c4:85:5a:4f:80:7c:ba:d6:cf:91:9d:3a:5a:88:b0:3b:ea:2c:63:72:d9:3c:40:c9
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA
+MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD
+VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy
+MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt
+c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ
+OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG
+vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud
+316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo
+0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE
+y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF
+zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE
++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN
+I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs
+x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa
+ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC
+4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4
+7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg
+JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti
+2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk
+pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF
+FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt
+rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk
+ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5
+u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP
+4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6
+N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3
+vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign Root E46 O=GlobalSign nv-sa
+# Subject: CN=GlobalSign Root E46 O=GlobalSign nv-sa
+# Label: "GlobalSign Root E46"
+# Serial: 1552617690338932563915843282459653771421763
+# MD5 Fingerprint: b5:b8:66:ed:de:08:83:e3:c9:e2:01:34:06:ac:51:6f
+# SHA1 Fingerprint: 39:b4:6c:d5:fe:80:06:eb:e2:2f:4a:bb:08:33:a0:af:db:b9:dd:84
+# SHA256 Fingerprint: cb:b9:c4:4d:84:b8:04:3e:10:50:ea:31:a6:9f:51:49:55:d7:bf:d2:e2:c6:b4:93:01:01:9a:d6:1d:9f:50:58
+-----BEGIN CERTIFICATE-----
+MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx
+CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD
+ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw
+MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex
+HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq
+R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd
+yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ
+7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8
++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A=
+-----END CERTIFICATE-----
+
+# Issuer: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH
+# Subject: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH
+# Label: "GLOBALTRUST 2020"
+# Serial: 109160994242082918454945253
+# MD5 Fingerprint: 8a:c7:6f:cb:6d:e3:cc:a2:f1:7c:83:fa:0e:78:d7:e8
+# SHA1 Fingerprint: d0:67:c1:13:51:01:0c:aa:d0:c7:6a:65:37:31:16:26:4f:53:71:a2
+# SHA256 Fingerprint: 9a:29:6a:51:82:d1:d4:51:a2:e3:7f:43:9b:74:da:af:a2:67:52:33:29:f9:0f:9a:0d:20:07:c3:34:e2:3c:9a
+-----BEGIN CERTIFICATE-----
+MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG
+A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw
+FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx
+MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u
+aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b
+RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z
+YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3
+QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw
+yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+
+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ
+SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH
+r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0
+4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me
+dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw
+q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2
+nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu
+H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA
+VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC
+XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd
+6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf
++I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi
+kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7
+wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB
+TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C
+MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn
+4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I
+aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy
+qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz
+# Subject: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz
+# Label: "ANF Secure Server Root CA"
+# Serial: 996390341000653745
+# MD5 Fingerprint: 26:a6:44:5a:d9:af:4e:2f:b2:1d:b6:65:b0:4e:e8:96
+# SHA1 Fingerprint: 5b:6e:68:d0:cc:15:b6:a0:5f:1e:c1:5f:ae:02:fc:6b:2f:5d:6f:74
+# SHA256 Fingerprint: fb:8f:ec:75:91:69:b9:10:6b:1e:51:16:44:c6:18:c5:13:04:37:3f:6c:06:43:08:8d:8b:ef:fd:1b:99:75:99
+-----BEGIN CERTIFICATE-----
+MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNV
+BAUTCUc2MzI4NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlk
+YWQgZGUgQ2VydGlmaWNhY2lvbjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNV
+BAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3QgQ0EwHhcNMTkwOTA0MTAwMDM4WhcN
+MzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEwMQswCQYDVQQGEwJF
+UzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQwEgYD
+VQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9v
+dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCj
+cqQZAZ2cC4Ffc0m6p6zzBE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9q
+yGFOtibBTI3/TO80sh9l2Ll49a2pcbnvT1gdpd50IJeh7WhM3pIXS7yr/2WanvtH
+2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcvB2VSAKduyK9o7PQUlrZX
+H1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXsezx76W0OL
+zc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyR
+p1RMVwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQz
+W7i1o0TJrH93PB0j7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/
+SiOL9V8BY9KHcyi1Swr1+KuCLH5zJTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJn
+LNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe8TZBAQIvfXOn3kLMTOmJDVb3
+n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVOHj1tyRRM4y5B
+u8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj
+o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
+AgEATh65isagmD9uw2nAalxJUqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L
+9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzxj6ptBZNscsdW699QIyjlRRA96Gej
+rw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDtdD+4E5UGUcjohybK
+pFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM5gf0
+vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjq
+OknkJjCb5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ
+/zo1PqVUSlJZS2Db7v54EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ9
+2zg/LFis6ELhDtjTO0wugumDLmsx2d1Hhk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI
++PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGyg77FGr8H6lnco4g175x2
+MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3r5+qPeoo
+tt7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority
+# Subject: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority
+# Label: "Certum EC-384 CA"
+# Serial: 160250656287871593594747141429395092468
+# MD5 Fingerprint: b6:65:b3:96:60:97:12:a1:ec:4e:e1:3d:a3:c6:c9:f1
+# SHA1 Fingerprint: f3:3e:78:3c:ac:df:f4:a2:cc:ac:67:55:69:56:d7:e5:16:3c:e1:ed
+# SHA256 Fingerprint: 6b:32:80:85:62:53:18:aa:50:d1:73:c9:8d:8b:da:09:d5:7e:27:41:3d:11:4c:f7:87:a0:f5:d0:6c:03:0c:f6
+-----BEGIN CERTIFICATE-----
+MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw
+CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw
+JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT
+EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0
+WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT
+LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX
+BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE
+KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm
+Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8
+EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J
+UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn
+nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority
+# Subject: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority
+# Label: "Certum Trusted Root CA"
+# Serial: 40870380103424195783807378461123655149
+# MD5 Fingerprint: 51:e1:c2:e7:fe:4c:84:af:59:0e:2f:f4:54:6f:ea:29
+# SHA1 Fingerprint: c8:83:44:c0:18:ae:9f:cc:f1:87:b7:8f:22:d1:c5:d7:45:84:ba:e5
+# SHA256 Fingerprint: fe:76:96:57:38:55:77:3e:37:a9:5e:7a:d4:d9:cc:96:c3:01:57:c1:5d:31:76:5b:a9:b1:57:04:e1:ae:78:fd
+-----BEGIN CERTIFICATE-----
+MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6
+MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu
+MScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNV
+BAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwHhcNMTgwMzE2MTIxMDEzWhcNNDMw
+MzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEg
+U3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo
+b3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZ
+n0EGze2jusDbCSzBfN8pfktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/q
+p1x4EaTByIVcJdPTsuclzxFUl6s1wB52HO8AU5853BSlLCIls3Jy/I2z5T4IHhQq
+NwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2fJmItdUDmj0VDT06qKhF
+8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGtg/BKEiJ3
+HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGa
+mqi4NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi
+7VdNIuJGmj8PkTQkfVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSF
+ytKAQd8FqKPVhJBPC/PgP5sZ0jeJP/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0P
+qafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSYnjYJdmZm/Bo/6khUHL4wvYBQ
+v3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHKHRzQ+8S1h9E6
+Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1
+vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQAD
+ggIBAEii1QALLtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4
+WxmB82M+w85bj/UvXgF2Ez8sALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvo
+zMrnadyHncI013nR03e4qllY/p0m+jiGPp2Kh2RX5Rc64vmNueMzeMGQ2Ljdt4NR
+5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8CYyqOhNf6DR5UMEQ
+GfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA4kZf
+5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq
+0Uc9NneoWWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7D
+P78v3DSk+yshzWePS/Tj6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTM
+qJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmTOPQD8rv7gmsHINFSH5pkAnuYZttcTVoP
+0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZckbxJF0WddCajJFdr60qZf
+E2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb
+-----END CERTIFICATE-----
+
+# Issuer: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique
+# Subject: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique
+# Label: "TunTrust Root CA"
+# Serial: 108534058042236574382096126452369648152337120275
+# MD5 Fingerprint: 85:13:b9:90:5b:36:5c:b6:5e:b8:5a:f8:e0:31:57:b4
+# SHA1 Fingerprint: cf:e9:70:84:0f:e0:73:0f:9d:f6:0c:7f:2c:4b:ee:20:46:34:9c:bb
+# SHA256 Fingerprint: 2e:44:10:2a:b5:8c:b8:54:19:45:1c:8e:19:d9:ac:f3:66:2c:af:bc:61:4b:6a:53:96:0a:30:f7:d0:e2:eb:41
+-----BEGIN CERTIFICATE-----
+MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL
+BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg
+Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv
+b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG
+EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u
+IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ
+n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd
+2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF
+VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ
+GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF
+li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU
+r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2
+eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb
+MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg
+jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB
+7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW
+5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE
+ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0
+90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z
+xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu
+QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4
+FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH
+22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP
+xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn
+dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5
+Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b
+nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ
+CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH
+u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj
+d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o=
+-----END CERTIFICATE-----
+
+# Issuer: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA
+# Subject: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA
+# Label: "HARICA TLS RSA Root CA 2021"
+# Serial: 76817823531813593706434026085292783742
+# MD5 Fingerprint: 65:47:9b:58:86:dd:2c:f0:fc:a2:84:1f:1e:96:c4:91
+# SHA1 Fingerprint: 02:2d:05:82:fa:88:ce:14:0c:06:79:de:7f:14:10:e9:45:d7:a5:6d
+# SHA256 Fingerprint: d9:5d:0e:8e:da:79:52:5b:f9:be:b1:1b:14:d2:10:0d:32:94:98:5f:0c:62:d9:fa:bd:9c:d9:99:ec:cb:7b:1d
+-----BEGIN CERTIFICATE-----
+MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs
+MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg
+Um9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUzOFoXDTQ1MDIxMzEwNTUzN1owbDEL
+MAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
+YXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNBIFJv
+b3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569l
+mwVnlskNJLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE
+4VGC/6zStGndLuwRo0Xua2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uv
+a9of08WRiFukiZLRgeaMOVig1mlDqa2YUlhu2wr7a89o+uOkXjpFc5gH6l8Cct4M
+pbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K5FrZx40d/JiZ+yykgmvw
+Kh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEvdmn8kN3b
+LW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcY
+AuUR0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqB
+AGMUuTNe3QvboEUHGjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYq
+E613TBoYm5EPWNgGVMWX+Ko/IIqmhaZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHr
+W2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQCPxrvrNQKlr9qEgYRtaQQJKQ
+CoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAU
+X15QvWiWkKQUEapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3
+f5Z2EMVGpdAgS1D0NTsY9FVqQRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxaja
+H6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxDQpSbIPDRzbLrLFPCU3hKTwSUQZqP
+JzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcRj88YxeMn/ibvBZ3P
+zzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5vZSt
+jBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0
+/L5H9MG0qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pT
+BGIBnfHAT+7hOtSLIBD6Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79
+aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW
+xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU
+63ZTGI0RmLo=
+-----END CERTIFICATE-----
+
+# Issuer: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA
+# Subject: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA
+# Label: "HARICA TLS ECC Root CA 2021"
+# Serial: 137515985548005187474074462014555733966
+# MD5 Fingerprint: ae:f7:4c:e5:66:35:d1:b7:9b:8c:22:93:74:d3:4b:b0
+# SHA1 Fingerprint: bc:b0:c1:9d:e9:98:92:70:19:38:57:e9:8d:a7:b4:5d:6e:ee:01:48
+# SHA256 Fingerprint: 3f:99:cc:47:4a:cf:ce:4d:fe:d5:87:94:66:5e:47:8d:15:47:73:9f:2e:78:0f:1b:b4:ca:9b:13:30:97:d4:01
+-----BEGIN CERTIFICATE-----
+MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw
+CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh
+cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v
+dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG
+A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
+aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg
+Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7
+KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y
+STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD
+AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw
+SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN
+nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps
+-----END CERTIFICATE-----
+
+# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068
+# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068
+# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068"
+# Serial: 1977337328857672817
+# MD5 Fingerprint: 4e:6e:9b:54:4c:ca:b7:fa:48:e4:90:b1:15:4b:1c:a3
+# SHA1 Fingerprint: 0b:be:c2:27:22:49:cb:39:aa:db:35:5c:53:e3:8c:ae:78:ff:b6:fe
+# SHA256 Fingerprint: 57:de:05:83:ef:d2:b2:6e:03:61:da:99:da:9d:f4:64:8d:ef:7e:e8:44:1c:3b:72:8a:fa:9b:cd:e0:f9:b2:6a
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE
+BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h
+cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1
+MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg
+Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9
+thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM
+cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG
+L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i
+NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h
+X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b
+m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy
+Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja
+EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T
+KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF
+6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh
+OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc
+tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd
+IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j
+b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC
+AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw
+ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m
+iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF
+Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ
+hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P
+Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE
+EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV
+1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t
+CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR
+5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw
+f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9
+ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK
+GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV
+-----END CERTIFICATE-----
+
+# Issuer: CN=vTrus ECC Root CA O=iTrusChina Co.,Ltd.
+# Subject: CN=vTrus ECC Root CA O=iTrusChina Co.,Ltd.
+# Label: "vTrus ECC Root CA"
+# Serial: 630369271402956006249506845124680065938238527194
+# MD5 Fingerprint: de:4b:c1:f5:52:8c:9b:43:e1:3e:8f:55:54:17:8d:85
+# SHA1 Fingerprint: f6:9c:db:b0:fc:f6:02:13:b6:52:32:a6:a3:91:3f:16:70:da:c3:e1
+# SHA256 Fingerprint: 30:fb:ba:2c:32:23:8e:2a:98:54:7a:f9:79:31:e5:50:42:8b:9b:3f:1c:8e:eb:66:33:dc:fa:86:c5:b2:7d:d3
+-----BEGIN CERTIFICATE-----
+MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw
+RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY
+BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz
+MTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28u
+LEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+cToL0
+v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUd
+e4BdS49nTPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIw
+V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA
+AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG
+GJTO
+-----END CERTIFICATE-----
+
+# Issuer: CN=vTrus Root CA O=iTrusChina Co.,Ltd.
+# Subject: CN=vTrus Root CA O=iTrusChina Co.,Ltd.
+# Label: "vTrus Root CA"
+# Serial: 387574501246983434957692974888460947164905180485
+# MD5 Fingerprint: b8:c9:37:df:fa:6b:31:84:64:c5:ea:11:6a:1b:75:fc
+# SHA1 Fingerprint: 84:1a:69:fb:f5:cd:1a:25:34:13:3d:e3:f8:fc:b8:99:d0:c9:14:b7
+# SHA256 Fingerprint: 8a:71:de:65:59:33:6f:42:6c:26:e5:38:80:d0:0d:88:a1:8d:a4:c6:a9:1f:0d:cb:61:94:e2:06:c5:c9:63:87
+-----BEGIN CERTIFICATE-----
+MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL
+BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x
+FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx
+MDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoGA1UEChMTaVRydXNDaGluYSBDby4s
+THRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZotsSKYc
+IrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykU
+AyyNJJrIZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+
+GrPSbcKvdmaVayqwlHeFXgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z9
+8Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KAYPxMvDVTAWqXcoKv8R1w6Jz1717CbMdH
+flqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70kLJrxLT5ZOrpGgrIDajt
+J8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2AXPKBlim
+0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZN
+pGvu/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQ
+UqqzApVg+QxMaPnu1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHW
+OXSuTEGC2/KmSNGzm/MzqvOmwMVO9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMB
+AAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYgscasGrz2iTAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAKbqSSaet
+8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd
+nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1j
+bhd47F18iMjrjld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvM
+Kar5CKXiNxTKsbhm7xqC5PD48acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIiv
+TDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJnxDHO2zTlJQNgJXtxmOTAGytfdELS
+S8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554WgicEFOwE30z9J4nfr
+I8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4sEb9
+b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNB
+UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P
+Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven
+sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s=
+-----END CERTIFICATE-----
+
+# Issuer: CN=ISRG Root X2 O=Internet Security Research Group
+# Subject: CN=ISRG Root X2 O=Internet Security Research Group
+# Label: "ISRG Root X2"
+# Serial: 87493402998870891108772069816698636114
+# MD5 Fingerprint: d3:9e:c4:1e:23:3c:a6:df:cf:a3:7e:6d:e0:14:e6:e5
+# SHA1 Fingerprint: bd:b1:b9:3c:d5:97:8d:45:c6:26:14:55:f8:db:95:c7:5a:d1:53:af
+# SHA256 Fingerprint: 69:72:9b:8e:15:a8:6e:fc:17:7a:57:af:b7:17:1d:fc:64:ad:d2:8c:2f:ca:8c:f1:50:7e:34:45:3c:cb:14:70
+-----BEGIN CERTIFICATE-----
+MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw
+CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg
+R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00
+MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT
+ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw
+EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW
++1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9
+ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI
+zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW
+tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1
+/q4AaOeMSQ+2b1tbFfLn
+-----END CERTIFICATE-----
+
+# Issuer: CN=HiPKI Root CA - G1 O=Chunghwa Telecom Co., Ltd.
+# Subject: CN=HiPKI Root CA - G1 O=Chunghwa Telecom Co., Ltd.
+# Label: "HiPKI Root CA - G1"
+# Serial: 60966262342023497858655262305426234976
+# MD5 Fingerprint: 69:45:df:16:65:4b:e8:68:9a:8f:76:5f:ff:80:9e:d3
+# SHA1 Fingerprint: 6a:92:e4:a8:ee:1b:ec:96:45:37:e3:29:57:49:cd:96:e3:e5:d2:60
+# SHA256 Fingerprint: f0:15:ce:3c:c2:39:bf:ef:06:4b:e9:f1:d2:c4:17:e1:a0:26:4a:0a:94:be:1f:0c:8d:12:18:64:eb:69:49:cc
+-----BEGIN CERTIFICATE-----
+MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP
+MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
+ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa
+Fw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3
+YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kgUm9vdCBDQSAtIEcx
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0o9Qw
+qNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twv
+Vcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6
+lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnz
+Qs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRtU6M9/Aes1MU3guvklQgZ
+KILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfdhSi8MEyr48KxRURHH+CK
+FgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj1jOXTyFj
+HluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDr
+y+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ
+/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgM
+a/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6
+fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQDAgGGMA0GCSqG
+SIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi
+7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqc
+SE5XCV0vrPSltJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6Fza
+ZsT0pPBWGTMpWmWSBUdGSquEwx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9Tc
+XzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07QJNBAsNB1CI69aO4I1258EHBGG3zg
+iLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv5wiZqAxeJoBF1Pho
+L5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+GpzjLrF
+Ne85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wr
+kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+
+vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU
+YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4
+# Label: "GlobalSign ECC Root CA - R4"
+# Serial: 159662223612894884239637590694
+# MD5 Fingerprint: 26:29:f8:6d:e1:88:bf:a2:65:7f:aa:c4:cd:0f:7f:fc
+# SHA1 Fingerprint: 6b:a0:b0:98:e1:71:ef:5a:ad:fe:48:15:80:77:10:f4:bd:6f:0b:28
+# SHA256 Fingerprint: b0:85:d7:0b:96:4f:19:1a:73:e4:af:0d:54:ae:7a:0e:07:aa:fd:af:9b:71:dd:08:62:13:8a:b7:32:5a:24:a2
+-----BEGIN CERTIFICATE-----
+MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD
+VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw
+MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g
+UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT
+BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx
+uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV
+HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/
++wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147
+bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm
+-----END CERTIFICATE-----
+
+# Issuer: CN=GTS Root R1 O=Google Trust Services LLC
+# Subject: CN=GTS Root R1 O=Google Trust Services LLC
+# Label: "GTS Root R1"
+# Serial: 159662320309726417404178440727
+# MD5 Fingerprint: 05:fe:d0:bf:71:a8:a3:76:63:da:01:e0:d8:52:dc:40
+# SHA1 Fingerprint: e5:8c:1c:c4:91:3b:38:63:4b:e9:10:6e:e3:ad:8e:6b:9d:d9:81:4a
+# SHA256 Fingerprint: d9:47:43:2a:bd:e7:b7:fa:90:fc:2e:6b:59:10:1b:12:80:e0:e1:c7:e4:e4:0f:a3:c6:88:7f:ff:57:a7:f4:cf
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo
+27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w
+Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw
+TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl
+qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH
+szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8
+Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk
+MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
+wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p
+aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN
+VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID
+AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb
+C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
+QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy
+h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4
+7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J
+ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef
+MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/
+Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT
+6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ
+0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm
+2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb
+bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c
+-----END CERTIFICATE-----
+
+# Issuer: CN=GTS Root R2 O=Google Trust Services LLC
+# Subject: CN=GTS Root R2 O=Google Trust Services LLC
+# Label: "GTS Root R2"
+# Serial: 159662449406622349769042896298
+# MD5 Fingerprint: 1e:39:c0:53:e6:1e:29:82:0b:ca:52:55:36:5d:57:dc
+# SHA1 Fingerprint: 9a:44:49:76:32:db:de:fa:d0:bc:fb:5a:7b:17:bd:9e:56:09:24:94
+# SHA256 Fingerprint: 8d:25:cd:97:22:9d:bf:70:35:6b:da:4e:b3:cc:73:40:31:e2:4c:f0:0f:af:cf:d3:2d:c7:6e:b5:84:1c:7e:a8
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt
+nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY
+6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu
+MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k
+RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg
+f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV
++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo
+dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW
+Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa
+G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq
+gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID
+AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H
+vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8
+0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC
+B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u
+NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg
+yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev
+HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6
+xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR
+TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg
+JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV
+7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl
+6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL
+-----END CERTIFICATE-----
+
+# Issuer: CN=GTS Root R3 O=Google Trust Services LLC
+# Subject: CN=GTS Root R3 O=Google Trust Services LLC
+# Label: "GTS Root R3"
+# Serial: 159662495401136852707857743206
+# MD5 Fingerprint: 3e:e7:9d:58:02:94:46:51:94:e5:e0:22:4a:8b:e7:73
+# SHA1 Fingerprint: ed:e5:71:80:2b:c8:92:b9:5b:83:3c:d2:32:68:3f:09:cd:a0:1e:46
+# SHA256 Fingerprint: 34:d8:a7:3e:e2:08:d9:bc:db:0d:95:65:20:93:4b:4e:40:e6:94:82:59:6e:8b:6f:73:c8:42:6b:01:0a:6f:48
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD
+VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG
+A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw
+WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz
+IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G
+jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2
+4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7
+VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm
+ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X
+-----END CERTIFICATE-----
+
+# Issuer: CN=GTS Root R4 O=Google Trust Services LLC
+# Subject: CN=GTS Root R4 O=Google Trust Services LLC
+# Label: "GTS Root R4"
+# Serial: 159662532700760215368942768210
+# MD5 Fingerprint: 43:96:83:77:19:4d:76:b3:9d:65:52:e4:1d:22:a5:e8
+# SHA1 Fingerprint: 77:d3:03:67:b5:e0:0c:15:f6:0c:38:61:df:7c:e1:3b:92:46:4d:47
+# SHA256 Fingerprint: 34:9d:fa:40:58:c5:e2:63:12:3b:39:8a:e7:95:57:3c:4e:13:13:c8:3f:e6:8f:93:55:6c:d5:e8:03:1b:3c:7d
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD
+VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG
+A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw
+WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz
+IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi
+QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR
+HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D
+9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8
+p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD
+-----END CERTIFICATE-----
+
+# Issuer: CN=Telia Root CA v2 O=Telia Finland Oyj
+# Subject: CN=Telia Root CA v2 O=Telia Finland Oyj
+# Label: "Telia Root CA v2"
+# Serial: 7288924052977061235122729490515358
+# MD5 Fingerprint: 0e:8f:ac:aa:82:df:85:b1:f4:dc:10:1c:fc:99:d9:48
+# SHA1 Fingerprint: b9:99:cd:d1:73:50:8a:c4:47:05:08:9c:8c:88:fb:be:a0:2b:40:cd
+# SHA256 Fingerprint: 24:2b:69:74:2f:cb:1e:5b:2a:bf:98:89:8b:94:57:21:87:54:4e:5b:4d:99:11:78:65:73:62:1f:6a:74:b8:2c
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx
+CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE
+AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1
+NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZ
+MBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ76zBq
+AMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9
+vVYiQJ3q9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9
+lRdU2HhE8Qx3FZLgmEKnpNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTOD
+n3WhUidhOPFZPY5Q4L15POdslv5e2QJltI5c0BE0312/UqeBAMN/mUWZFdUXyApT
+7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW5olWK8jjfN7j/4nlNW4o
+6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNrRBH0pUPC
+TEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6
+WT0EBXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63R
+DolUK5X6wK0dmBR4M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZI
+pEYslOqodmJHixBTB0hXbOKSTbauBcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGj
+YzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7Wxy+G2CQ5MB0GA1UdDgQWBBRy
+rOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ
+8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi
+0f6X+J8wfBj5tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMM
+A8iZGok1GTzTyVR8qPAs5m4HeW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBS
+SRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+Cy748fdHif64W1lZYudogsYMVoe+K
+TTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygCQMez2P2ccGrGKMOF
+6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15h2Er
+3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMt
+Ty3EHD70sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pT
+VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW
+ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA
+rBPuUBQemMc=
+-----END CERTIFICATE-----
+
+# Issuer: CN=D-TRUST BR Root CA 1 2020 O=D-Trust GmbH
+# Subject: CN=D-TRUST BR Root CA 1 2020 O=D-Trust GmbH
+# Label: "D-TRUST BR Root CA 1 2020"
+# Serial: 165870826978392376648679885835942448534
+# MD5 Fingerprint: b5:aa:4b:d5:ed:f7:e3:55:2e:8f:72:0a:f3:75:b8:ed
+# SHA1 Fingerprint: 1f:5b:98:f0:e3:b5:f7:74:3c:ed:e6:b0:36:7d:32:cd:f4:09:41:67
+# SHA256 Fingerprint: e5:9a:aa:81:60:09:c2:2b:ff:5b:25:ba:d3:7d:f3:06:f0:49:79:7c:1f:81:d8:5a:b0:89:e6:57:bd:8f:00:44
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw
+CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS
+VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5
+NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG
+A1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7dPYS
+zuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0
+QVK5buXuQqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/
+VbNafAkl1bK6CKBrqx9tMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g
+PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2JyX3Jvb3Rf
+Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l
+dC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1
+c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO
+PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW
+wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV
+dWNbFJWcHwHP2NVypw87
+-----END CERTIFICATE-----
+
+# Issuer: CN=D-TRUST EV Root CA 1 2020 O=D-Trust GmbH
+# Subject: CN=D-TRUST EV Root CA 1 2020 O=D-Trust GmbH
+# Label: "D-TRUST EV Root CA 1 2020"
+# Serial: 126288379621884218666039612629459926992
+# MD5 Fingerprint: 8c:2d:9d:70:9f:48:99:11:06:11:fb:e9:cb:30:c0:6e
+# SHA1 Fingerprint: 61:db:8c:21:59:69:03:90:d8:7c:9c:12:86:54:cf:9d:3d:f4:dd:07
+# SHA256 Fingerprint: 08:17:0d:1a:a3:64:53:90:1a:2f:95:92:45:e3:47:db:0c:8d:37:ab:aa:bc:56:b8:1a:a1:00:dc:95:89:70:db
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw
+CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS
+VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5
+NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG
+A1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8ZRCC
+/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rD
+wpdhQntJraOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3
+OqQo5FD4pPfsazK2/umLMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g
+PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2V2X3Jvb3Rf
+Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l
+dC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1
+c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO
+PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA
+y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb
+gfM0agPnIjhQW+0ZT0MW
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc.
+# Subject: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc.
+# Label: "DigiCert TLS ECC P384 Root G5"
+# Serial: 13129116028163249804115411775095713523
+# MD5 Fingerprint: d3:71:04:6a:43:1c:db:a6:59:e1:a8:a3:aa:c5:71:ed
+# SHA1 Fingerprint: 17:f3:de:5e:9f:0f:19:e9:8e:f6:1f:32:26:6e:20:c4:07:ae:30:ee
+# SHA256 Fingerprint: 01:8e:13:f0:77:25:32:cf:80:9b:d1:b1:72:81:86:72:83:fc:48:c6:e1:3b:e9:c6:98:12:85:4a:49:0c:1b:05
+-----BEGIN CERTIFICATE-----
+MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp
+Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2
+MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
+bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS
+7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp
+0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS
+B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49
+BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ
+LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4
+DXZDjC5Ty3zfDBeWUA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc.
+# Subject: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc.
+# Label: "DigiCert TLS RSA4096 Root G5"
+# Serial: 11930366277458970227240571539258396554
+# MD5 Fingerprint: ac:fe:f7:34:96:a9:f2:b3:b4:12:4b:e4:27:41:6f:e1
+# SHA1 Fingerprint: a7:88:49:dc:5d:7c:75:8c:8c:de:39:98:56:b3:aa:d0:b2:a5:71:35
+# SHA256 Fingerprint: 37:1a:00:dc:05:33:b3:72:1a:7e:eb:40:e8:41:9e:70:79:9d:2b:0a:0f:2c:1d:80:69:31:65:f7:ce:c4:ad:75
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN
+MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT
+HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN
+NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs
+IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+
+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0
+2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp
+wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM
+pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD
+nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po
+sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx
+Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd
+Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX
+KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe
+XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL
+tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv
+TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
+AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw
+GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H
+PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF
+O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ
+REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik
+AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv
+/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+
+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw
+MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF
+qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK
+ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certainly Root R1 O=Certainly
+# Subject: CN=Certainly Root R1 O=Certainly
+# Label: "Certainly Root R1"
+# Serial: 188833316161142517227353805653483829216
+# MD5 Fingerprint: 07:70:d4:3e:82:87:a0:fa:33:36:13:f4:fa:33:e7:12
+# SHA1 Fingerprint: a0:50:ee:0f:28:71:f4:27:b2:12:6d:6f:50:96:25:ba:cc:86:42:af
+# SHA256 Fingerprint: 77:b8:2c:d8:64:4c:43:05:f7:ac:c5:cb:15:6b:45:67:50:04:03:3d:51:c6:0c:62:02:a8:e0:c3:34:67:d3:a0
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw
+PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy
+dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0
+YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2
+1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT
+vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed
+aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0
+1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5
+r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5
+cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ
+wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ
+6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA
+2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH
+Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR
+eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB
+/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u
+d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr
+PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d
+8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi
+1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd
+rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di
+taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7
+lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj
+yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn
+Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy
+yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n
+wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6
+OV+KmalBWQewLK8=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certainly Root E1 O=Certainly
+# Subject: CN=Certainly Root E1 O=Certainly
+# Label: "Certainly Root E1"
+# Serial: 8168531406727139161245376702891150584
+# MD5 Fingerprint: 0a:9e:ca:cd:3e:52:50:c6:36:f3:4b:a3:ed:a7:53:e9
+# SHA1 Fingerprint: f9:e1:6d:dc:01:89:cf:d5:82:45:63:3e:c5:37:7d:c2:eb:93:6f:2b
+# SHA256 Fingerprint: b4:58:5f:22:e4:ac:75:6a:4e:86:12:a1:36:1c:5d:9d:03:1a:93:fd:84:fe:bb:77:8f:a3:06:8b:0f:c4:2d:c2
+-----BEGIN CERTIFICATE-----
+MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw
+CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu
+bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ
+BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s
+eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK
++IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2
+QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4
+hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm
+ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG
+BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR
+-----END CERTIFICATE-----
+
+# Issuer: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD.
+# Subject: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD.
+# Label: "Security Communication ECC RootCA1"
+# Serial: 15446673492073852651
+# MD5 Fingerprint: 7e:43:b0:92:68:ec:05:43:4c:98:ab:5d:35:2e:7e:86
+# SHA1 Fingerprint: b8:0e:26:a9:bf:d2:b2:3b:c0:ef:46:c9:ba:c7:bb:f6:1d:0d:41:41
+# SHA256 Fingerprint: e7:4f:bd:a5:5b:d5:64:c4:73:a3:6b:44:1a:a7:99:c8:a6:8e:07:74:40:e8:28:8b:9f:a1:e5:0e:4b:ba:ca:11
+-----BEGIN CERTIFICATE-----
+MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT
+AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD
+VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx
+NjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoT
+HFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5
+IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+Cnnfdl
+dB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpK
+ULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu
+9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O
+be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k=
+-----END CERTIFICATE-----
+
+# Issuer: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY
+# Subject: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY
+# Label: "BJCA Global Root CA1"
+# Serial: 113562791157148395269083148143378328608
+# MD5 Fingerprint: 42:32:99:76:43:33:36:24:35:07:82:9b:28:f9:d0:90
+# SHA1 Fingerprint: d5:ec:8d:7b:4c:ba:79:f4:e7:e8:cb:9d:6b:ae:77:83:10:03:21:6a
+# SHA256 Fingerprint: f3:89:6f:88:fe:7c:0a:88:27:66:a7:fa:6a:d2:74:9f:b5:7a:7f:3e:98:fb:76:9c:1f:a7:b0:9c:2c:44:d5:ae
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU
+MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI
+T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz
+MTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJF
+SUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2Jh
+bCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3Z
+xRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZ
+spDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O5
+58dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgR
+at7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll
+5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4Tq
+nMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XK
+V0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/
+pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZO
+z2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXn
+jSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+
+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF
+7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4
+YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3Kli
+awLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u
++2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88
+X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkN
+SoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOo
+P2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI
++pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRz
+znfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9
+eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2
+YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy
+r/6zcCwupvI=
+-----END CERTIFICATE-----
+
+# Issuer: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY
+# Subject: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY
+# Label: "BJCA Global Root CA2"
+# Serial: 58605626836079930195615843123109055211
+# MD5 Fingerprint: 5e:0a:f6:47:5f:a6:14:e8:11:01:95:3f:4d:01:eb:3c
+# SHA1 Fingerprint: f4:27:86:eb:6e:b8:6d:88:31:67:02:fb:ba:66:a4:53:00:aa:7a:a6
+# SHA256 Fingerprint: 57:4d:f6:93:1e:27:80:39:66:7b:72:0a:fd:c1:60:0f:c2:7e:b6:6d:d3:09:29:79:fb:73:85:64:87:21:28:82
+-----BEGIN CERTIFICATE-----
+MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw
+CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ
+VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy
+MVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJ
+TkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBS
+b290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9B
+IgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK+
++kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJK
+sVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA
+94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B
+43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited
+# Subject: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited
+# Label: "Sectigo Public Server Authentication Root E46"
+# Serial: 88989738453351742415770396670917916916
+# MD5 Fingerprint: 28:23:f8:b2:98:5c:37:16:3b:3e:46:13:4e:b0:b3:01
+# SHA1 Fingerprint: ec:8a:39:6c:40:f0:2e:bc:42:75:d4:9f:ab:1c:1a:5b:67:be:d2:9a
+# SHA256 Fingerprint: c9:0f:26:f0:fb:1b:40:18:b2:22:27:51:9b:5c:a2:b5:3e:2c:a5:b3:be:5c:f1:8e:fe:1b:ef:47:38:0c:53:83
+-----BEGIN CERTIFICATE-----
+MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw
+CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T
+ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN
+MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG
+A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT
+ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC
+WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+
+6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B
+Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa
+qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q
+4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited
+# Subject: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited
+# Label: "Sectigo Public Server Authentication Root R46"
+# Serial: 156256931880233212765902055439220583700
+# MD5 Fingerprint: 32:10:09:52:00:d5:7e:6c:43:df:15:c0:b1:16:93:e5
+# SHA1 Fingerprint: ad:98:f9:f3:e4:7d:75:3b:65:d4:82:b3:a4:52:17:bb:6e:f5:e4:38
+# SHA256 Fingerprint: 7b:b6:47:a6:2a:ee:ac:88:bf:25:7a:a5:22:d0:1f:fe:a3:95:e0:ab:45:c7:3f:93:f6:56:54:ec:38:f2:5a:06
+-----BEGIN CERTIFICATE-----
+MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf
+MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
+Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
+HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY
+MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp
+YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa
+ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz
+SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf
+iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X
+ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3
+IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS
+VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE
+SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu
++Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt
+8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L
+HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt
+zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P
+AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c
+mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ
+YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52
+gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA
+Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB
+JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX
+DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui
+TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5
+dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65
+LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp
+0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY
+QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL
+-----END CERTIFICATE-----
+
+# Issuer: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation
+# Subject: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation
+# Label: "SSL.com TLS RSA Root CA 2022"
+# Serial: 148535279242832292258835760425842727825
+# MD5 Fingerprint: d8:4e:c6:59:30:d8:fe:a0:d6:7a:5a:2c:2c:69:78:da
+# SHA1 Fingerprint: ec:2c:83:40:72:af:26:95:10:ff:0e:f2:03:ee:31:70:f6:78:9d:ca
+# SHA256 Fingerprint: 8f:af:7d:2e:2c:b4:70:9b:b8:e0:b3:36:66:bf:75:a5:dd:45:b5:de:48:0f:8e:a8:d4:bf:e6:be:bc:17:f2:ed
+-----BEGIN CERTIFICATE-----
+MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO
+MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD
+DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX
+DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw
+b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC
+AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP
+L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY
+t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins
+S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3
+PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO
+L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3
+R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w
+dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS
++YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS
+d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG
+AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f
+gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
+BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z
+NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt
+hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM
+QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf
+R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ
+DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW
+P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy
+lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq
+bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w
+AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q
+r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji
+Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU
+98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA=
+-----END CERTIFICATE-----
+
+# Issuer: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation
+# Subject: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation
+# Label: "SSL.com TLS ECC Root CA 2022"
+# Serial: 26605119622390491762507526719404364228
+# MD5 Fingerprint: 99:d7:5c:f1:51:36:cc:e9:ce:d9:19:2e:77:71:56:c5
+# SHA1 Fingerprint: 9f:5f:d9:1a:54:6d:f5:0c:71:f0:ee:7a:bd:17:49:98:84:73:e2:39
+# SHA256 Fingerprint: c3:2f:fd:9f:46:f9:36:d1:6c:36:73:99:09:59:43:4b:9a:d6:0a:af:bb:9e:7c:f3:36:54:f1:44:cc:1b:a1:43
+-----BEGIN CERTIFICATE-----
+MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw
+CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT
+U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2
+MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh
+dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm
+acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN
+SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME
+GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW
+uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp
+15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN
+b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos
+# Subject: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos
+# Label: "Atos TrustedRoot Root CA ECC TLS 2021"
+# Serial: 81873346711060652204712539181482831616
+# MD5 Fingerprint: 16:9f:ad:f1:70:ad:79:d6:ed:29:b4:d1:c5:79:70:a8
+# SHA1 Fingerprint: 9e:bc:75:10:42:b3:02:f3:81:f4:f7:30:62:d4:8f:c3:a7:51:b2:dd
+# SHA256 Fingerprint: b2:fa:e5:3e:14:cc:d7:ab:92:12:06:47:01:ae:27:9c:1d:89:88:fa:cb:77:5f:a8:a0:08:91:4e:66:39:88:a8
+-----BEGIN CERTIFICATE-----
+MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w
+LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w
+CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0
+MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBF
+Q0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZI
+zj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/X
+tXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4
+AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2
+KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMD
+aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu
+CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo
+9H1/IISpQuQo
+-----END CERTIFICATE-----
+
+# Issuer: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos
+# Subject: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos
+# Label: "Atos TrustedRoot Root CA RSA TLS 2021"
+# Serial: 111436099570196163832749341232207667876
+# MD5 Fingerprint: d4:d3:46:b8:9a:c0:9c:76:5d:9e:3a:c3:b9:99:31:d2
+# SHA1 Fingerprint: 18:52:3b:0d:06:37:e4:d6:3a:df:23:e4:98:fb:5b:16:fb:86:74:48
+# SHA256 Fingerprint: 81:a9:08:8e:a5:9f:b3:64:c5:48:a6:f8:55:59:09:9b:6f:04:05:ef:bf:18:e5:32:4e:c9:f4:57:ba:00:11:2f
+-----BEGIN CERTIFICATE-----
+MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM
+MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx
+MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00
+MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBD
+QSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z
+4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYv
+Ye+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZ
+kmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDs
+GY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUln
+nkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh
+3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD
+0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzy
+geBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8
+ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezB
+c6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lI
+pw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
+dEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
+DAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS
+4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPs
+o0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJ
+qM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuyw
+xfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgM
+rr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4
+AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR
+0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuY
+o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5
+dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE
+oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=TrustAsia Global Root CA G3 O=TrustAsia Technologies, Inc.
+# Subject: CN=TrustAsia Global Root CA G3 O=TrustAsia Technologies, Inc.
+# Label: "TrustAsia Global Root CA G3"
+# Serial: 576386314500428537169965010905813481816650257167
+# MD5 Fingerprint: 30:42:1b:b7:bb:81:75:35:e4:16:4f:53:d2:94:de:04
+# SHA1 Fingerprint: 63:cf:b6:c1:27:2b:56:e4:88:8e:1c:23:9a:b6:2e:81:47:24:c3:c7
+# SHA256 Fingerprint: e0:d3:22:6a:eb:11:63:c2:e4:8f:f9:be:3b:50:b4:c6:43:1b:e7:bb:1e:ac:c5:c3:6b:5d:5e:c5:09:03:9a:08
+-----BEGIN CERTIFICATE-----
+MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEM
+BQAwWjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dp
+ZXMsIEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAe
+Fw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEwMTlaMFoxCzAJBgNVBAYTAkNOMSUw
+IwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtU
+cnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNS
+T1QY4SxzlZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqK
+AtCWHwDNBSHvBm3dIZwZQ0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1
+nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/VP68czH5GX6zfZBCK70bwkPAPLfSIC7Ep
+qq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1AgdB4SQXMeJNnKziyhWTXA
+yB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm9WAPzJMs
+hH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gX
+zhqcD0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAv
+kV34PmVACxmZySYgWmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msT
+f9FkPz2ccEblooV7WIQn3MSAPmeamseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jA
+uPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCFTIcQcf+eQxuulXUtgQIDAQAB
+o2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj7zjKsK5Xf/Ih
+MBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E
+BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4
+wM8zAQLpw6o1D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2
+XFNFV1pF1AWZLy4jVe5jaN/TG3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1
+JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNjduMNhXJEIlU/HHzp/LgV6FL6qj6j
+ITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstlcHboCoWASzY9M/eV
+VHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys+TIx
+xHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1on
+AX1daBli2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d
+7XB4tmBZrOFdRWOPyN9yaFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2Ntjj
+gKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsASZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV
++Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFRJQJ6+N1rZdVtTTDIZbpo
+FGWsJwt0ivKH
+-----END CERTIFICATE-----
+
+# Issuer: CN=TrustAsia Global Root CA G4 O=TrustAsia Technologies, Inc.
+# Subject: CN=TrustAsia Global Root CA G4 O=TrustAsia Technologies, Inc.
+# Label: "TrustAsia Global Root CA G4"
+# Serial: 451799571007117016466790293371524403291602933463
+# MD5 Fingerprint: 54:dd:b2:d7:5f:d8:3e:ed:7c:e0:0b:2e:cc:ed:eb:eb
+# SHA1 Fingerprint: 57:73:a5:61:5d:80:b2:e6:ac:38:82:fc:68:07:31:ac:9f:b5:92:5a
+# SHA256 Fingerprint: be:4b:56:cb:50:56:c0:13:6a:52:6d:f4:44:50:8d:aa:36:a0:b5:4f:42:e4:ac:38:f7:2a:f4:70:e4:79:65:4c
+-----BEGIN CERTIFICATE-----
+MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMw
+WjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs
+IEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0y
+MTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJaMFoxCzAJBgNVBAYTAkNOMSUwIwYD
+VQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtUcnVz
+dEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATx
+s8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbw
+LxYI+hW8m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJij
+YzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mD
+pm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/pDHel4NZg6ZvccveMA4GA1UdDwEB/wQE
+AwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AAbbd+NvBNEU/zy4k6LHiR
+UKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xkdUfFVZDj
+/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=CommScope Public Trust ECC Root-01 O=CommScope
+# Subject: CN=CommScope Public Trust ECC Root-01 O=CommScope
+# Label: "CommScope Public Trust ECC Root-01"
+# Serial: 385011430473757362783587124273108818652468453534
+# MD5 Fingerprint: 3a:40:a7:fc:03:8c:9c:38:79:2f:3a:a2:6c:b6:0a:16
+# SHA1 Fingerprint: 07:86:c0:d8:dd:8e:c0:80:98:06:98:d0:58:7a:ef:de:a6:cc:a2:5d
+# SHA256 Fingerprint: 11:43:7c:da:7b:b4:5e:41:36:5f:45:b3:9a:38:98:6b:0d:e0:0d:ef:34:8e:0c:7b:b0:87:36:33:80:0b:c3:8b
+-----BEGIN CERTIFICATE-----
+MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMw
+TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t
+bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNa
+Fw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv
+cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDEw
+djAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLxeP0C
+flfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJE
+hRGnSjot6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggq
+hkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg
+2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liWpDVfG2XqYZpwI7UNo5uS
+Um9poIyNStDuiw7LR47QjRE=
+-----END CERTIFICATE-----
+
+# Issuer: CN=CommScope Public Trust ECC Root-02 O=CommScope
+# Subject: CN=CommScope Public Trust ECC Root-02 O=CommScope
+# Label: "CommScope Public Trust ECC Root-02"
+# Serial: 234015080301808452132356021271193974922492992893
+# MD5 Fingerprint: 59:b0:44:d5:65:4d:b8:5c:55:19:92:02:b6:d1:94:b2
+# SHA1 Fingerprint: 3c:3f:ef:57:0f:fe:65:93:86:9e:a0:fe:b0:f6:ed:8e:d1:13:c7:e5
+# SHA256 Fingerprint: 2f:fb:7f:81:3b:bb:b3:c8:9a:b4:e8:16:2d:0f:16:d7:15:09:a8:30:cc:9d:73:c2:62:e5:14:08:75:d1:ad:4a
+-----BEGIN CERTIFICATE-----
+MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMw
+TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t
+bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRa
+Fw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv
+cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDIw
+djAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/MMDAL
+j2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmU
+v4RDsNuESgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggq
+hkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/n
+ich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs73u1Z/GtMMH9ZzkXpc2AV
+mkzw5l4lIhVtwodZ0LKOag==
+-----END CERTIFICATE-----
+
+# Issuer: CN=CommScope Public Trust RSA Root-01 O=CommScope
+# Subject: CN=CommScope Public Trust RSA Root-01 O=CommScope
+# Label: "CommScope Public Trust RSA Root-01"
+# Serial: 354030733275608256394402989253558293562031411421
+# MD5 Fingerprint: 0e:b4:15:bc:87:63:5d:5d:02:73:d4:26:38:68:73:d8
+# SHA1 Fingerprint: 6d:0a:5f:f7:b4:23:06:b4:85:b3:b7:97:64:fc:ac:75:f5:33:f2:93
+# SHA256 Fingerprint: 02:bd:f9:6e:2a:45:dd:9b:f1:8f:c7:e1:db:df:21:a0:37:9b:a3:c9:c2:61:03:44:cf:d8:d6:06:fe:c1:ed:81
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQEL
+BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi
+Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1
+NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t
+U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt
+MDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45FtnYSk
+YZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslh
+suitQDy6uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0al
+DrJLpA6lfO741GIDuZNqihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3Oj
+WiE260f6GBfZumbCk6SP/F2krfxQapWsvCQz0b2If4b19bJzKo98rwjyGpg/qYFl
+P8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/cZip8UlF1y5mO6D1cv547
+KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTifBSeolz7p
+UcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/
+kQO9lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JO
+Hg9O5j9ZpSPcPYeoKFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkB
+Ea801M/XrmLTBQe0MXXgDW1XT2mH+VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6U
+CBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm45P3luG0wDQYJ
+KoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6
+NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQ
+nmhUQo8mUuJM3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+
+QgvfKNmwrZggvkN80V4aCRckjXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2v
+trV0KnahP/t1MJ+UXjulYPPLXAziDslg+MkfFoom3ecnf+slpoq9uC02EJqxWE2a
+aE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/WNyVntHKLr4W96ioD
+j8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+o/E4
+Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0w
+lREQKC6/oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHn
+YfkUyq+Dj7+vsQpZXdxc1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVoc
+icCMb3SgazNNtQEo/a2tiRc7ppqEvOuM6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw
+-----END CERTIFICATE-----
+
+# Issuer: CN=CommScope Public Trust RSA Root-02 O=CommScope
+# Subject: CN=CommScope Public Trust RSA Root-02 O=CommScope
+# Label: "CommScope Public Trust RSA Root-02"
+# Serial: 480062499834624527752716769107743131258796508494
+# MD5 Fingerprint: e1:29:f9:62:7b:76:e2:96:6d:f3:d4:d7:0f:ae:1f:aa
+# SHA1 Fingerprint: ea:b0:e2:52:1b:89:93:4c:11:68:f2:d8:9a:ac:22:4c:a3:8a:57:ae
+# SHA256 Fingerprint: ff:e9:43:d7:93:42:4b:4f:7c:44:0c:1c:3d:64:8d:53:63:f3:4b:82:dc:87:aa:7a:9f:11:8f:c5:de:e1:01:f1
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQEL
+BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi
+Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2
+NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t
+U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt
+MDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3VrCLE
+NQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0
+kyI9p+Kx7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1C
+rWDaSWqVcN3SAOLMV2MCe5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxz
+hkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2WWy09X6GDRl224yW4fKcZgBzqZUPckXk2
+LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rpM9kzXzehxfCrPfp4sOcs
+n/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIfhs1w/tku
+FT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5
+kQMreyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3
+wNemKfrb3vOTlycEVS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6v
+wQcQeKwRoi9C8DfF8rhW3Q5iLc4tVn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs
+5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7GxcJXvYXowDQYJ
+KoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqB
+KCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3
++VGXu6TwYofF1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbyme
+APnCKfWxkxlSaRosTKCL4BWaMS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3Nyq
+pgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xdgSGn2rtO/+YHqP65DSdsu3BaVXoT
+6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2OHG1QAk8mGEPej1WF
+sQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+NmYWvt
+PjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2d
+lklyALKrdVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670
+v64fG9PiO/yzcnMcmyiQiRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17O
+rg3bhzjlP1v9mxnhMUF6cKojawHhRUzNlM47ni3niAIi9G7oyOzWPPO5std3eqx7
+-----END CERTIFICATE-----
+
+# Issuer: CN=Telekom Security TLS ECC Root 2020 O=Deutsche Telekom Security GmbH
+# Subject: CN=Telekom Security TLS ECC Root 2020 O=Deutsche Telekom Security GmbH
+# Label: "Telekom Security TLS ECC Root 2020"
+# Serial: 72082518505882327255703894282316633856
+# MD5 Fingerprint: c1:ab:fe:6a:10:2c:03:8d:bc:1c:22:32:c0:85:a7:fd
+# SHA1 Fingerprint: c0:f8:96:c5:a9:3b:01:06:21:07:da:18:42:48:bc:e9:9d:88:d5:ec
+# SHA256 Fingerprint: 57:8a:f4:de:d0:85:3f:4e:59:98:db:4a:ea:f9:cb:ea:8d:94:5f:60:b6:20:a3:8d:1a:3c:13:b2:bc:7b:a8:e1
+-----BEGIN CERTIFICATE-----
+MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQsw
+CQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBH
+bWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIw
+MB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIzNTk1OVowYzELMAkGA1UEBhMCREUx
+JzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkGA1UE
+AwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqGSM49
+AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/O
+tdKPD/M12kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDP
+f8iAC8GXs7s1J8nCG6NCMEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6f
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cA
+MGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZMo7k+5Dck2TOrbRBR2Di
+z6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdUga/sf+Rn
+27iQ7t0l
+-----END CERTIFICATE-----
+
+# Issuer: CN=Telekom Security TLS RSA Root 2023 O=Deutsche Telekom Security GmbH
+# Subject: CN=Telekom Security TLS RSA Root 2023 O=Deutsche Telekom Security GmbH
+# Label: "Telekom Security TLS RSA Root 2023"
+# Serial: 44676229530606711399881795178081572759
+# MD5 Fingerprint: bf:5b:eb:54:40:cd:48:71:c4:20:8d:7d:de:0a:42:f2
+# SHA1 Fingerprint: 54:d3:ac:b3:bd:57:56:f6:85:9d:ce:e5:c3:21:e2:d4:ad:83:d0:93
+# SHA256 Fingerprint: ef:c6:5c:ad:bb:59:ad:b6:ef:e8:4d:a2:23:11:b3:56:24:b7:1b:3b:1e:a0:da:8b:66:55:17:4e:c8:97:86:46
+-----BEGIN CERTIFICATE-----
+MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBj
+MQswCQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0
+eSBHbWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAy
+MDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMyNzIzNTk1OVowYzELMAkGA1UEBhMC
+REUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkG
+A1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9
+cUD/h3VCKSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHV
+cp6R+SPWcHu79ZvB7JPPGeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMA
+U6DksquDOFczJZSfvkgdmOGjup5czQRxUX11eKvzWarE4GC+j4NSuHUaQTXtvPM6
+Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWol8hHD/BeEIvnHRz+sTug
+BTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9FIS3R/qy
+8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73J
+co4vzLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg
+8qKrBC7m8kwOFjQgrIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8
+rFEz0ciD0cmfHdRHNCk+y7AO+oMLKFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12
+mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7SWWO/gLCMk3PLNaaZlSJhZQNg
++y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtqeX
+gj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2
+p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQ
+pGv7qHBFfLp+sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm
+9S3ul0A8Yute1hTWjOKWi0FpkzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErw
+M807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy/SKE8YXJN3nptT+/XOR0so8RYgDd
+GGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4mZqTuXNnQkYRIer+
+CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtzaL1t
+xKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+
+w6jv/naaoqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aK
+L4x35bcF7DvB7L6Gs4a8wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+lj
+X273CXE2whJdV/LItM3z7gLfEdxquVeEHVlNjM7IDiPCtyaaEBRx/pOyiriA8A4Q
+ntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0o82bNSQ3+pCTE4FCxpgm
+dTdmQRCsu/WU48IxK63nI1bMNSWSs1A=
+-----END CERTIFICATE-----
+
+# Issuer: CN=FIRMAPROFESIONAL CA ROOT-A WEB O=Firmaprofesional SA
+# Subject: CN=FIRMAPROFESIONAL CA ROOT-A WEB O=Firmaprofesional SA
+# Label: "FIRMAPROFESIONAL CA ROOT-A WEB"
+# Serial: 65916896770016886708751106294915943533
+# MD5 Fingerprint: 82:b2:ad:45:00:82:b0:66:63:f8:5f:c3:67:4e:ce:a3
+# SHA1 Fingerprint: a8:31:11:74:a6:14:15:0d:ca:77:dd:0e:e4:0c:5d:58:fc:a0:72:a5
+# SHA256 Fingerprint: be:f2:56:da:f2:6e:9c:69:bd:ec:16:02:35:97:98:f3:ca:f7:18:21:a0:3e:01:82:57:c5:3c:65:61:7f:3d:4a
+-----BEGIN CERTIFICATE-----
+MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQsw
+CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE
+YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB
+IFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2WhcNNDcwMzMxMDkwMTM2WjBuMQsw
+CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE
+YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB
+IFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zf
+e9MEkVz6iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6C
+cyvHZpsKjECcfIr28jlgst7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB
+/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FDY1w8ndYn81LsF7Kpryz3dvgwHQYDVR0O
+BBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO
+PQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgLcFBTApFw
+hVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dG
+XSaQpYXFuXqUPoeovQA=
+-----END CERTIFICATE-----
+
+# Issuer: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA
+# Subject: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA
+# Label: "TWCA CYBER Root CA"
+# Serial: 85076849864375384482682434040119489222
+# MD5 Fingerprint: 0b:33:a0:97:52:95:d4:a9:fd:bb:db:6e:a3:55:5b:51
+# SHA1 Fingerprint: f6:b1:1c:1a:83:38:e9:7b:db:b3:a8:c8:33:24:e0:2d:9c:7f:26:66
+# SHA256 Fingerprint: 3f:63:bb:28:14:be:17:4e:c8:b6:43:9c:f0:8d:6d:56:f0:b7:c4:05:88:3a:56:48:a3:34:42:4d:6b:3e:c5:58
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQ
+MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290
+IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5
+WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FO
+LUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3Qg
+Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1sTs6P
+40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxF
+avcokPFhV8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/
+34bKS1PE2Y2yHer43CdTo0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684i
+JkXXYJndzk834H/nY62wuFm40AZoNWDTNq5xQwTxaWV4fPMf88oon1oglWa0zbfu
+j3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK/c/WMw+f+5eesRycnupf
+Xtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkHIuNZW0CP
+2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDA
+S9TMfAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDA
+oS/xUgXJP+92ZuJF2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzC
+kHDXShi8fgGwsOsVHkQGzaRP6AzRwyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW
+5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83QOGt4A1WNzAd
+BgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB
+AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0t
+tGlTITVX1olNc79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn
+68xDiBaiA9a5F/gZbG0jAn/xX9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNn
+TKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDRIG4kqIQnoVesqlVYL9zZyvpoBJ7t
+RCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq/p1hvIbZv97Tujqx
+f36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0RFxbI
+Qh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz
+8ppy6rBePm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4
+NxKfKjLji7gh7MMrZQzvIt6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzX
+xeSDwWrruoBa3lwtcHb4yOWHh8qgnaHlIhInD0Q9HWzq1MKLL295q39QpsQZp6F6
+t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd.
+# Subject: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd.
+# Label: "SecureSign Root CA12"
+# Serial: 587887345431707215246142177076162061960426065942
+# MD5 Fingerprint: c6:89:ca:64:42:9b:62:08:49:0b:1e:7f:e9:07:3d:e8
+# SHA1 Fingerprint: 7a:22:1e:3d:de:1b:06:ac:9e:c8:47:70:16:8e:3c:e5:f7:6b:06:f4
+# SHA256 Fingerprint: 3f:03:4b:b5:70:4d:44:b2:d0:85:45:a0:20:57:de:93:eb:f3:90:5f:ce:72:1a:cb:c7:30:c0:6d:da:ee:90:4e
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQEL
+BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u
+LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgw
+NTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD
+eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS
+b290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3emhF
+KxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mt
+p7JIKwccJ/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zd
+J1M3s6oYwlkm7Fsf0uZlfO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gur
+FzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBFEaCeVESE99g2zvVQR9wsMJvuwPWW0v4J
+hscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1UefNzFJM3IFTQy2VYzxV4+K
+h9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsF
+AAOCAQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6Ld
+mmQOmFxv3Y67ilQiLUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJ
+mBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA
+8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPSvWKErI4cqc1avTc7bgoitPQV
+55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/
+yOPiZwud9AzqVN/Ssq+xIvEg37xEHA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd.
+# Subject: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd.
+# Label: "SecureSign Root CA14"
+# Serial: 575790784512929437950770173562378038616896959179
+# MD5 Fingerprint: 71:0d:72:fa:92:19:65:5e:89:04:ac:16:33:f0:bc:d5
+# SHA1 Fingerprint: dd:50:c0:f7:79:b3:64:2e:74:a2:b8:9d:9f:d3:40:dd:bb:f0:f2:4f
+# SHA256 Fingerprint: 4b:00:9c:10:34:49:4f:9a:b5:6b:ba:3b:a1:d6:27:31:fc:4d:20:d8:95:5a:dc:ec:10:a9:25:60:72:61:e3:38
+-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEM
+BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u
+LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgw
+NzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD
+eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS
+b290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh1oq/
+FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOg
+vlIfX8xnbacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy
+6pJxaeQp8E+BgQQ8sqVb1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo
+/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9J
+kdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOEkJTRX45zGRBdAuVwpcAQ
+0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSxjVIHvXib
+y8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac
+18izju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs
+0Wq2XSqypWa9a4X0dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIAB
+SMbHdPTGrMNASRZhdCyvjG817XsYAFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVL
+ApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeqYR3r6/wtbyPk
+86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E
+rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ib
+ed87hwriZLoAymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopT
+zfFP7ELyk+OZpDc8h7hi2/DsHzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHS
+DCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPGFrojutzdfhrGe0K22VoF3Jpf1d+4
+2kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6qnsb58Nn4DSEC5MUo
+FlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/OfVy
+K4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6
+dB7h7sxaOgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtl
+Lor6CZpO2oYofaphNdgOpygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB
+365jJ6UeTo3cKXhZ+PmhIIynJkBugnLNeLLIjzwec+fBH7/PzqUqm9tEZDKgu39c
+JRNItX+S
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd.
+# Subject: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd.
+# Label: "SecureSign Root CA15"
+# Serial: 126083514594751269499665114766174399806381178503
+# MD5 Fingerprint: 13:30:fc:c4:62:a6:a9:de:b5:c1:68:af:b5:d2:31:47
+# SHA1 Fingerprint: cb:ba:83:c8:c1:5a:5d:f1:f9:73:6f:ca:d7:ef:28:13:06:4a:07:7d
+# SHA256 Fingerprint: e7:78:f0:f0:95:fe:84:37:29:cd:1a:00:82:17:9e:53:14:a9:c2:91:44:28:05:e1:fb:1d:8f:b6:b8:88:6c:3a
+-----BEGIN CERTIFICATE-----
+MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMw
+UTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBM
+dGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMy
+NTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJl
+cnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290
+IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5GdCx4
+wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSR
+ZHX+AezB2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT
+9DAKBggqhkjOPQQDAwNoADBlAjEA2S6Jfl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp
+4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJSwdLZrWeqrqgHkHZAXQ6
+bkU6iYAZezKYVWOr62Nuk22rGwlgMU4=
+-----END CERTIFICATE-----
+
+# Issuer: CN=D-TRUST BR Root CA 2 2023 O=D-Trust GmbH
+# Subject: CN=D-TRUST BR Root CA 2 2023 O=D-Trust GmbH
+# Label: "D-TRUST BR Root CA 2 2023"
+# Serial: 153168538924886464690566649552453098598
+# MD5 Fingerprint: e1:09:ed:d3:60:d4:56:1b:47:1f:b7:0c:5f:1b:5f:85
+# SHA1 Fingerprint: 2d:b0:70:ee:71:94:af:69:68:17:db:79:ce:58:9f:a0:6b:96:f7:87
+# SHA256 Fingerprint: 05:52:e6:f8:3f:df:65:e8:fa:96:70:e6:66:df:28:a4:e2:13:40:b5:10:cb:e5:25:66:f9:7c:4f:b9:4b:2b:d1
+-----BEGIN CERTIFICATE-----
+MIIFqTCCA5GgAwIBAgIQczswBEhb2U14LnNLyaHcZjANBgkqhkiG9w0BAQ0FADBI
+MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE
+LVRSVVNUIEJSIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA4NTYzMVoXDTM4MDUw
+OTA4NTYzMFowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi
+MCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBAK7/CVmRgApKaOYkP7in5Mg6CjoWzckjYaCTcfKr
+i3OPoGdlYNJUa2NRb0kz4HIHE304zQaSBylSa053bATTlfrdTIzZXcFhfUvnKLNE
+gXtRr90zsWh81k5M/itoucpmacTsXld/9w3HnDY25QdgrMBM6ghs7wZ8T1soegj8
+k12b9py0i4a6Ibn08OhZWiihNIQaJZG2tY/vsvmA+vk9PBFy2OMvhnbFeSzBqZCT
+Rphny4NqoFAjpzv2gTng7fC5v2Xx2Mt6++9zA84A9H3X4F07ZrjcjrqDy4d2A/wl
+2ecjbwb9Z/Pg/4S8R7+1FhhGaRTMBffb00msa8yr5LULQyReS2tNZ9/WtT5PeB+U
+cSTq3nD88ZP+npNa5JRal1QMNXtfbO4AHyTsA7oC9Xb0n9Sa7YUsOCIvx9gvdhFP
+/Wxc6PWOJ4d/GUohR5AdeY0cW/jPSoXk7bNbjb7EZChdQcRurDhaTyN0dKkSw/bS
+uREVMweR2Ds3OmMwBtHFIjYoYiMQ4EbMl6zWK11kJNXuHA7e+whadSr2Y23OC0K+
+0bpwHJwh5Q8xaRfX/Aq03u2AnMuStIv13lmiWAmlY0cL4UEyNEHZmrHZqLAbWt4N
+DfTisl01gLmB1IRpkQLLddCNxbU9CZEJjxShFHR5PtbJFR2kWVki3PaKRT08EtY+
+XTIvAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUZ5Dw1t61
+GNVGKX5cq/ieCLxklRAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG
+OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfYnJfcm9vdF9jYV8y
+XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQA097N3U9swFrktpSHxQCF16+tI
+FoE9c+CeJyrrd6kTpGoKWloUMz1oH4Guaf2Mn2VsNELZLdB/eBaxOqwjMa1ef67n
+riv6uvw8l5VAk1/DLQOj7aRvU9f6QA4w9QAgLABMjDu0ox+2v5Eyq6+SmNMW5tTR
+VFxDWy6u71cqqLRvpO8NVhTaIasgdp4D/Ca4nj8+AybmTNudX0KEPUUDAxxZiMrc
+LmEkWqTqJwtzEr5SswrPMhfiHocaFpVIbVrg0M8JkiZmkdijYQ6qgYF/6FKC0ULn
+4B0Y+qSFNueG4A3rvNTJ1jxD8V1Jbn6Bm2m1iWKPiFLY1/4nwSPFyysCu7Ff/vtD
+hQNGvl3GyiEm/9cCnnRK3PgTFbGBVzbLZVzRHTF36SXDw7IyN9XxmAnkbWOACKsG
+koHU6XCPpz+y7YaMgmo1yEJagtFSGkUPFaUA8JR7ZSdXOUPPfH/mvTWze/EZTN46
+ls/pdu4D58JDUjxqgejBWoC9EV2Ta/vH5mQ/u2kc6d0li690yVRAysuTEwrt+2aS
+Ecr1wPrYg1UDfNPFIkZ1cGt5SAYqgpq/5usWDiJFAbzdNpQ0qTUmiteXue4Icr80
+knCDgKs4qllo3UCkGJCy89UDyibK79XH4I9TjvAA46jtn/mtd+ArY0+ew+43u3gJ
+hJ65bvspmZDogNOfJA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=D-TRUST EV Root CA 2 2023 O=D-Trust GmbH
+# Subject: CN=D-TRUST EV Root CA 2 2023 O=D-Trust GmbH
+# Label: "D-TRUST EV Root CA 2 2023"
+# Serial: 139766439402180512324132425437959641711
+# MD5 Fingerprint: 96:b4:78:09:f0:09:cb:77:eb:bb:1b:4d:6f:36:bc:b6
+# SHA1 Fingerprint: a5:5b:d8:47:6c:8f:19:f7:4c:f4:6d:6b:b6:c2:79:82:22:df:54:8b
+# SHA256 Fingerprint: 8e:82:21:b2:e7:d4:00:78:36:a1:67:2f:0d:cc:29:9c:33:bc:07:d3:16:f1:32:fa:1a:20:6d:58:71:50:f1:ce
+-----BEGIN CERTIFICATE-----
+MIIFqTCCA5GgAwIBAgIQaSYJfoBLTKCnjHhiU19abzANBgkqhkiG9w0BAQ0FADBI
+MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE
+LVRSVVNUIEVWIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA5MTAzM1oXDTM4MDUw
+OTA5MTAzMlowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi
+MCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBANiOo4mAC7JXUtypU0w3uX9jFxPvp1sjW2l1sJkK
+F8GLxNuo4MwxusLyzV3pt/gdr2rElYfXR8mV2IIEUD2BCP/kPbOx1sWy/YgJ25yE
+7CUXFId/MHibaljJtnMoPDT3mfd/06b4HEV8rSyMlD/YZxBTfiLNTiVR8CUkNRFe
+EMbsh2aJgWi6zCudR3Mfvc2RpHJqnKIbGKBv7FD0fUDCqDDPvXPIEysQEx6Lmqg6
+lHPTGGkKSv/BAQP/eX+1SH977ugpbzZMlWGG2Pmic4ruri+W7mjNPU0oQvlFKzIb
+RlUWaqZLKfm7lVa/Rh3sHZMdwGWyH6FDrlaeoLGPaxK3YG14C8qKXO0elg6DpkiV
+jTujIcSuWMYAsoS0I6SWhjW42J7YrDRJmGOVxcttSEfi8i4YHtAxq9107PncjLgc
+jmgjutDzUNzPZY9zOjLHfP7KgiJPvo5iR2blzYfi6NUPGJ/lBHJLRjwQ8kTCZFZx
+TnXonMkmdMV9WdEKWw9t/p51HBjGGjp82A0EzM23RWV6sY+4roRIPrN6TagD4uJ+
+ARZZaBhDM7DS3LAaQzXupdqpRlyuhoFBAUp0JuyfBr/CBTdkdXgpaP3F9ev+R/nk
+hbDhezGdpn9yo7nELC7MmVcOIQxFAZRl62UJxmMiCzNJkkg8/M3OsD6Onov4/knF
+NXJHAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqvyREBuH
+kV8Wub9PS5FeAByxMoAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG
+OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfZXZfcm9vdF9jYV8y
+XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQCTy6UfmRHsmg1fLBWTxj++EI14
+QvBukEdHjqOSMo1wj/Zbjb6JzkcBahsgIIlbyIIQbODnmaprxiqgYzWRaoUlrRc4
+pZt+UPJ26oUFKidBK7GB0aL2QHWpDsvxVUjY7NHss+jOFKE17MJeNRqrphYBBo7q
+3C+jisosketSjl8MmxfPy3MHGcRqwnNU73xDUmPBEcrCRbH0O1P1aa4846XerOhU
+t7KR/aypH/KH5BfGSah82ApB9PI+53c0BFLd6IHyTS9URZ0V4U/M5d40VxDJI3IX
+cI1QcB9WbMy5/zpaT2N6w25lBx2Eof+pDGOJbbJAiDnXH3dotfyc1dZnaVuodNv8
+ifYbMvekJKZ2t0dT741Jj6m2g1qllpBFYfXeA08mD6iL8AOWsKwV0HFaanuU5nCT
+2vFp4LJiTZ6P/4mdm13NRemUAiKN4DV/6PEEeXFsVIP4M7kFMhtYVRFP0OUnR3Hs
+7dpn1mKmS00PaaLJvOwiS5THaJQXfuKOKD62xur1NGyfN4gHONuGcfrNlUhDbqNP
+gofXNJhuS5N5YHVpD/Aa1VP6IQzCP+k/HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAst
+Nl7F6cTVg8uGF5csbBNvh1qvSaYd2804BC5f4ko1Di1L+KIkBI3Y4WNeApI02phh
+XBxvWHZks/wCuPWdCg==
+-----END CERTIFICATE-----
diff --git a/testcline/lib/python3.12/site-packages/certifi/core.py b/testcline/lib/python3.12/site-packages/certifi/core.py
new file mode 100644
index 0000000..91f538b
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/certifi/core.py
@@ -0,0 +1,114 @@
+"""
+certifi.py
+~~~~~~~~~~
+
+This module returns the installation location of cacert.pem or its contents.
+"""
+import sys
+import atexit
+
+def exit_cacert_ctx() -> None:
+ _CACERT_CTX.__exit__(None, None, None) # type: ignore[union-attr]
+
+
+if sys.version_info >= (3, 11):
+
+ from importlib.resources import as_file, files
+
+ _CACERT_CTX = None
+ _CACERT_PATH = None
+
+ def where() -> str:
+ # This is slightly terrible, but we want to delay extracting the file
+ # in cases where we're inside of a zipimport situation until someone
+ # actually calls where(), but we don't want to re-extract the file
+ # on every call of where(), so we'll do it once then store it in a
+ # global variable.
+ global _CACERT_CTX
+ global _CACERT_PATH
+ if _CACERT_PATH is None:
+ # This is slightly janky, the importlib.resources API wants you to
+ # manage the cleanup of this file, so it doesn't actually return a
+ # path, it returns a context manager that will give you the path
+ # when you enter it and will do any cleanup when you leave it. In
+ # the common case of not needing a temporary file, it will just
+ # return the file system location and the __exit__() is a no-op.
+ #
+ # We also have to hold onto the actual context manager, because
+ # it will do the cleanup whenever it gets garbage collected, so
+ # we will also store that at the global level as well.
+ _CACERT_CTX = as_file(files("certifi").joinpath("cacert.pem"))
+ _CACERT_PATH = str(_CACERT_CTX.__enter__())
+ atexit.register(exit_cacert_ctx)
+
+ return _CACERT_PATH
+
+ def contents() -> str:
+ return files("certifi").joinpath("cacert.pem").read_text(encoding="ascii")
+
+elif sys.version_info >= (3, 7):
+
+ from importlib.resources import path as get_path, read_text
+
+ _CACERT_CTX = None
+ _CACERT_PATH = None
+
+ def where() -> str:
+ # This is slightly terrible, but we want to delay extracting the
+ # file in cases where we're inside of a zipimport situation until
+ # someone actually calls where(), but we don't want to re-extract
+ # the file on every call of where(), so we'll do it once then store
+ # it in a global variable.
+ global _CACERT_CTX
+ global _CACERT_PATH
+ if _CACERT_PATH is None:
+ # This is slightly janky, the importlib.resources API wants you
+ # to manage the cleanup of this file, so it doesn't actually
+ # return a path, it returns a context manager that will give
+ # you the path when you enter it and will do any cleanup when
+ # you leave it. In the common case of not needing a temporary
+ # file, it will just return the file system location and the
+ # __exit__() is a no-op.
+ #
+ # We also have to hold onto the actual context manager, because
+ # it will do the cleanup whenever it gets garbage collected, so
+ # we will also store that at the global level as well.
+ _CACERT_CTX = get_path("certifi", "cacert.pem")
+ _CACERT_PATH = str(_CACERT_CTX.__enter__())
+ atexit.register(exit_cacert_ctx)
+
+ return _CACERT_PATH
+
+ def contents() -> str:
+ return read_text("certifi", "cacert.pem", encoding="ascii")
+
+else:
+ import os
+ import types
+ from typing import Union
+
+ Package = Union[types.ModuleType, str]
+ Resource = Union[str, "os.PathLike"]
+
+ # This fallback will work for Python versions prior to 3.7 that lack the
+ # importlib.resources module but relies on the existing `where` function
+ # so won't address issues with environments like PyOxidizer that don't set
+ # __file__ on modules.
+ def read_text(
+ package: Package,
+ resource: Resource,
+ encoding: str = 'utf-8',
+ errors: str = 'strict'
+ ) -> str:
+ with open(where(), encoding=encoding) as data:
+ return data.read()
+
+ # If we don't have importlib.resources, then we will just do the old logic
+ # of assuming we're on the filesystem and munge the path directly.
+ def where() -> str:
+ f = os.path.dirname(__file__)
+
+ return os.path.join(f, "cacert.pem")
+
+ def contents() -> str:
+ return read_text("certifi", "cacert.pem", encoding="ascii")
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/__init__.py b/testcline/lib/python3.12/site-packages/certifi/py.typed
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/__init__.py
rename to testcline/lib/python3.12/site-packages/certifi/py.typed
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/LICENSE
new file mode 100644
index 0000000..9725772
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 TAHRI Ahmed R.
+
+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/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/METADATA b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/METADATA
new file mode 100644
index 0000000..58f3667
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/METADATA
@@ -0,0 +1,721 @@
+Metadata-Version: 2.1
+Name: charset-normalizer
+Version: 3.4.1
+Summary: The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet.
+Author-email: "Ahmed R. TAHRI"
+Maintainer-email: "Ahmed R. TAHRI"
+License: MIT
+Project-URL: Changelog, https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md
+Project-URL: Documentation, https://charset-normalizer.readthedocs.io/
+Project-URL: Code, https://github.com/jawah/charset_normalizer
+Project-URL: Issue tracker, https://github.com/jawah/charset_normalizer/issues
+Keywords: encoding,charset,charset-detector,detector,normalization,unicode,chardet,detect
+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
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Text Processing :: Linguistic
+Classifier: Topic :: Utilities
+Classifier: Typing :: Typed
+Requires-Python: >=3.7
+Description-Content-Type: text/markdown
+License-File: LICENSE
+Provides-Extra: unicode-backport
+
+Charset Detection, for Everyone 👋
+
+
+ The Real First Universal Charset Detector
+
+
+
+
+
+
+
+
+
+
+
+ Featured Packages
+
+
+
+
+
+
+
+
+ In other language (unofficial port - by the community)
+
+
+
+
+
+> A library that helps you read text from an unknown charset encoding.
Motivated by `chardet`,
+> I'm trying to resolve the issue by taking a new approach.
+> All IANA character set names for which the Python core library provides codecs are supported.
+
+
+ >>>>> 👉 Try Me Online Now, Then Adopt Me 👈 <<<<<
+
+
+This project offers you an alternative to **Universal Charset Encoding Detector**, also known as **Chardet**.
+
+| Feature | [Chardet](https://github.com/chardet/chardet) | Charset Normalizer | [cChardet](https://github.com/PyYoshi/cChardet) |
+|--------------------------------------------------|:---------------------------------------------:|:--------------------------------------------------------------------------------------------------:|:-----------------------------------------------:|
+| `Fast` | ❌ | ✅ | ✅ |
+| `Universal**` | ❌ | ✅ | ❌ |
+| `Reliable` **without** distinguishable standards | ❌ | ✅ | ✅ |
+| `Reliable` **with** distinguishable standards | ✅ | ✅ | ✅ |
+| `License` | LGPL-2.1
_restrictive_ | MIT | MPL-1.1
_restrictive_ |
+| `Native Python` | ✅ | ✅ | ❌ |
+| `Detect spoken language` | ❌ | ✅ | N/A |
+| `UnicodeDecodeError Safety` | ❌ | ✅ | ❌ |
+| `Whl Size (min)` | 193.6 kB | 42 kB | ~200 kB |
+| `Supported Encoding` | 33 | 🎉 [99](https://charset-normalizer.readthedocs.io/en/latest/user/support.html#supported-encodings) | 40 |
+
+
+
+
+
+*\*\* : They are clearly using specific code for a specific encoding even if covering most of used one*
+
+## ⚡ Performance
+
+This package offer better performance than its counterpart Chardet. Here are some numbers.
+
+| Package | Accuracy | Mean per file (ms) | File per sec (est) |
+|-----------------------------------------------|:--------:|:------------------:|:------------------:|
+| [chardet](https://github.com/chardet/chardet) | 86 % | 63 ms | 16 file/sec |
+| charset-normalizer | **98 %** | **10 ms** | 100 file/sec |
+
+| Package | 99th percentile | 95th percentile | 50th percentile |
+|-----------------------------------------------|:---------------:|:---------------:|:---------------:|
+| [chardet](https://github.com/chardet/chardet) | 265 ms | 71 ms | 7 ms |
+| charset-normalizer | 100 ms | 50 ms | 5 ms |
+
+_updated as of december 2024 using CPython 3.12_
+
+Chardet's performance on larger file (1MB+) are very poor. Expect huge difference on large payload.
+
+> Stats are generated using 400+ files using default parameters. More details on used files, see GHA workflows.
+> And yes, these results might change at any time. The dataset can be updated to include more files.
+> The actual delays heavily depends on your CPU capabilities. The factors should remain the same.
+> Keep in mind that the stats are generous and that Chardet accuracy vs our is measured using Chardet initial capability
+> (e.g. Supported Encoding) Challenge-them if you want.
+
+## ✨ Installation
+
+Using pip:
+
+```sh
+pip install charset-normalizer -U
+```
+
+## 🚀 Basic Usage
+
+### CLI
+This package comes with a CLI.
+
+```
+usage: normalizer [-h] [-v] [-a] [-n] [-m] [-r] [-f] [-t THRESHOLD]
+ file [file ...]
+
+The Real First Universal Charset Detector. Discover originating encoding used
+on text file. Normalize text to unicode.
+
+positional arguments:
+ files File(s) to be analysed
+
+optional arguments:
+ -h, --help show this help message and exit
+ -v, --verbose Display complementary information about file if any.
+ Stdout will contain logs about the detection process.
+ -a, --with-alternative
+ Output complementary possibilities if any. Top-level
+ JSON WILL be a list.
+ -n, --normalize Permit to normalize input file. If not set, program
+ does not write anything.
+ -m, --minimal Only output the charset detected to STDOUT. Disabling
+ JSON output.
+ -r, --replace Replace file when trying to normalize it instead of
+ creating a new one.
+ -f, --force Replace file without asking if you are sure, use this
+ flag with caution.
+ -t THRESHOLD, --threshold THRESHOLD
+ Define a custom maximum amount of chaos allowed in
+ decoded content. 0. <= chaos <= 1.
+ --version Show version information and exit.
+```
+
+```bash
+normalizer ./data/sample.1.fr.srt
+```
+
+or
+
+```bash
+python -m charset_normalizer ./data/sample.1.fr.srt
+```
+
+🎉 Since version 1.4.0 the CLI produce easily usable stdout result in JSON format.
+
+```json
+{
+ "path": "/home/default/projects/charset_normalizer/data/sample.1.fr.srt",
+ "encoding": "cp1252",
+ "encoding_aliases": [
+ "1252",
+ "windows_1252"
+ ],
+ "alternative_encodings": [
+ "cp1254",
+ "cp1256",
+ "cp1258",
+ "iso8859_14",
+ "iso8859_15",
+ "iso8859_16",
+ "iso8859_3",
+ "iso8859_9",
+ "latin_1",
+ "mbcs"
+ ],
+ "language": "French",
+ "alphabets": [
+ "Basic Latin",
+ "Latin-1 Supplement"
+ ],
+ "has_sig_or_bom": false,
+ "chaos": 0.149,
+ "coherence": 97.152,
+ "unicode_path": null,
+ "is_preferred": true
+}
+```
+
+### Python
+*Just print out normalized text*
+```python
+from charset_normalizer import from_path
+
+results = from_path('./my_subtitle.srt')
+
+print(str(results.best()))
+```
+
+*Upgrade your code without effort*
+```python
+from charset_normalizer import detect
+```
+
+The above code will behave the same as **chardet**. We ensure that we offer the best (reasonable) BC result possible.
+
+See the docs for advanced usage : [readthedocs.io](https://charset-normalizer.readthedocs.io/en/latest/)
+
+## 😇 Why
+
+When I started using Chardet, I noticed that it was not suited to my expectations, and I wanted to propose a
+reliable alternative using a completely different method. Also! I never back down on a good challenge!
+
+I **don't care** about the **originating charset** encoding, because **two different tables** can
+produce **two identical rendered string.**
+What I want is to get readable text, the best I can.
+
+In a way, **I'm brute forcing text decoding.** How cool is that ? 😎
+
+Don't confuse package **ftfy** with charset-normalizer or chardet. ftfy goal is to repair Unicode string whereas charset-normalizer to convert raw file in unknown encoding to unicode.
+
+## 🍰 How
+
+ - Discard all charset encoding table that could not fit the binary content.
+ - Measure noise, or the mess once opened (by chunks) with a corresponding charset encoding.
+ - Extract matches with the lowest mess detected.
+ - Additionally, we measure coherence / probe for a language.
+
+**Wait a minute**, what is noise/mess and coherence according to **YOU ?**
+
+*Noise :* I opened hundred of text files, **written by humans**, with the wrong encoding table. **I observed**, then
+**I established** some ground rules about **what is obvious** when **it seems like** a mess (aka. defining noise in rendered text).
+ I know that my interpretation of what is noise is probably incomplete, feel free to contribute in order to
+ improve or rewrite it.
+
+*Coherence :* For each language there is on earth, we have computed ranked letter appearance occurrences (the best we can). So I thought
+that intel is worth something here. So I use those records against decoded text to check if I can detect intelligent design.
+
+## ⚡ Known limitations
+
+ - Language detection is unreliable when text contains two or more languages sharing identical letters. (eg. HTML (english tags) + Turkish content (Sharing Latin characters))
+ - Every charset detector heavily depends on sufficient content. In common cases, do not bother run detection on very tiny content.
+
+## ⚠️ About Python EOLs
+
+**If you are running:**
+
+- Python >=2.7,<3.5: Unsupported
+- Python 3.5: charset-normalizer < 2.1
+- Python 3.6: charset-normalizer < 3.1
+- Python 3.7: charset-normalizer < 4.0
+
+Upgrade your Python interpreter as soon as possible.
+
+## 👤 Contributing
+
+Contributions, issues and feature requests are very much welcome.
+Feel free to check [issues page](https://github.com/ousret/charset_normalizer/issues) if you want to contribute.
+
+## 📝 License
+
+Copyright © [Ahmed TAHRI @Ousret](https://github.com/Ousret).
+This project is [MIT](https://github.com/Ousret/charset_normalizer/blob/master/LICENSE) licensed.
+
+Characters frequencies used in this project © 2012 [Denny Vrandečić](http://simia.net/letters/)
+
+## 💼 For Enterprise
+
+Professional support for charset-normalizer is available as part of the [Tidelift
+Subscription][1]. Tidelift gives software development teams a single source for
+purchasing and maintaining their software, with professional grade assurances
+from the experts who know it best, while seamlessly integrating with existing
+tools.
+
+[1]: https://tidelift.com/subscription/pkg/pypi-charset-normalizer?utm_source=pypi-charset-normalizer&utm_medium=readme
+
+[](https://www.bestpractices.dev/projects/7297)
+
+# Changelog
+All notable changes to charset-normalizer will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+
+## [3.4.1](https://github.com/Ousret/charset_normalizer/compare/3.4.0...3.4.1) (2024-12-24)
+
+### Changed
+- Project metadata are now stored using `pyproject.toml` instead of `setup.cfg` using setuptools as the build backend.
+- Enforce annotation delayed loading for a simpler and consistent types in the project.
+- Optional mypyc compilation upgraded to version 1.14 for Python >= 3.8
+
+### Added
+- pre-commit configuration.
+- noxfile.
+
+### Removed
+- `build-requirements.txt` as per using `pyproject.toml` native build configuration.
+- `bin/integration.py` and `bin/serve.py` in favor of downstream integration test (see noxfile).
+- `setup.cfg` in favor of `pyproject.toml` metadata configuration.
+- Unused `utils.range_scan` function.
+
+### Fixed
+- Converting content to Unicode bytes may insert `utf_8` instead of preferred `utf-8`. (#572)
+- Deprecation warning "'count' is passed as positional argument" when converting to Unicode bytes on Python 3.13+
+
+## [3.4.0](https://github.com/Ousret/charset_normalizer/compare/3.3.2...3.4.0) (2024-10-08)
+
+### Added
+- Argument `--no-preemptive` in the CLI to prevent the detector to search for hints.
+- Support for Python 3.13 (#512)
+
+### Fixed
+- Relax the TypeError exception thrown when trying to compare a CharsetMatch with anything else than a CharsetMatch.
+- Improved the general reliability of the detector based on user feedbacks. (#520) (#509) (#498) (#407) (#537)
+- Declared charset in content (preemptive detection) not changed when converting to utf-8 bytes. (#381)
+
+## [3.3.2](https://github.com/Ousret/charset_normalizer/compare/3.3.1...3.3.2) (2023-10-31)
+
+### Fixed
+- Unintentional memory usage regression when using large payload that match several encoding (#376)
+- Regression on some detection case showcased in the documentation (#371)
+
+### Added
+- Noise (md) probe that identify malformed arabic representation due to the presence of letters in isolated form (credit to my wife)
+
+## [3.3.1](https://github.com/Ousret/charset_normalizer/compare/3.3.0...3.3.1) (2023-10-22)
+
+### Changed
+- Optional mypyc compilation upgraded to version 1.6.1 for Python >= 3.8
+- Improved the general detection reliability based on reports from the community
+
+## [3.3.0](https://github.com/Ousret/charset_normalizer/compare/3.2.0...3.3.0) (2023-09-30)
+
+### Added
+- Allow to execute the CLI (e.g. normalizer) through `python -m charset_normalizer.cli` or `python -m charset_normalizer`
+- Support for 9 forgotten encoding that are supported by Python but unlisted in `encoding.aliases` as they have no alias (#323)
+
+### Removed
+- (internal) Redundant utils.is_ascii function and unused function is_private_use_only
+- (internal) charset_normalizer.assets is moved inside charset_normalizer.constant
+
+### Changed
+- (internal) Unicode code blocks in constants are updated using the latest v15.0.0 definition to improve detection
+- Optional mypyc compilation upgraded to version 1.5.1 for Python >= 3.8
+
+### Fixed
+- Unable to properly sort CharsetMatch when both chaos/noise and coherence were close due to an unreachable condition in \_\_lt\_\_ (#350)
+
+## [3.2.0](https://github.com/Ousret/charset_normalizer/compare/3.1.0...3.2.0) (2023-06-07)
+
+### Changed
+- Typehint for function `from_path` no longer enforce `PathLike` as its first argument
+- Minor improvement over the global detection reliability
+
+### Added
+- Introduce function `is_binary` that relies on main capabilities, and optimized to detect binaries
+- Propagate `enable_fallback` argument throughout `from_bytes`, `from_path`, and `from_fp` that allow a deeper control over the detection (default True)
+- Explicit support for Python 3.12
+
+### Fixed
+- Edge case detection failure where a file would contain 'very-long' camel cased word (Issue #289)
+
+## [3.1.0](https://github.com/Ousret/charset_normalizer/compare/3.0.1...3.1.0) (2023-03-06)
+
+### Added
+- Argument `should_rename_legacy` for legacy function `detect` and disregard any new arguments without errors (PR #262)
+
+### Removed
+- Support for Python 3.6 (PR #260)
+
+### Changed
+- Optional speedup provided by mypy/c 1.0.1
+
+## [3.0.1](https://github.com/Ousret/charset_normalizer/compare/3.0.0...3.0.1) (2022-11-18)
+
+### Fixed
+- Multi-bytes cutter/chunk generator did not always cut correctly (PR #233)
+
+### Changed
+- Speedup provided by mypy/c 0.990 on Python >= 3.7
+
+## [3.0.0](https://github.com/Ousret/charset_normalizer/compare/2.1.1...3.0.0) (2022-10-20)
+
+### Added
+- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results
+- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES
+- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio
+- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl)
+
+### Changed
+- Build with static metadata using 'build' frontend
+- Make the language detection stricter
+- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1
+
+### Fixed
+- CLI with opt --normalize fail when using full path for files
+- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it
+- Sphinx warnings when generating the documentation
+
+### Removed
+- Coherence detector no longer return 'Simple English' instead return 'English'
+- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese'
+- Breaking: Method `first()` and `best()` from CharsetMatch
+- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII)
+- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches
+- Breaking: Top-level function `normalize`
+- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch
+- Support for the backport `unicodedata2`
+
+## [3.0.0rc1](https://github.com/Ousret/charset_normalizer/compare/3.0.0b2...3.0.0rc1) (2022-10-18)
+
+### Added
+- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results
+- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES
+- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio
+
+### Changed
+- Build with static metadata using 'build' frontend
+- Make the language detection stricter
+
+### Fixed
+- CLI with opt --normalize fail when using full path for files
+- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it
+
+### Removed
+- Coherence detector no longer return 'Simple English' instead return 'English'
+- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese'
+
+## [3.0.0b2](https://github.com/Ousret/charset_normalizer/compare/3.0.0b1...3.0.0b2) (2022-08-21)
+
+### Added
+- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl)
+
+### Removed
+- Breaking: Method `first()` and `best()` from CharsetMatch
+- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII)
+
+### Fixed
+- Sphinx warnings when generating the documentation
+
+## [3.0.0b1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...3.0.0b1) (2022-08-15)
+
+### Changed
+- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1
+
+### Removed
+- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches
+- Breaking: Top-level function `normalize`
+- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch
+- Support for the backport `unicodedata2`
+
+## [2.1.1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...2.1.1) (2022-08-19)
+
+### Deprecated
+- Function `normalize` scheduled for removal in 3.0
+
+### Changed
+- Removed useless call to decode in fn is_unprintable (#206)
+
+### Fixed
+- Third-party library (i18n xgettext) crashing not recognizing utf_8 (PEP 263) with underscore from [@aleksandernovikov](https://github.com/aleksandernovikov) (#204)
+
+## [2.1.0](https://github.com/Ousret/charset_normalizer/compare/2.0.12...2.1.0) (2022-06-19)
+
+### Added
+- Output the Unicode table version when running the CLI with `--version` (PR #194)
+
+### Changed
+- Re-use decoded buffer for single byte character sets from [@nijel](https://github.com/nijel) (PR #175)
+- Fixing some performance bottlenecks from [@deedy5](https://github.com/deedy5) (PR #183)
+
+### Fixed
+- Workaround potential bug in cpython with Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space (PR #175)
+- CLI default threshold aligned with the API threshold from [@oleksandr-kuzmenko](https://github.com/oleksandr-kuzmenko) (PR #181)
+
+### Removed
+- Support for Python 3.5 (PR #192)
+
+### Deprecated
+- Use of backport unicodedata from `unicodedata2` as Python is quickly catching up, scheduled for removal in 3.0 (PR #194)
+
+## [2.0.12](https://github.com/Ousret/charset_normalizer/compare/2.0.11...2.0.12) (2022-02-12)
+
+### Fixed
+- ASCII miss-detection on rare cases (PR #170)
+
+## [2.0.11](https://github.com/Ousret/charset_normalizer/compare/2.0.10...2.0.11) (2022-01-30)
+
+### Added
+- Explicit support for Python 3.11 (PR #164)
+
+### Changed
+- The logging behavior have been completely reviewed, now using only TRACE and DEBUG levels (PR #163 #165)
+
+## [2.0.10](https://github.com/Ousret/charset_normalizer/compare/2.0.9...2.0.10) (2022-01-04)
+
+### Fixed
+- Fallback match entries might lead to UnicodeDecodeError for large bytes sequence (PR #154)
+
+### Changed
+- Skipping the language-detection (CD) on ASCII (PR #155)
+
+## [2.0.9](https://github.com/Ousret/charset_normalizer/compare/2.0.8...2.0.9) (2021-12-03)
+
+### Changed
+- Moderating the logging impact (since 2.0.8) for specific environments (PR #147)
+
+### Fixed
+- Wrong logging level applied when setting kwarg `explain` to True (PR #146)
+
+## [2.0.8](https://github.com/Ousret/charset_normalizer/compare/2.0.7...2.0.8) (2021-11-24)
+### Changed
+- Improvement over Vietnamese detection (PR #126)
+- MD improvement on trailing data and long foreign (non-pure latin) data (PR #124)
+- Efficiency improvements in cd/alphabet_languages from [@adbar](https://github.com/adbar) (PR #122)
+- call sum() without an intermediary list following PEP 289 recommendations from [@adbar](https://github.com/adbar) (PR #129)
+- Code style as refactored by Sourcery-AI (PR #131)
+- Minor adjustment on the MD around european words (PR #133)
+- Remove and replace SRTs from assets / tests (PR #139)
+- Initialize the library logger with a `NullHandler` by default from [@nmaynes](https://github.com/nmaynes) (PR #135)
+- Setting kwarg `explain` to True will add provisionally (bounded to function lifespan) a specific stream handler (PR #135)
+
+### Fixed
+- Fix large (misleading) sequence giving UnicodeDecodeError (PR #137)
+- Avoid using too insignificant chunk (PR #137)
+
+### Added
+- Add and expose function `set_logging_handler` to configure a specific StreamHandler from [@nmaynes](https://github.com/nmaynes) (PR #135)
+- Add `CHANGELOG.md` entries, format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) (PR #141)
+
+## [2.0.7](https://github.com/Ousret/charset_normalizer/compare/2.0.6...2.0.7) (2021-10-11)
+### Added
+- Add support for Kazakh (Cyrillic) language detection (PR #109)
+
+### Changed
+- Further, improve inferring the language from a given single-byte code page (PR #112)
+- Vainly trying to leverage PEP263 when PEP3120 is not supported (PR #116)
+- Refactoring for potential performance improvements in loops from [@adbar](https://github.com/adbar) (PR #113)
+- Various detection improvement (MD+CD) (PR #117)
+
+### Removed
+- Remove redundant logging entry about detected language(s) (PR #115)
+
+### Fixed
+- Fix a minor inconsistency between Python 3.5 and other versions regarding language detection (PR #117 #102)
+
+## [2.0.6](https://github.com/Ousret/charset_normalizer/compare/2.0.5...2.0.6) (2021-09-18)
+### Fixed
+- Unforeseen regression with the loss of the backward-compatibility with some older minor of Python 3.5.x (PR #100)
+- Fix CLI crash when using --minimal output in certain cases (PR #103)
+
+### Changed
+- Minor improvement to the detection efficiency (less than 1%) (PR #106 #101)
+
+## [2.0.5](https://github.com/Ousret/charset_normalizer/compare/2.0.4...2.0.5) (2021-09-14)
+### Changed
+- The project now comply with: flake8, mypy, isort and black to ensure a better overall quality (PR #81)
+- The BC-support with v1.x was improved, the old staticmethods are restored (PR #82)
+- The Unicode detection is slightly improved (PR #93)
+- Add syntax sugar \_\_bool\_\_ for results CharsetMatches list-container (PR #91)
+
+### Removed
+- The project no longer raise warning on tiny content given for detection, will be simply logged as warning instead (PR #92)
+
+### Fixed
+- In some rare case, the chunks extractor could cut in the middle of a multi-byte character and could mislead the mess detection (PR #95)
+- Some rare 'space' characters could trip up the UnprintablePlugin/Mess detection (PR #96)
+- The MANIFEST.in was not exhaustive (PR #78)
+
+## [2.0.4](https://github.com/Ousret/charset_normalizer/compare/2.0.3...2.0.4) (2021-07-30)
+### Fixed
+- The CLI no longer raise an unexpected exception when no encoding has been found (PR #70)
+- Fix accessing the 'alphabets' property when the payload contains surrogate characters (PR #68)
+- The logger could mislead (explain=True) on detected languages and the impact of one MBCS match (PR #72)
+- Submatch factoring could be wrong in rare edge cases (PR #72)
+- Multiple files given to the CLI were ignored when publishing results to STDOUT. (After the first path) (PR #72)
+- Fix line endings from CRLF to LF for certain project files (PR #67)
+
+### Changed
+- Adjust the MD to lower the sensitivity, thus improving the global detection reliability (PR #69 #76)
+- Allow fallback on specified encoding if any (PR #71)
+
+## [2.0.3](https://github.com/Ousret/charset_normalizer/compare/2.0.2...2.0.3) (2021-07-16)
+### Changed
+- Part of the detection mechanism has been improved to be less sensitive, resulting in more accurate detection results. Especially ASCII. (PR #63)
+- According to the community wishes, the detection will fall back on ASCII or UTF-8 in a last-resort case. (PR #64)
+
+## [2.0.2](https://github.com/Ousret/charset_normalizer/compare/2.0.1...2.0.2) (2021-07-15)
+### Fixed
+- Empty/Too small JSON payload miss-detection fixed. Report from [@tseaver](https://github.com/tseaver) (PR #59)
+
+### Changed
+- Don't inject unicodedata2 into sys.modules from [@akx](https://github.com/akx) (PR #57)
+
+## [2.0.1](https://github.com/Ousret/charset_normalizer/compare/2.0.0...2.0.1) (2021-07-13)
+### Fixed
+- Make it work where there isn't a filesystem available, dropping assets frequencies.json. Report from [@sethmlarson](https://github.com/sethmlarson). (PR #55)
+- Using explain=False permanently disable the verbose output in the current runtime (PR #47)
+- One log entry (language target preemptive) was not show in logs when using explain=True (PR #47)
+- Fix undesired exception (ValueError) on getitem of instance CharsetMatches (PR #52)
+
+### Changed
+- Public function normalize default args values were not aligned with from_bytes (PR #53)
+
+### Added
+- You may now use charset aliases in cp_isolation and cp_exclusion arguments (PR #47)
+
+## [2.0.0](https://github.com/Ousret/charset_normalizer/compare/1.4.1...2.0.0) (2021-07-02)
+### Changed
+- 4x to 5 times faster than the previous 1.4.0 release. At least 2x faster than Chardet.
+- Accent has been made on UTF-8 detection, should perform rather instantaneous.
+- The backward compatibility with Chardet has been greatly improved. The legacy detect function returns an identical charset name whenever possible.
+- The detection mechanism has been slightly improved, now Turkish content is detected correctly (most of the time)
+- The program has been rewritten to ease the readability and maintainability. (+Using static typing)+
+- utf_7 detection has been reinstated.
+
+### Removed
+- This package no longer require anything when used with Python 3.5 (Dropped cached_property)
+- Removed support for these languages: Catalan, Esperanto, Kazakh, Baque, Volapük, Azeri, Galician, Nynorsk, Macedonian, and Serbocroatian.
+- The exception hook on UnicodeDecodeError has been removed.
+
+### Deprecated
+- Methods coherence_non_latin, w_counter, chaos_secondary_pass of the class CharsetMatch are now deprecated and scheduled for removal in v3.0
+
+### Fixed
+- The CLI output used the relative path of the file(s). Should be absolute.
+
+## [1.4.1](https://github.com/Ousret/charset_normalizer/compare/1.4.0...1.4.1) (2021-05-28)
+### Fixed
+- Logger configuration/usage no longer conflict with others (PR #44)
+
+## [1.4.0](https://github.com/Ousret/charset_normalizer/compare/1.3.9...1.4.0) (2021-05-21)
+### Removed
+- Using standard logging instead of using the package loguru.
+- Dropping nose test framework in favor of the maintained pytest.
+- Choose to not use dragonmapper package to help with gibberish Chinese/CJK text.
+- Require cached_property only for Python 3.5 due to constraint. Dropping for every other interpreter version.
+- Stop support for UTF-7 that does not contain a SIG.
+- Dropping PrettyTable, replaced with pure JSON output in CLI.
+
+### Fixed
+- BOM marker in a CharsetNormalizerMatch instance could be False in rare cases even if obviously present. Due to the sub-match factoring process.
+- Not searching properly for the BOM when trying utf32/16 parent codec.
+
+### Changed
+- Improving the package final size by compressing frequencies.json.
+- Huge improvement over the larges payload.
+
+### Added
+- CLI now produces JSON consumable output.
+- Return ASCII if given sequences fit. Given reasonable confidence.
+
+## [1.3.9](https://github.com/Ousret/charset_normalizer/compare/1.3.8...1.3.9) (2021-05-13)
+
+### Fixed
+- In some very rare cases, you may end up getting encode/decode errors due to a bad bytes payload (PR #40)
+
+## [1.3.8](https://github.com/Ousret/charset_normalizer/compare/1.3.7...1.3.8) (2021-05-12)
+
+### Fixed
+- Empty given payload for detection may cause an exception if trying to access the `alphabets` property. (PR #39)
+
+## [1.3.7](https://github.com/Ousret/charset_normalizer/compare/1.3.6...1.3.7) (2021-05-12)
+
+### Fixed
+- The legacy detect function should return UTF-8-SIG if sig is present in the payload. (PR #38)
+
+## [1.3.6](https://github.com/Ousret/charset_normalizer/compare/1.3.5...1.3.6) (2021-02-09)
+
+### Changed
+- Amend the previous release to allow prettytable 2.0 (PR #35)
+
+## [1.3.5](https://github.com/Ousret/charset_normalizer/compare/1.3.4...1.3.5) (2021-02-08)
+
+### Fixed
+- Fix error while using the package with a python pre-release interpreter (PR #33)
+
+### Changed
+- Dependencies refactoring, constraints revised.
+
+### Added
+- Add python 3.9 and 3.10 to the supported interpreters
+
+MIT License
+
+Copyright (c) 2025 TAHRI Ahmed R.
+
+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/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/RECORD b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/RECORD
new file mode 100644
index 0000000..98deee8
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/RECORD
@@ -0,0 +1,35 @@
+../../../bin/normalizer,sha256=rPIMOwi0a5F-c2txHIpC7agM3Ms0zAV7mIChkVHIZ6g,255
+charset_normalizer-3.4.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+charset_normalizer-3.4.1.dist-info/LICENSE,sha256=bQ1Bv-FwrGx9wkjJpj4lTQ-0WmDVCoJX0K-SxuJJuIc,1071
+charset_normalizer-3.4.1.dist-info/METADATA,sha256=JbyHzhmqZh_ugEn1Y7TY7CDYZA9FoU6BP25hrCNDf50,35313
+charset_normalizer-3.4.1.dist-info/RECORD,,
+charset_normalizer-3.4.1.dist-info/WHEEL,sha256=tRzqFuK6eFjpbf2xTNvU7E3xL2y00S_NWJvyqxej3BA,151
+charset_normalizer-3.4.1.dist-info/entry_points.txt,sha256=8C-Y3iXIfyXQ83Tpir2B8t-XLJYpxF5xbb38d_js-h4,65
+charset_normalizer-3.4.1.dist-info/top_level.txt,sha256=7ASyzePr8_xuZWJsnqJjIBtyV8vhEo0wBCv1MPRRi3Q,19
+charset_normalizer/__init__.py,sha256=OKRxRv2Zhnqk00tqkN0c1BtJjm165fWXLydE52IKuHc,1590
+charset_normalizer/__main__.py,sha256=yzYxMR-IhKRHYwcSlavEv8oGdwxsR89mr2X09qXGdps,109
+charset_normalizer/__pycache__/__init__.cpython-312.pyc,,
+charset_normalizer/__pycache__/__main__.cpython-312.pyc,,
+charset_normalizer/__pycache__/api.cpython-312.pyc,,
+charset_normalizer/__pycache__/cd.cpython-312.pyc,,
+charset_normalizer/__pycache__/constant.cpython-312.pyc,,
+charset_normalizer/__pycache__/legacy.cpython-312.pyc,,
+charset_normalizer/__pycache__/md.cpython-312.pyc,,
+charset_normalizer/__pycache__/models.cpython-312.pyc,,
+charset_normalizer/__pycache__/utils.cpython-312.pyc,,
+charset_normalizer/__pycache__/version.cpython-312.pyc,,
+charset_normalizer/api.py,sha256=qBRz8mJ_R5E713R6TOyqHEdnmyxbEDnCSHvx32ubDGg,22617
+charset_normalizer/cd.py,sha256=WKTo1HDb-H9HfCDc3Bfwq5jzS25Ziy9SE2a74SgTq88,12522
+charset_normalizer/cli/__init__.py,sha256=D8I86lFk2-py45JvqxniTirSj_sFyE6sjaY_0-G1shc,136
+charset_normalizer/cli/__main__.py,sha256=VGC9klOoi6_R2z8rmyrc936kv7u2A1udjjHtlmNPDTM,10410
+charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc,,
+charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc,,
+charset_normalizer/constant.py,sha256=4VuTcZNLew1j_8ixA-Rt_VVqNWD4pwgHOHMCMlr0964,40477
+charset_normalizer/legacy.py,sha256=yhNXsPHkBfqPXKRb-sPXNj3Bscp9-mFGcYOkJ62tg9c,2328
+charset_normalizer/md.cpython-312-x86_64-linux-gnu.so,sha256=W654QTU3QZI6eWJ0fanScAr0_O6sL0I61fyRSdC-39Y,16064
+charset_normalizer/md.py,sha256=iyXXQGWl54nnLQLueMWTmUtlivO0-rTBgVkmJxIIAGU,20036
+charset_normalizer/md__mypyc.cpython-312-x86_64-linux-gnu.so,sha256=02IBduHhrAfIJteTWMlJulQK2gKMGP64dy8bVubEw3M,280904
+charset_normalizer/models.py,sha256=lKXhOnIPtiakbK3i__J9wpOfzx3JDTKj7Dn3Rg0VaRI,12394
+charset_normalizer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+charset_normalizer/utils.py,sha256=T5UHo8AS7NVMmgruWoZyqEf0WrZVcQpgUNetRoborSk,12002
+charset_normalizer/version.py,sha256=Ambcj3O8FfvdLfDLc8dkaxZx97O1IM_R4_aKGD_TDdE,115
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/WHEEL
new file mode 100644
index 0000000..1c04f8b
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/WHEEL
@@ -0,0 +1,6 @@
+Wheel-Version: 1.0
+Generator: setuptools (75.6.0)
+Root-Is-Purelib: false
+Tag: cp312-cp312-manylinux_2_17_x86_64
+Tag: cp312-cp312-manylinux2014_x86_64
+
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/entry_points.txt b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/entry_points.txt
new file mode 100644
index 0000000..ec92012
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/entry_points.txt
@@ -0,0 +1,2 @@
+[console_scripts]
+normalizer = charset_normalizer:cli.cli_detect
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/top_level.txt
new file mode 100644
index 0000000..66958f0
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/top_level.txt
@@ -0,0 +1 @@
+charset_normalizer
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__init__.py b/testcline/lib/python3.12/site-packages/charset_normalizer/__init__.py
new file mode 100644
index 0000000..0d3a379
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/__init__.py
@@ -0,0 +1,48 @@
+"""
+Charset-Normalizer
+~~~~~~~~~~~~~~
+The Real First Universal Charset Detector.
+A library that helps you read text from an unknown charset encoding.
+Motivated by chardet, This package is trying to resolve the issue by taking a new approach.
+All IANA character set names for which the Python core library provides codecs are supported.
+
+Basic usage:
+ >>> from charset_normalizer import from_bytes
+ >>> results = from_bytes('Bсеки човек има право на образование. Oбразованието!'.encode('utf_8'))
+ >>> best_guess = results.best()
+ >>> str(best_guess)
+ 'Bсеки човек има право на образование. Oбразованието!'
+
+Others methods and usages are available - see the full documentation
+at .
+:copyright: (c) 2021 by Ahmed TAHRI
+:license: MIT, see LICENSE for more details.
+"""
+
+from __future__ import annotations
+
+import logging
+
+from .api import from_bytes, from_fp, from_path, is_binary
+from .legacy import detect
+from .models import CharsetMatch, CharsetMatches
+from .utils import set_logging_handler
+from .version import VERSION, __version__
+
+__all__ = (
+ "from_fp",
+ "from_path",
+ "from_bytes",
+ "is_binary",
+ "detect",
+ "CharsetMatch",
+ "CharsetMatches",
+ "__version__",
+ "VERSION",
+ "set_logging_handler",
+)
+
+# Attach a NullHandler to the top level logger by default
+# https://docs.python.org/3.3/howto/logging.html#configuring-logging-for-a-library
+
+logging.getLogger("charset_normalizer").addHandler(logging.NullHandler())
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__main__.py b/testcline/lib/python3.12/site-packages/charset_normalizer/__main__.py
new file mode 100644
index 0000000..e0e76f7
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/__main__.py
@@ -0,0 +1,6 @@
+from __future__ import annotations
+
+from .cli import cli_detect
+
+if __name__ == "__main__":
+ cli_detect()
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..c75f4b7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc
new file mode 100644
index 0000000..380328e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc
new file mode 100644
index 0000000..ed202d6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc
new file mode 100644
index 0000000..456f2ea
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc
new file mode 100644
index 0000000..5c3496e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc
new file mode 100644
index 0000000..fe85f66
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc
new file mode 100644
index 0000000..e2e7185
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc
new file mode 100644
index 0000000..06361e7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc
new file mode 100644
index 0000000..f5cd2f7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc
new file mode 100644
index 0000000..ac7758f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/api.py b/testcline/lib/python3.12/site-packages/charset_normalizer/api.py
new file mode 100644
index 0000000..2c8c061
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/api.py
@@ -0,0 +1,668 @@
+from __future__ import annotations
+
+import logging
+from os import PathLike
+from typing import BinaryIO
+
+from .cd import (
+ coherence_ratio,
+ encoding_languages,
+ mb_encoding_languages,
+ merge_coherence_ratios,
+)
+from .constant import IANA_SUPPORTED, TOO_BIG_SEQUENCE, TOO_SMALL_SEQUENCE, TRACE
+from .md import mess_ratio
+from .models import CharsetMatch, CharsetMatches
+from .utils import (
+ any_specified_encoding,
+ cut_sequence_chunks,
+ iana_name,
+ identify_sig_or_bom,
+ is_cp_similar,
+ is_multi_byte_encoding,
+ should_strip_sig_or_bom,
+)
+
+logger = logging.getLogger("charset_normalizer")
+explain_handler = logging.StreamHandler()
+explain_handler.setFormatter(
+ logging.Formatter("%(asctime)s | %(levelname)s | %(message)s")
+)
+
+
+def from_bytes(
+ sequences: bytes | bytearray,
+ steps: int = 5,
+ chunk_size: int = 512,
+ threshold: float = 0.2,
+ cp_isolation: list[str] | None = None,
+ cp_exclusion: list[str] | None = None,
+ preemptive_behaviour: bool = True,
+ explain: bool = False,
+ language_threshold: float = 0.1,
+ enable_fallback: bool = True,
+) -> CharsetMatches:
+ """
+ Given a raw bytes sequence, return the best possibles charset usable to render str objects.
+ If there is no results, it is a strong indicator that the source is binary/not text.
+ By default, the process will extract 5 blocks of 512o each to assess the mess and coherence of a given sequence.
+ And will give up a particular code page after 20% of measured mess. Those criteria are customizable at will.
+
+ The preemptive behavior DOES NOT replace the traditional detection workflow, it prioritize a particular code page
+ but never take it for granted. Can improve the performance.
+
+ You may want to focus your attention to some code page or/and not others, use cp_isolation and cp_exclusion for that
+ purpose.
+
+ This function will strip the SIG in the payload/sequence every time except on UTF-16, UTF-32.
+ By default the library does not setup any handler other than the NullHandler, if you choose to set the 'explain'
+ toggle to True it will alter the logger configuration to add a StreamHandler that is suitable for debugging.
+ Custom logging format and handler can be set manually.
+ """
+
+ if not isinstance(sequences, (bytearray, bytes)):
+ raise TypeError(
+ "Expected object of type bytes or bytearray, got: {}".format(
+ type(sequences)
+ )
+ )
+
+ if explain:
+ previous_logger_level: int = logger.level
+ logger.addHandler(explain_handler)
+ logger.setLevel(TRACE)
+
+ length: int = len(sequences)
+
+ if length == 0:
+ logger.debug("Encoding detection on empty bytes, assuming utf_8 intention.")
+ if explain: # Defensive: ensure exit path clean handler
+ logger.removeHandler(explain_handler)
+ logger.setLevel(previous_logger_level or logging.WARNING)
+ return CharsetMatches([CharsetMatch(sequences, "utf_8", 0.0, False, [], "")])
+
+ if cp_isolation is not None:
+ logger.log(
+ TRACE,
+ "cp_isolation is set. use this flag for debugging purpose. "
+ "limited list of encoding allowed : %s.",
+ ", ".join(cp_isolation),
+ )
+ cp_isolation = [iana_name(cp, False) for cp in cp_isolation]
+ else:
+ cp_isolation = []
+
+ if cp_exclusion is not None:
+ logger.log(
+ TRACE,
+ "cp_exclusion is set. use this flag for debugging purpose. "
+ "limited list of encoding excluded : %s.",
+ ", ".join(cp_exclusion),
+ )
+ cp_exclusion = [iana_name(cp, False) for cp in cp_exclusion]
+ else:
+ cp_exclusion = []
+
+ if length <= (chunk_size * steps):
+ logger.log(
+ TRACE,
+ "override steps (%i) and chunk_size (%i) as content does not fit (%i byte(s) given) parameters.",
+ steps,
+ chunk_size,
+ length,
+ )
+ steps = 1
+ chunk_size = length
+
+ if steps > 1 and length / steps < chunk_size:
+ chunk_size = int(length / steps)
+
+ is_too_small_sequence: bool = len(sequences) < TOO_SMALL_SEQUENCE
+ is_too_large_sequence: bool = len(sequences) >= TOO_BIG_SEQUENCE
+
+ if is_too_small_sequence:
+ logger.log(
+ TRACE,
+ "Trying to detect encoding from a tiny portion of ({}) byte(s).".format(
+ length
+ ),
+ )
+ elif is_too_large_sequence:
+ logger.log(
+ TRACE,
+ "Using lazy str decoding because the payload is quite large, ({}) byte(s).".format(
+ length
+ ),
+ )
+
+ prioritized_encodings: list[str] = []
+
+ specified_encoding: str | None = (
+ any_specified_encoding(sequences) if preemptive_behaviour else None
+ )
+
+ if specified_encoding is not None:
+ prioritized_encodings.append(specified_encoding)
+ logger.log(
+ TRACE,
+ "Detected declarative mark in sequence. Priority +1 given for %s.",
+ specified_encoding,
+ )
+
+ tested: set[str] = set()
+ tested_but_hard_failure: list[str] = []
+ tested_but_soft_failure: list[str] = []
+
+ fallback_ascii: CharsetMatch | None = None
+ fallback_u8: CharsetMatch | None = None
+ fallback_specified: CharsetMatch | None = None
+
+ results: CharsetMatches = CharsetMatches()
+
+ early_stop_results: CharsetMatches = CharsetMatches()
+
+ sig_encoding, sig_payload = identify_sig_or_bom(sequences)
+
+ if sig_encoding is not None:
+ prioritized_encodings.append(sig_encoding)
+ logger.log(
+ TRACE,
+ "Detected a SIG or BOM mark on first %i byte(s). Priority +1 given for %s.",
+ len(sig_payload),
+ sig_encoding,
+ )
+
+ prioritized_encodings.append("ascii")
+
+ if "utf_8" not in prioritized_encodings:
+ prioritized_encodings.append("utf_8")
+
+ for encoding_iana in prioritized_encodings + IANA_SUPPORTED:
+ if cp_isolation and encoding_iana not in cp_isolation:
+ continue
+
+ if cp_exclusion and encoding_iana in cp_exclusion:
+ continue
+
+ if encoding_iana in tested:
+ continue
+
+ tested.add(encoding_iana)
+
+ decoded_payload: str | None = None
+ bom_or_sig_available: bool = sig_encoding == encoding_iana
+ strip_sig_or_bom: bool = bom_or_sig_available and should_strip_sig_or_bom(
+ encoding_iana
+ )
+
+ if encoding_iana in {"utf_16", "utf_32"} and not bom_or_sig_available:
+ logger.log(
+ TRACE,
+ "Encoding %s won't be tested as-is because it require a BOM. Will try some sub-encoder LE/BE.",
+ encoding_iana,
+ )
+ continue
+ if encoding_iana in {"utf_7"} and not bom_or_sig_available:
+ logger.log(
+ TRACE,
+ "Encoding %s won't be tested as-is because detection is unreliable without BOM/SIG.",
+ encoding_iana,
+ )
+ continue
+
+ try:
+ is_multi_byte_decoder: bool = is_multi_byte_encoding(encoding_iana)
+ except (ModuleNotFoundError, ImportError):
+ logger.log(
+ TRACE,
+ "Encoding %s does not provide an IncrementalDecoder",
+ encoding_iana,
+ )
+ continue
+
+ try:
+ if is_too_large_sequence and is_multi_byte_decoder is False:
+ str(
+ (
+ sequences[: int(50e4)]
+ if strip_sig_or_bom is False
+ else sequences[len(sig_payload) : int(50e4)]
+ ),
+ encoding=encoding_iana,
+ )
+ else:
+ decoded_payload = str(
+ (
+ sequences
+ if strip_sig_or_bom is False
+ else sequences[len(sig_payload) :]
+ ),
+ encoding=encoding_iana,
+ )
+ except (UnicodeDecodeError, LookupError) as e:
+ if not isinstance(e, LookupError):
+ logger.log(
+ TRACE,
+ "Code page %s does not fit given bytes sequence at ALL. %s",
+ encoding_iana,
+ str(e),
+ )
+ tested_but_hard_failure.append(encoding_iana)
+ continue
+
+ similar_soft_failure_test: bool = False
+
+ for encoding_soft_failed in tested_but_soft_failure:
+ if is_cp_similar(encoding_iana, encoding_soft_failed):
+ similar_soft_failure_test = True
+ break
+
+ if similar_soft_failure_test:
+ logger.log(
+ TRACE,
+ "%s is deemed too similar to code page %s and was consider unsuited already. Continuing!",
+ encoding_iana,
+ encoding_soft_failed,
+ )
+ continue
+
+ r_ = range(
+ 0 if not bom_or_sig_available else len(sig_payload),
+ length,
+ int(length / steps),
+ )
+
+ multi_byte_bonus: bool = (
+ is_multi_byte_decoder
+ and decoded_payload is not None
+ and len(decoded_payload) < length
+ )
+
+ if multi_byte_bonus:
+ logger.log(
+ TRACE,
+ "Code page %s is a multi byte encoding table and it appear that at least one character "
+ "was encoded using n-bytes.",
+ encoding_iana,
+ )
+
+ max_chunk_gave_up: int = int(len(r_) / 4)
+
+ max_chunk_gave_up = max(max_chunk_gave_up, 2)
+ early_stop_count: int = 0
+ lazy_str_hard_failure = False
+
+ md_chunks: list[str] = []
+ md_ratios = []
+
+ try:
+ for chunk in cut_sequence_chunks(
+ sequences,
+ encoding_iana,
+ r_,
+ chunk_size,
+ bom_or_sig_available,
+ strip_sig_or_bom,
+ sig_payload,
+ is_multi_byte_decoder,
+ decoded_payload,
+ ):
+ md_chunks.append(chunk)
+
+ md_ratios.append(
+ mess_ratio(
+ chunk,
+ threshold,
+ explain is True and 1 <= len(cp_isolation) <= 2,
+ )
+ )
+
+ if md_ratios[-1] >= threshold:
+ early_stop_count += 1
+
+ if (early_stop_count >= max_chunk_gave_up) or (
+ bom_or_sig_available and strip_sig_or_bom is False
+ ):
+ break
+ except (
+ UnicodeDecodeError
+ ) as e: # Lazy str loading may have missed something there
+ logger.log(
+ TRACE,
+ "LazyStr Loading: After MD chunk decode, code page %s does not fit given bytes sequence at ALL. %s",
+ encoding_iana,
+ str(e),
+ )
+ early_stop_count = max_chunk_gave_up
+ lazy_str_hard_failure = True
+
+ # We might want to check the sequence again with the whole content
+ # Only if initial MD tests passes
+ if (
+ not lazy_str_hard_failure
+ and is_too_large_sequence
+ and not is_multi_byte_decoder
+ ):
+ try:
+ sequences[int(50e3) :].decode(encoding_iana, errors="strict")
+ except UnicodeDecodeError as e:
+ logger.log(
+ TRACE,
+ "LazyStr Loading: After final lookup, code page %s does not fit given bytes sequence at ALL. %s",
+ encoding_iana,
+ str(e),
+ )
+ tested_but_hard_failure.append(encoding_iana)
+ continue
+
+ mean_mess_ratio: float = sum(md_ratios) / len(md_ratios) if md_ratios else 0.0
+ if mean_mess_ratio >= threshold or early_stop_count >= max_chunk_gave_up:
+ tested_but_soft_failure.append(encoding_iana)
+ logger.log(
+ TRACE,
+ "%s was excluded because of initial chaos probing. Gave up %i time(s). "
+ "Computed mean chaos is %f %%.",
+ encoding_iana,
+ early_stop_count,
+ round(mean_mess_ratio * 100, ndigits=3),
+ )
+ # Preparing those fallbacks in case we got nothing.
+ if (
+ enable_fallback
+ and encoding_iana in ["ascii", "utf_8", specified_encoding]
+ and not lazy_str_hard_failure
+ ):
+ fallback_entry = CharsetMatch(
+ sequences,
+ encoding_iana,
+ threshold,
+ False,
+ [],
+ decoded_payload,
+ preemptive_declaration=specified_encoding,
+ )
+ if encoding_iana == specified_encoding:
+ fallback_specified = fallback_entry
+ elif encoding_iana == "ascii":
+ fallback_ascii = fallback_entry
+ else:
+ fallback_u8 = fallback_entry
+ continue
+
+ logger.log(
+ TRACE,
+ "%s passed initial chaos probing. Mean measured chaos is %f %%",
+ encoding_iana,
+ round(mean_mess_ratio * 100, ndigits=3),
+ )
+
+ if not is_multi_byte_decoder:
+ target_languages: list[str] = encoding_languages(encoding_iana)
+ else:
+ target_languages = mb_encoding_languages(encoding_iana)
+
+ if target_languages:
+ logger.log(
+ TRACE,
+ "{} should target any language(s) of {}".format(
+ encoding_iana, str(target_languages)
+ ),
+ )
+
+ cd_ratios = []
+
+ # We shall skip the CD when its about ASCII
+ # Most of the time its not relevant to run "language-detection" on it.
+ if encoding_iana != "ascii":
+ for chunk in md_chunks:
+ chunk_languages = coherence_ratio(
+ chunk,
+ language_threshold,
+ ",".join(target_languages) if target_languages else None,
+ )
+
+ cd_ratios.append(chunk_languages)
+
+ cd_ratios_merged = merge_coherence_ratios(cd_ratios)
+
+ if cd_ratios_merged:
+ logger.log(
+ TRACE,
+ "We detected language {} using {}".format(
+ cd_ratios_merged, encoding_iana
+ ),
+ )
+
+ current_match = CharsetMatch(
+ sequences,
+ encoding_iana,
+ mean_mess_ratio,
+ bom_or_sig_available,
+ cd_ratios_merged,
+ (
+ decoded_payload
+ if (
+ is_too_large_sequence is False
+ or encoding_iana in [specified_encoding, "ascii", "utf_8"]
+ )
+ else None
+ ),
+ preemptive_declaration=specified_encoding,
+ )
+
+ results.append(current_match)
+
+ if (
+ encoding_iana in [specified_encoding, "ascii", "utf_8"]
+ and mean_mess_ratio < 0.1
+ ):
+ # If md says nothing to worry about, then... stop immediately!
+ if mean_mess_ratio == 0.0:
+ logger.debug(
+ "Encoding detection: %s is most likely the one.",
+ current_match.encoding,
+ )
+ if explain: # Defensive: ensure exit path clean handler
+ logger.removeHandler(explain_handler)
+ logger.setLevel(previous_logger_level)
+ return CharsetMatches([current_match])
+
+ early_stop_results.append(current_match)
+
+ if (
+ len(early_stop_results)
+ and (specified_encoding is None or specified_encoding in tested)
+ and "ascii" in tested
+ and "utf_8" in tested
+ ):
+ probable_result: CharsetMatch = early_stop_results.best() # type: ignore[assignment]
+ logger.debug(
+ "Encoding detection: %s is most likely the one.",
+ probable_result.encoding,
+ )
+ if explain: # Defensive: ensure exit path clean handler
+ logger.removeHandler(explain_handler)
+ logger.setLevel(previous_logger_level)
+
+ return CharsetMatches([probable_result])
+
+ if encoding_iana == sig_encoding:
+ logger.debug(
+ "Encoding detection: %s is most likely the one as we detected a BOM or SIG within "
+ "the beginning of the sequence.",
+ encoding_iana,
+ )
+ if explain: # Defensive: ensure exit path clean handler
+ logger.removeHandler(explain_handler)
+ logger.setLevel(previous_logger_level)
+ return CharsetMatches([results[encoding_iana]])
+
+ if len(results) == 0:
+ if fallback_u8 or fallback_ascii or fallback_specified:
+ logger.log(
+ TRACE,
+ "Nothing got out of the detection process. Using ASCII/UTF-8/Specified fallback.",
+ )
+
+ if fallback_specified:
+ logger.debug(
+ "Encoding detection: %s will be used as a fallback match",
+ fallback_specified.encoding,
+ )
+ results.append(fallback_specified)
+ elif (
+ (fallback_u8 and fallback_ascii is None)
+ or (
+ fallback_u8
+ and fallback_ascii
+ and fallback_u8.fingerprint != fallback_ascii.fingerprint
+ )
+ or (fallback_u8 is not None)
+ ):
+ logger.debug("Encoding detection: utf_8 will be used as a fallback match")
+ results.append(fallback_u8)
+ elif fallback_ascii:
+ logger.debug("Encoding detection: ascii will be used as a fallback match")
+ results.append(fallback_ascii)
+
+ if results:
+ logger.debug(
+ "Encoding detection: Found %s as plausible (best-candidate) for content. With %i alternatives.",
+ results.best().encoding, # type: ignore
+ len(results) - 1,
+ )
+ else:
+ logger.debug("Encoding detection: Unable to determine any suitable charset.")
+
+ if explain:
+ logger.removeHandler(explain_handler)
+ logger.setLevel(previous_logger_level)
+
+ return results
+
+
+def from_fp(
+ fp: BinaryIO,
+ steps: int = 5,
+ chunk_size: int = 512,
+ threshold: float = 0.20,
+ cp_isolation: list[str] | None = None,
+ cp_exclusion: list[str] | None = None,
+ preemptive_behaviour: bool = True,
+ explain: bool = False,
+ language_threshold: float = 0.1,
+ enable_fallback: bool = True,
+) -> CharsetMatches:
+ """
+ Same thing than the function from_bytes but using a file pointer that is already ready.
+ Will not close the file pointer.
+ """
+ return from_bytes(
+ fp.read(),
+ steps,
+ chunk_size,
+ threshold,
+ cp_isolation,
+ cp_exclusion,
+ preemptive_behaviour,
+ explain,
+ language_threshold,
+ enable_fallback,
+ )
+
+
+def from_path(
+ path: str | bytes | PathLike, # type: ignore[type-arg]
+ steps: int = 5,
+ chunk_size: int = 512,
+ threshold: float = 0.20,
+ cp_isolation: list[str] | None = None,
+ cp_exclusion: list[str] | None = None,
+ preemptive_behaviour: bool = True,
+ explain: bool = False,
+ language_threshold: float = 0.1,
+ enable_fallback: bool = True,
+) -> CharsetMatches:
+ """
+ Same thing than the function from_bytes but with one extra step. Opening and reading given file path in binary mode.
+ Can raise IOError.
+ """
+ with open(path, "rb") as fp:
+ return from_fp(
+ fp,
+ steps,
+ chunk_size,
+ threshold,
+ cp_isolation,
+ cp_exclusion,
+ preemptive_behaviour,
+ explain,
+ language_threshold,
+ enable_fallback,
+ )
+
+
+def is_binary(
+ fp_or_path_or_payload: PathLike | str | BinaryIO | bytes, # type: ignore[type-arg]
+ steps: int = 5,
+ chunk_size: int = 512,
+ threshold: float = 0.20,
+ cp_isolation: list[str] | None = None,
+ cp_exclusion: list[str] | None = None,
+ preemptive_behaviour: bool = True,
+ explain: bool = False,
+ language_threshold: float = 0.1,
+ enable_fallback: bool = False,
+) -> bool:
+ """
+ Detect if the given input (file, bytes, or path) points to a binary file. aka. not a string.
+ Based on the same main heuristic algorithms and default kwargs at the sole exception that fallbacks match
+ are disabled to be stricter around ASCII-compatible but unlikely to be a string.
+ """
+ if isinstance(fp_or_path_or_payload, (str, PathLike)):
+ guesses = from_path(
+ fp_or_path_or_payload,
+ steps=steps,
+ chunk_size=chunk_size,
+ threshold=threshold,
+ cp_isolation=cp_isolation,
+ cp_exclusion=cp_exclusion,
+ preemptive_behaviour=preemptive_behaviour,
+ explain=explain,
+ language_threshold=language_threshold,
+ enable_fallback=enable_fallback,
+ )
+ elif isinstance(
+ fp_or_path_or_payload,
+ (
+ bytes,
+ bytearray,
+ ),
+ ):
+ guesses = from_bytes(
+ fp_or_path_or_payload,
+ steps=steps,
+ chunk_size=chunk_size,
+ threshold=threshold,
+ cp_isolation=cp_isolation,
+ cp_exclusion=cp_exclusion,
+ preemptive_behaviour=preemptive_behaviour,
+ explain=explain,
+ language_threshold=language_threshold,
+ enable_fallback=enable_fallback,
+ )
+ else:
+ guesses = from_fp(
+ fp_or_path_or_payload,
+ steps=steps,
+ chunk_size=chunk_size,
+ threshold=threshold,
+ cp_isolation=cp_isolation,
+ cp_exclusion=cp_exclusion,
+ preemptive_behaviour=preemptive_behaviour,
+ explain=explain,
+ language_threshold=language_threshold,
+ enable_fallback=enable_fallback,
+ )
+
+ return not guesses
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/cd.py b/testcline/lib/python3.12/site-packages/charset_normalizer/cd.py
new file mode 100644
index 0000000..71a3ed5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/cd.py
@@ -0,0 +1,395 @@
+from __future__ import annotations
+
+import importlib
+from codecs import IncrementalDecoder
+from collections import Counter
+from functools import lru_cache
+from typing import Counter as TypeCounter
+
+from .constant import (
+ FREQUENCIES,
+ KO_NAMES,
+ LANGUAGE_SUPPORTED_COUNT,
+ TOO_SMALL_SEQUENCE,
+ ZH_NAMES,
+)
+from .md import is_suspiciously_successive_range
+from .models import CoherenceMatches
+from .utils import (
+ is_accentuated,
+ is_latin,
+ is_multi_byte_encoding,
+ is_unicode_range_secondary,
+ unicode_range,
+)
+
+
+def encoding_unicode_range(iana_name: str) -> list[str]:
+ """
+ Return associated unicode ranges in a single byte code page.
+ """
+ if is_multi_byte_encoding(iana_name):
+ raise OSError("Function not supported on multi-byte code page")
+
+ decoder = importlib.import_module(f"encodings.{iana_name}").IncrementalDecoder
+
+ p: IncrementalDecoder = decoder(errors="ignore")
+ seen_ranges: dict[str, int] = {}
+ character_count: int = 0
+
+ for i in range(0x40, 0xFF):
+ chunk: str = p.decode(bytes([i]))
+
+ if chunk:
+ character_range: str | None = unicode_range(chunk)
+
+ if character_range is None:
+ continue
+
+ if is_unicode_range_secondary(character_range) is False:
+ if character_range not in seen_ranges:
+ seen_ranges[character_range] = 0
+ seen_ranges[character_range] += 1
+ character_count += 1
+
+ return sorted(
+ [
+ character_range
+ for character_range in seen_ranges
+ if seen_ranges[character_range] / character_count >= 0.15
+ ]
+ )
+
+
+def unicode_range_languages(primary_range: str) -> list[str]:
+ """
+ Return inferred languages used with a unicode range.
+ """
+ languages: list[str] = []
+
+ for language, characters in FREQUENCIES.items():
+ for character in characters:
+ if unicode_range(character) == primary_range:
+ languages.append(language)
+ break
+
+ return languages
+
+
+@lru_cache()
+def encoding_languages(iana_name: str) -> list[str]:
+ """
+ Single-byte encoding language association. Some code page are heavily linked to particular language(s).
+ This function does the correspondence.
+ """
+ unicode_ranges: list[str] = encoding_unicode_range(iana_name)
+ primary_range: str | None = None
+
+ for specified_range in unicode_ranges:
+ if "Latin" not in specified_range:
+ primary_range = specified_range
+ break
+
+ if primary_range is None:
+ return ["Latin Based"]
+
+ return unicode_range_languages(primary_range)
+
+
+@lru_cache()
+def mb_encoding_languages(iana_name: str) -> list[str]:
+ """
+ Multi-byte encoding language association. Some code page are heavily linked to particular language(s).
+ This function does the correspondence.
+ """
+ if (
+ iana_name.startswith("shift_")
+ or iana_name.startswith("iso2022_jp")
+ or iana_name.startswith("euc_j")
+ or iana_name == "cp932"
+ ):
+ return ["Japanese"]
+ if iana_name.startswith("gb") or iana_name in ZH_NAMES:
+ return ["Chinese"]
+ if iana_name.startswith("iso2022_kr") or iana_name in KO_NAMES:
+ return ["Korean"]
+
+ return []
+
+
+@lru_cache(maxsize=LANGUAGE_SUPPORTED_COUNT)
+def get_target_features(language: str) -> tuple[bool, bool]:
+ """
+ Determine main aspects from a supported language if it contains accents and if is pure Latin.
+ """
+ target_have_accents: bool = False
+ target_pure_latin: bool = True
+
+ for character in FREQUENCIES[language]:
+ if not target_have_accents and is_accentuated(character):
+ target_have_accents = True
+ if target_pure_latin and is_latin(character) is False:
+ target_pure_latin = False
+
+ return target_have_accents, target_pure_latin
+
+
+def alphabet_languages(
+ characters: list[str], ignore_non_latin: bool = False
+) -> list[str]:
+ """
+ Return associated languages associated to given characters.
+ """
+ languages: list[tuple[str, float]] = []
+
+ source_have_accents = any(is_accentuated(character) for character in characters)
+
+ for language, language_characters in FREQUENCIES.items():
+ target_have_accents, target_pure_latin = get_target_features(language)
+
+ if ignore_non_latin and target_pure_latin is False:
+ continue
+
+ if target_have_accents is False and source_have_accents:
+ continue
+
+ character_count: int = len(language_characters)
+
+ character_match_count: int = len(
+ [c for c in language_characters if c in characters]
+ )
+
+ ratio: float = character_match_count / character_count
+
+ if ratio >= 0.2:
+ languages.append((language, ratio))
+
+ languages = sorted(languages, key=lambda x: x[1], reverse=True)
+
+ return [compatible_language[0] for compatible_language in languages]
+
+
+def characters_popularity_compare(
+ language: str, ordered_characters: list[str]
+) -> float:
+ """
+ Determine if a ordered characters list (by occurrence from most appearance to rarest) match a particular language.
+ The result is a ratio between 0. (absolutely no correspondence) and 1. (near perfect fit).
+ Beware that is function is not strict on the match in order to ease the detection. (Meaning close match is 1.)
+ """
+ if language not in FREQUENCIES:
+ raise ValueError(f"{language} not available")
+
+ character_approved_count: int = 0
+ FREQUENCIES_language_set = set(FREQUENCIES[language])
+
+ ordered_characters_count: int = len(ordered_characters)
+ target_language_characters_count: int = len(FREQUENCIES[language])
+
+ large_alphabet: bool = target_language_characters_count > 26
+
+ for character, character_rank in zip(
+ ordered_characters, range(0, ordered_characters_count)
+ ):
+ if character not in FREQUENCIES_language_set:
+ continue
+
+ character_rank_in_language: int = FREQUENCIES[language].index(character)
+ expected_projection_ratio: float = (
+ target_language_characters_count / ordered_characters_count
+ )
+ character_rank_projection: int = int(character_rank * expected_projection_ratio)
+
+ if (
+ large_alphabet is False
+ and abs(character_rank_projection - character_rank_in_language) > 4
+ ):
+ continue
+
+ if (
+ large_alphabet is True
+ and abs(character_rank_projection - character_rank_in_language)
+ < target_language_characters_count / 3
+ ):
+ character_approved_count += 1
+ continue
+
+ characters_before_source: list[str] = FREQUENCIES[language][
+ 0:character_rank_in_language
+ ]
+ characters_after_source: list[str] = FREQUENCIES[language][
+ character_rank_in_language:
+ ]
+ characters_before: list[str] = ordered_characters[0:character_rank]
+ characters_after: list[str] = ordered_characters[character_rank:]
+
+ before_match_count: int = len(
+ set(characters_before) & set(characters_before_source)
+ )
+
+ after_match_count: int = len(
+ set(characters_after) & set(characters_after_source)
+ )
+
+ if len(characters_before_source) == 0 and before_match_count <= 4:
+ character_approved_count += 1
+ continue
+
+ if len(characters_after_source) == 0 and after_match_count <= 4:
+ character_approved_count += 1
+ continue
+
+ if (
+ before_match_count / len(characters_before_source) >= 0.4
+ or after_match_count / len(characters_after_source) >= 0.4
+ ):
+ character_approved_count += 1
+ continue
+
+ return character_approved_count / len(ordered_characters)
+
+
+def alpha_unicode_split(decoded_sequence: str) -> list[str]:
+ """
+ Given a decoded text sequence, return a list of str. Unicode range / alphabet separation.
+ Ex. a text containing English/Latin with a bit a Hebrew will return two items in the resulting list;
+ One containing the latin letters and the other hebrew.
+ """
+ layers: dict[str, str] = {}
+
+ for character in decoded_sequence:
+ if character.isalpha() is False:
+ continue
+
+ character_range: str | None = unicode_range(character)
+
+ if character_range is None:
+ continue
+
+ layer_target_range: str | None = None
+
+ for discovered_range in layers:
+ if (
+ is_suspiciously_successive_range(discovered_range, character_range)
+ is False
+ ):
+ layer_target_range = discovered_range
+ break
+
+ if layer_target_range is None:
+ layer_target_range = character_range
+
+ if layer_target_range not in layers:
+ layers[layer_target_range] = character.lower()
+ continue
+
+ layers[layer_target_range] += character.lower()
+
+ return list(layers.values())
+
+
+def merge_coherence_ratios(results: list[CoherenceMatches]) -> CoherenceMatches:
+ """
+ This function merge results previously given by the function coherence_ratio.
+ The return type is the same as coherence_ratio.
+ """
+ per_language_ratios: dict[str, list[float]] = {}
+ for result in results:
+ for sub_result in result:
+ language, ratio = sub_result
+ if language not in per_language_ratios:
+ per_language_ratios[language] = [ratio]
+ continue
+ per_language_ratios[language].append(ratio)
+
+ merge = [
+ (
+ language,
+ round(
+ sum(per_language_ratios[language]) / len(per_language_ratios[language]),
+ 4,
+ ),
+ )
+ for language in per_language_ratios
+ ]
+
+ return sorted(merge, key=lambda x: x[1], reverse=True)
+
+
+def filter_alt_coherence_matches(results: CoherenceMatches) -> CoherenceMatches:
+ """
+ We shall NOT return "English—" in CoherenceMatches because it is an alternative
+ of "English". This function only keeps the best match and remove the em-dash in it.
+ """
+ index_results: dict[str, list[float]] = dict()
+
+ for result in results:
+ language, ratio = result
+ no_em_name: str = language.replace("—", "")
+
+ if no_em_name not in index_results:
+ index_results[no_em_name] = []
+
+ index_results[no_em_name].append(ratio)
+
+ if any(len(index_results[e]) > 1 for e in index_results):
+ filtered_results: CoherenceMatches = []
+
+ for language in index_results:
+ filtered_results.append((language, max(index_results[language])))
+
+ return filtered_results
+
+ return results
+
+
+@lru_cache(maxsize=2048)
+def coherence_ratio(
+ decoded_sequence: str, threshold: float = 0.1, lg_inclusion: str | None = None
+) -> CoherenceMatches:
+ """
+ Detect ANY language that can be identified in given sequence. The sequence will be analysed by layers.
+ A layer = Character extraction by alphabets/ranges.
+ """
+
+ results: list[tuple[str, float]] = []
+ ignore_non_latin: bool = False
+
+ sufficient_match_count: int = 0
+
+ lg_inclusion_list = lg_inclusion.split(",") if lg_inclusion is not None else []
+ if "Latin Based" in lg_inclusion_list:
+ ignore_non_latin = True
+ lg_inclusion_list.remove("Latin Based")
+
+ for layer in alpha_unicode_split(decoded_sequence):
+ sequence_frequencies: TypeCounter[str] = Counter(layer)
+ most_common = sequence_frequencies.most_common()
+
+ character_count: int = sum(o for c, o in most_common)
+
+ if character_count <= TOO_SMALL_SEQUENCE:
+ continue
+
+ popular_character_ordered: list[str] = [c for c, o in most_common]
+
+ for language in lg_inclusion_list or alphabet_languages(
+ popular_character_ordered, ignore_non_latin
+ ):
+ ratio: float = characters_popularity_compare(
+ language, popular_character_ordered
+ )
+
+ if ratio < threshold:
+ continue
+ elif ratio >= 0.8:
+ sufficient_match_count += 1
+
+ results.append((language, round(ratio, 4)))
+
+ if sufficient_match_count >= 3:
+ break
+
+ return sorted(
+ filter_alt_coherence_matches(results), key=lambda x: x[1], reverse=True
+ )
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__init__.py b/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__init__.py
new file mode 100644
index 0000000..543a5a4
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__init__.py
@@ -0,0 +1,8 @@
+from __future__ import annotations
+
+from .__main__ import cli_detect, query_yes_no
+
+__all__ = (
+ "cli_detect",
+ "query_yes_no",
+)
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__main__.py b/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__main__.py
new file mode 100644
index 0000000..64a290f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__main__.py
@@ -0,0 +1,321 @@
+from __future__ import annotations
+
+import argparse
+import sys
+from json import dumps
+from os.path import abspath, basename, dirname, join, realpath
+from platform import python_version
+from unicodedata import unidata_version
+
+import charset_normalizer.md as md_module
+from charset_normalizer import from_fp
+from charset_normalizer.models import CliDetectionResult
+from charset_normalizer.version import __version__
+
+
+def query_yes_no(question: str, default: str = "yes") -> bool:
+ """Ask a yes/no question via input() and return their answer.
+
+ "question" is a string that is presented to the user.
+ "default" is the presumed answer if the user just hits .
+ It must be "yes" (the default), "no" or None (meaning
+ an answer is required of the user).
+
+ The "answer" return value is True for "yes" or False for "no".
+
+ Credit goes to (c) https://stackoverflow.com/questions/3041986/apt-command-line-interface-like-yes-no-input
+ """
+ valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False}
+ if default is None:
+ prompt = " [y/n] "
+ elif default == "yes":
+ prompt = " [Y/n] "
+ elif default == "no":
+ prompt = " [y/N] "
+ else:
+ raise ValueError("invalid default answer: '%s'" % default)
+
+ while True:
+ sys.stdout.write(question + prompt)
+ choice = input().lower()
+ if default is not None and choice == "":
+ return valid[default]
+ elif choice in valid:
+ return valid[choice]
+ else:
+ sys.stdout.write("Please respond with 'yes' or 'no' " "(or 'y' or 'n').\n")
+
+
+def cli_detect(argv: list[str] | None = None) -> int:
+ """
+ CLI assistant using ARGV and ArgumentParser
+ :param argv:
+ :return: 0 if everything is fine, anything else equal trouble
+ """
+ parser = argparse.ArgumentParser(
+ description="The Real First Universal Charset Detector. "
+ "Discover originating encoding used on text file. "
+ "Normalize text to unicode."
+ )
+
+ parser.add_argument(
+ "files", type=argparse.FileType("rb"), nargs="+", help="File(s) to be analysed"
+ )
+ parser.add_argument(
+ "-v",
+ "--verbose",
+ action="store_true",
+ default=False,
+ dest="verbose",
+ help="Display complementary information about file if any. "
+ "Stdout will contain logs about the detection process.",
+ )
+ parser.add_argument(
+ "-a",
+ "--with-alternative",
+ action="store_true",
+ default=False,
+ dest="alternatives",
+ help="Output complementary possibilities if any. Top-level JSON WILL be a list.",
+ )
+ parser.add_argument(
+ "-n",
+ "--normalize",
+ action="store_true",
+ default=False,
+ dest="normalize",
+ help="Permit to normalize input file. If not set, program does not write anything.",
+ )
+ parser.add_argument(
+ "-m",
+ "--minimal",
+ action="store_true",
+ default=False,
+ dest="minimal",
+ help="Only output the charset detected to STDOUT. Disabling JSON output.",
+ )
+ parser.add_argument(
+ "-r",
+ "--replace",
+ action="store_true",
+ default=False,
+ dest="replace",
+ help="Replace file when trying to normalize it instead of creating a new one.",
+ )
+ parser.add_argument(
+ "-f",
+ "--force",
+ action="store_true",
+ default=False,
+ dest="force",
+ help="Replace file without asking if you are sure, use this flag with caution.",
+ )
+ parser.add_argument(
+ "-i",
+ "--no-preemptive",
+ action="store_true",
+ default=False,
+ dest="no_preemptive",
+ help="Disable looking at a charset declaration to hint the detector.",
+ )
+ parser.add_argument(
+ "-t",
+ "--threshold",
+ action="store",
+ default=0.2,
+ type=float,
+ dest="threshold",
+ help="Define a custom maximum amount of noise allowed in decoded content. 0. <= noise <= 1.",
+ )
+ parser.add_argument(
+ "--version",
+ action="version",
+ version="Charset-Normalizer {} - Python {} - Unicode {} - SpeedUp {}".format(
+ __version__,
+ python_version(),
+ unidata_version,
+ "OFF" if md_module.__file__.lower().endswith(".py") else "ON",
+ ),
+ help="Show version information and exit.",
+ )
+
+ args = parser.parse_args(argv)
+
+ if args.replace is True and args.normalize is False:
+ if args.files:
+ for my_file in args.files:
+ my_file.close()
+ print("Use --replace in addition of --normalize only.", file=sys.stderr)
+ return 1
+
+ if args.force is True and args.replace is False:
+ if args.files:
+ for my_file in args.files:
+ my_file.close()
+ print("Use --force in addition of --replace only.", file=sys.stderr)
+ return 1
+
+ if args.threshold < 0.0 or args.threshold > 1.0:
+ if args.files:
+ for my_file in args.files:
+ my_file.close()
+ print("--threshold VALUE should be between 0. AND 1.", file=sys.stderr)
+ return 1
+
+ x_ = []
+
+ for my_file in args.files:
+ matches = from_fp(
+ my_file,
+ threshold=args.threshold,
+ explain=args.verbose,
+ preemptive_behaviour=args.no_preemptive is False,
+ )
+
+ best_guess = matches.best()
+
+ if best_guess is None:
+ print(
+ 'Unable to identify originating encoding for "{}". {}'.format(
+ my_file.name,
+ (
+ "Maybe try increasing maximum amount of chaos."
+ if args.threshold < 1.0
+ else ""
+ ),
+ ),
+ file=sys.stderr,
+ )
+ x_.append(
+ CliDetectionResult(
+ abspath(my_file.name),
+ None,
+ [],
+ [],
+ "Unknown",
+ [],
+ False,
+ 1.0,
+ 0.0,
+ None,
+ True,
+ )
+ )
+ else:
+ x_.append(
+ CliDetectionResult(
+ abspath(my_file.name),
+ best_guess.encoding,
+ best_guess.encoding_aliases,
+ [
+ cp
+ for cp in best_guess.could_be_from_charset
+ if cp != best_guess.encoding
+ ],
+ best_guess.language,
+ best_guess.alphabets,
+ best_guess.bom,
+ best_guess.percent_chaos,
+ best_guess.percent_coherence,
+ None,
+ True,
+ )
+ )
+
+ if len(matches) > 1 and args.alternatives:
+ for el in matches:
+ if el != best_guess:
+ x_.append(
+ CliDetectionResult(
+ abspath(my_file.name),
+ el.encoding,
+ el.encoding_aliases,
+ [
+ cp
+ for cp in el.could_be_from_charset
+ if cp != el.encoding
+ ],
+ el.language,
+ el.alphabets,
+ el.bom,
+ el.percent_chaos,
+ el.percent_coherence,
+ None,
+ False,
+ )
+ )
+
+ if args.normalize is True:
+ if best_guess.encoding.startswith("utf") is True:
+ print(
+ '"{}" file does not need to be normalized, as it already came from unicode.'.format(
+ my_file.name
+ ),
+ file=sys.stderr,
+ )
+ if my_file.closed is False:
+ my_file.close()
+ continue
+
+ dir_path = dirname(realpath(my_file.name))
+ file_name = basename(realpath(my_file.name))
+
+ o_: list[str] = file_name.split(".")
+
+ if args.replace is False:
+ o_.insert(-1, best_guess.encoding)
+ if my_file.closed is False:
+ my_file.close()
+ elif (
+ args.force is False
+ and query_yes_no(
+ 'Are you sure to normalize "{}" by replacing it ?'.format(
+ my_file.name
+ ),
+ "no",
+ )
+ is False
+ ):
+ if my_file.closed is False:
+ my_file.close()
+ continue
+
+ try:
+ x_[0].unicode_path = join(dir_path, ".".join(o_))
+
+ with open(x_[0].unicode_path, "wb") as fp:
+ fp.write(best_guess.output())
+ except OSError as e:
+ print(str(e), file=sys.stderr)
+ if my_file.closed is False:
+ my_file.close()
+ return 2
+
+ if my_file.closed is False:
+ my_file.close()
+
+ if args.minimal is False:
+ print(
+ dumps(
+ [el.__dict__ for el in x_] if len(x_) > 1 else x_[0].__dict__,
+ ensure_ascii=True,
+ indent=4,
+ )
+ )
+ else:
+ for my_file in args.files:
+ print(
+ ", ".join(
+ [
+ el.encoding or "undefined"
+ for el in x_
+ if el.path == abspath(my_file.name)
+ ]
+ )
+ )
+
+ return 0
+
+
+if __name__ == "__main__":
+ cli_detect()
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..d62464a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc
new file mode 100644
index 0000000..4b8dd06
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/constant.py b/testcline/lib/python3.12/site-packages/charset_normalizer/constant.py
new file mode 100644
index 0000000..1fb9508
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/constant.py
@@ -0,0 +1,1998 @@
+from __future__ import annotations
+
+from codecs import BOM_UTF8, BOM_UTF16_BE, BOM_UTF16_LE, BOM_UTF32_BE, BOM_UTF32_LE
+from encodings.aliases import aliases
+from re import IGNORECASE
+from re import compile as re_compile
+
+# Contain for each eligible encoding a list of/item bytes SIG/BOM
+ENCODING_MARKS: dict[str, bytes | list[bytes]] = {
+ "utf_8": BOM_UTF8,
+ "utf_7": [
+ b"\x2b\x2f\x76\x38",
+ b"\x2b\x2f\x76\x39",
+ b"\x2b\x2f\x76\x2b",
+ b"\x2b\x2f\x76\x2f",
+ b"\x2b\x2f\x76\x38\x2d",
+ ],
+ "gb18030": b"\x84\x31\x95\x33",
+ "utf_32": [BOM_UTF32_BE, BOM_UTF32_LE],
+ "utf_16": [BOM_UTF16_BE, BOM_UTF16_LE],
+}
+
+TOO_SMALL_SEQUENCE: int = 32
+TOO_BIG_SEQUENCE: int = int(10e6)
+
+UTF8_MAXIMAL_ALLOCATION: int = 1_112_064
+
+# Up-to-date Unicode ucd/15.0.0
+UNICODE_RANGES_COMBINED: dict[str, range] = {
+ "Control character": range(32),
+ "Basic Latin": range(32, 128),
+ "Latin-1 Supplement": range(128, 256),
+ "Latin Extended-A": range(256, 384),
+ "Latin Extended-B": range(384, 592),
+ "IPA Extensions": range(592, 688),
+ "Spacing Modifier Letters": range(688, 768),
+ "Combining Diacritical Marks": range(768, 880),
+ "Greek and Coptic": range(880, 1024),
+ "Cyrillic": range(1024, 1280),
+ "Cyrillic Supplement": range(1280, 1328),
+ "Armenian": range(1328, 1424),
+ "Hebrew": range(1424, 1536),
+ "Arabic": range(1536, 1792),
+ "Syriac": range(1792, 1872),
+ "Arabic Supplement": range(1872, 1920),
+ "Thaana": range(1920, 1984),
+ "NKo": range(1984, 2048),
+ "Samaritan": range(2048, 2112),
+ "Mandaic": range(2112, 2144),
+ "Syriac Supplement": range(2144, 2160),
+ "Arabic Extended-B": range(2160, 2208),
+ "Arabic Extended-A": range(2208, 2304),
+ "Devanagari": range(2304, 2432),
+ "Bengali": range(2432, 2560),
+ "Gurmukhi": range(2560, 2688),
+ "Gujarati": range(2688, 2816),
+ "Oriya": range(2816, 2944),
+ "Tamil": range(2944, 3072),
+ "Telugu": range(3072, 3200),
+ "Kannada": range(3200, 3328),
+ "Malayalam": range(3328, 3456),
+ "Sinhala": range(3456, 3584),
+ "Thai": range(3584, 3712),
+ "Lao": range(3712, 3840),
+ "Tibetan": range(3840, 4096),
+ "Myanmar": range(4096, 4256),
+ "Georgian": range(4256, 4352),
+ "Hangul Jamo": range(4352, 4608),
+ "Ethiopic": range(4608, 4992),
+ "Ethiopic Supplement": range(4992, 5024),
+ "Cherokee": range(5024, 5120),
+ "Unified Canadian Aboriginal Syllabics": range(5120, 5760),
+ "Ogham": range(5760, 5792),
+ "Runic": range(5792, 5888),
+ "Tagalog": range(5888, 5920),
+ "Hanunoo": range(5920, 5952),
+ "Buhid": range(5952, 5984),
+ "Tagbanwa": range(5984, 6016),
+ "Khmer": range(6016, 6144),
+ "Mongolian": range(6144, 6320),
+ "Unified Canadian Aboriginal Syllabics Extended": range(6320, 6400),
+ "Limbu": range(6400, 6480),
+ "Tai Le": range(6480, 6528),
+ "New Tai Lue": range(6528, 6624),
+ "Khmer Symbols": range(6624, 6656),
+ "Buginese": range(6656, 6688),
+ "Tai Tham": range(6688, 6832),
+ "Combining Diacritical Marks Extended": range(6832, 6912),
+ "Balinese": range(6912, 7040),
+ "Sundanese": range(7040, 7104),
+ "Batak": range(7104, 7168),
+ "Lepcha": range(7168, 7248),
+ "Ol Chiki": range(7248, 7296),
+ "Cyrillic Extended-C": range(7296, 7312),
+ "Georgian Extended": range(7312, 7360),
+ "Sundanese Supplement": range(7360, 7376),
+ "Vedic Extensions": range(7376, 7424),
+ "Phonetic Extensions": range(7424, 7552),
+ "Phonetic Extensions Supplement": range(7552, 7616),
+ "Combining Diacritical Marks Supplement": range(7616, 7680),
+ "Latin Extended Additional": range(7680, 7936),
+ "Greek Extended": range(7936, 8192),
+ "General Punctuation": range(8192, 8304),
+ "Superscripts and Subscripts": range(8304, 8352),
+ "Currency Symbols": range(8352, 8400),
+ "Combining Diacritical Marks for Symbols": range(8400, 8448),
+ "Letterlike Symbols": range(8448, 8528),
+ "Number Forms": range(8528, 8592),
+ "Arrows": range(8592, 8704),
+ "Mathematical Operators": range(8704, 8960),
+ "Miscellaneous Technical": range(8960, 9216),
+ "Control Pictures": range(9216, 9280),
+ "Optical Character Recognition": range(9280, 9312),
+ "Enclosed Alphanumerics": range(9312, 9472),
+ "Box Drawing": range(9472, 9600),
+ "Block Elements": range(9600, 9632),
+ "Geometric Shapes": range(9632, 9728),
+ "Miscellaneous Symbols": range(9728, 9984),
+ "Dingbats": range(9984, 10176),
+ "Miscellaneous Mathematical Symbols-A": range(10176, 10224),
+ "Supplemental Arrows-A": range(10224, 10240),
+ "Braille Patterns": range(10240, 10496),
+ "Supplemental Arrows-B": range(10496, 10624),
+ "Miscellaneous Mathematical Symbols-B": range(10624, 10752),
+ "Supplemental Mathematical Operators": range(10752, 11008),
+ "Miscellaneous Symbols and Arrows": range(11008, 11264),
+ "Glagolitic": range(11264, 11360),
+ "Latin Extended-C": range(11360, 11392),
+ "Coptic": range(11392, 11520),
+ "Georgian Supplement": range(11520, 11568),
+ "Tifinagh": range(11568, 11648),
+ "Ethiopic Extended": range(11648, 11744),
+ "Cyrillic Extended-A": range(11744, 11776),
+ "Supplemental Punctuation": range(11776, 11904),
+ "CJK Radicals Supplement": range(11904, 12032),
+ "Kangxi Radicals": range(12032, 12256),
+ "Ideographic Description Characters": range(12272, 12288),
+ "CJK Symbols and Punctuation": range(12288, 12352),
+ "Hiragana": range(12352, 12448),
+ "Katakana": range(12448, 12544),
+ "Bopomofo": range(12544, 12592),
+ "Hangul Compatibility Jamo": range(12592, 12688),
+ "Kanbun": range(12688, 12704),
+ "Bopomofo Extended": range(12704, 12736),
+ "CJK Strokes": range(12736, 12784),
+ "Katakana Phonetic Extensions": range(12784, 12800),
+ "Enclosed CJK Letters and Months": range(12800, 13056),
+ "CJK Compatibility": range(13056, 13312),
+ "CJK Unified Ideographs Extension A": range(13312, 19904),
+ "Yijing Hexagram Symbols": range(19904, 19968),
+ "CJK Unified Ideographs": range(19968, 40960),
+ "Yi Syllables": range(40960, 42128),
+ "Yi Radicals": range(42128, 42192),
+ "Lisu": range(42192, 42240),
+ "Vai": range(42240, 42560),
+ "Cyrillic Extended-B": range(42560, 42656),
+ "Bamum": range(42656, 42752),
+ "Modifier Tone Letters": range(42752, 42784),
+ "Latin Extended-D": range(42784, 43008),
+ "Syloti Nagri": range(43008, 43056),
+ "Common Indic Number Forms": range(43056, 43072),
+ "Phags-pa": range(43072, 43136),
+ "Saurashtra": range(43136, 43232),
+ "Devanagari Extended": range(43232, 43264),
+ "Kayah Li": range(43264, 43312),
+ "Rejang": range(43312, 43360),
+ "Hangul Jamo Extended-A": range(43360, 43392),
+ "Javanese": range(43392, 43488),
+ "Myanmar Extended-B": range(43488, 43520),
+ "Cham": range(43520, 43616),
+ "Myanmar Extended-A": range(43616, 43648),
+ "Tai Viet": range(43648, 43744),
+ "Meetei Mayek Extensions": range(43744, 43776),
+ "Ethiopic Extended-A": range(43776, 43824),
+ "Latin Extended-E": range(43824, 43888),
+ "Cherokee Supplement": range(43888, 43968),
+ "Meetei Mayek": range(43968, 44032),
+ "Hangul Syllables": range(44032, 55216),
+ "Hangul Jamo Extended-B": range(55216, 55296),
+ "High Surrogates": range(55296, 56192),
+ "High Private Use Surrogates": range(56192, 56320),
+ "Low Surrogates": range(56320, 57344),
+ "Private Use Area": range(57344, 63744),
+ "CJK Compatibility Ideographs": range(63744, 64256),
+ "Alphabetic Presentation Forms": range(64256, 64336),
+ "Arabic Presentation Forms-A": range(64336, 65024),
+ "Variation Selectors": range(65024, 65040),
+ "Vertical Forms": range(65040, 65056),
+ "Combining Half Marks": range(65056, 65072),
+ "CJK Compatibility Forms": range(65072, 65104),
+ "Small Form Variants": range(65104, 65136),
+ "Arabic Presentation Forms-B": range(65136, 65280),
+ "Halfwidth and Fullwidth Forms": range(65280, 65520),
+ "Specials": range(65520, 65536),
+ "Linear B Syllabary": range(65536, 65664),
+ "Linear B Ideograms": range(65664, 65792),
+ "Aegean Numbers": range(65792, 65856),
+ "Ancient Greek Numbers": range(65856, 65936),
+ "Ancient Symbols": range(65936, 66000),
+ "Phaistos Disc": range(66000, 66048),
+ "Lycian": range(66176, 66208),
+ "Carian": range(66208, 66272),
+ "Coptic Epact Numbers": range(66272, 66304),
+ "Old Italic": range(66304, 66352),
+ "Gothic": range(66352, 66384),
+ "Old Permic": range(66384, 66432),
+ "Ugaritic": range(66432, 66464),
+ "Old Persian": range(66464, 66528),
+ "Deseret": range(66560, 66640),
+ "Shavian": range(66640, 66688),
+ "Osmanya": range(66688, 66736),
+ "Osage": range(66736, 66816),
+ "Elbasan": range(66816, 66864),
+ "Caucasian Albanian": range(66864, 66928),
+ "Vithkuqi": range(66928, 67008),
+ "Linear A": range(67072, 67456),
+ "Latin Extended-F": range(67456, 67520),
+ "Cypriot Syllabary": range(67584, 67648),
+ "Imperial Aramaic": range(67648, 67680),
+ "Palmyrene": range(67680, 67712),
+ "Nabataean": range(67712, 67760),
+ "Hatran": range(67808, 67840),
+ "Phoenician": range(67840, 67872),
+ "Lydian": range(67872, 67904),
+ "Meroitic Hieroglyphs": range(67968, 68000),
+ "Meroitic Cursive": range(68000, 68096),
+ "Kharoshthi": range(68096, 68192),
+ "Old South Arabian": range(68192, 68224),
+ "Old North Arabian": range(68224, 68256),
+ "Manichaean": range(68288, 68352),
+ "Avestan": range(68352, 68416),
+ "Inscriptional Parthian": range(68416, 68448),
+ "Inscriptional Pahlavi": range(68448, 68480),
+ "Psalter Pahlavi": range(68480, 68528),
+ "Old Turkic": range(68608, 68688),
+ "Old Hungarian": range(68736, 68864),
+ "Hanifi Rohingya": range(68864, 68928),
+ "Rumi Numeral Symbols": range(69216, 69248),
+ "Yezidi": range(69248, 69312),
+ "Arabic Extended-C": range(69312, 69376),
+ "Old Sogdian": range(69376, 69424),
+ "Sogdian": range(69424, 69488),
+ "Old Uyghur": range(69488, 69552),
+ "Chorasmian": range(69552, 69600),
+ "Elymaic": range(69600, 69632),
+ "Brahmi": range(69632, 69760),
+ "Kaithi": range(69760, 69840),
+ "Sora Sompeng": range(69840, 69888),
+ "Chakma": range(69888, 69968),
+ "Mahajani": range(69968, 70016),
+ "Sharada": range(70016, 70112),
+ "Sinhala Archaic Numbers": range(70112, 70144),
+ "Khojki": range(70144, 70224),
+ "Multani": range(70272, 70320),
+ "Khudawadi": range(70320, 70400),
+ "Grantha": range(70400, 70528),
+ "Newa": range(70656, 70784),
+ "Tirhuta": range(70784, 70880),
+ "Siddham": range(71040, 71168),
+ "Modi": range(71168, 71264),
+ "Mongolian Supplement": range(71264, 71296),
+ "Takri": range(71296, 71376),
+ "Ahom": range(71424, 71504),
+ "Dogra": range(71680, 71760),
+ "Warang Citi": range(71840, 71936),
+ "Dives Akuru": range(71936, 72032),
+ "Nandinagari": range(72096, 72192),
+ "Zanabazar Square": range(72192, 72272),
+ "Soyombo": range(72272, 72368),
+ "Unified Canadian Aboriginal Syllabics Extended-A": range(72368, 72384),
+ "Pau Cin Hau": range(72384, 72448),
+ "Devanagari Extended-A": range(72448, 72544),
+ "Bhaiksuki": range(72704, 72816),
+ "Marchen": range(72816, 72896),
+ "Masaram Gondi": range(72960, 73056),
+ "Gunjala Gondi": range(73056, 73136),
+ "Makasar": range(73440, 73472),
+ "Kawi": range(73472, 73568),
+ "Lisu Supplement": range(73648, 73664),
+ "Tamil Supplement": range(73664, 73728),
+ "Cuneiform": range(73728, 74752),
+ "Cuneiform Numbers and Punctuation": range(74752, 74880),
+ "Early Dynastic Cuneiform": range(74880, 75088),
+ "Cypro-Minoan": range(77712, 77824),
+ "Egyptian Hieroglyphs": range(77824, 78896),
+ "Egyptian Hieroglyph Format Controls": range(78896, 78944),
+ "Anatolian Hieroglyphs": range(82944, 83584),
+ "Bamum Supplement": range(92160, 92736),
+ "Mro": range(92736, 92784),
+ "Tangsa": range(92784, 92880),
+ "Bassa Vah": range(92880, 92928),
+ "Pahawh Hmong": range(92928, 93072),
+ "Medefaidrin": range(93760, 93856),
+ "Miao": range(93952, 94112),
+ "Ideographic Symbols and Punctuation": range(94176, 94208),
+ "Tangut": range(94208, 100352),
+ "Tangut Components": range(100352, 101120),
+ "Khitan Small Script": range(101120, 101632),
+ "Tangut Supplement": range(101632, 101760),
+ "Kana Extended-B": range(110576, 110592),
+ "Kana Supplement": range(110592, 110848),
+ "Kana Extended-A": range(110848, 110896),
+ "Small Kana Extension": range(110896, 110960),
+ "Nushu": range(110960, 111360),
+ "Duployan": range(113664, 113824),
+ "Shorthand Format Controls": range(113824, 113840),
+ "Znamenny Musical Notation": range(118528, 118736),
+ "Byzantine Musical Symbols": range(118784, 119040),
+ "Musical Symbols": range(119040, 119296),
+ "Ancient Greek Musical Notation": range(119296, 119376),
+ "Kaktovik Numerals": range(119488, 119520),
+ "Mayan Numerals": range(119520, 119552),
+ "Tai Xuan Jing Symbols": range(119552, 119648),
+ "Counting Rod Numerals": range(119648, 119680),
+ "Mathematical Alphanumeric Symbols": range(119808, 120832),
+ "Sutton SignWriting": range(120832, 121520),
+ "Latin Extended-G": range(122624, 122880),
+ "Glagolitic Supplement": range(122880, 122928),
+ "Cyrillic Extended-D": range(122928, 123024),
+ "Nyiakeng Puachue Hmong": range(123136, 123216),
+ "Toto": range(123536, 123584),
+ "Wancho": range(123584, 123648),
+ "Nag Mundari": range(124112, 124160),
+ "Ethiopic Extended-B": range(124896, 124928),
+ "Mende Kikakui": range(124928, 125152),
+ "Adlam": range(125184, 125280),
+ "Indic Siyaq Numbers": range(126064, 126144),
+ "Ottoman Siyaq Numbers": range(126208, 126288),
+ "Arabic Mathematical Alphabetic Symbols": range(126464, 126720),
+ "Mahjong Tiles": range(126976, 127024),
+ "Domino Tiles": range(127024, 127136),
+ "Playing Cards": range(127136, 127232),
+ "Enclosed Alphanumeric Supplement": range(127232, 127488),
+ "Enclosed Ideographic Supplement": range(127488, 127744),
+ "Miscellaneous Symbols and Pictographs": range(127744, 128512),
+ "Emoticons range(Emoji)": range(128512, 128592),
+ "Ornamental Dingbats": range(128592, 128640),
+ "Transport and Map Symbols": range(128640, 128768),
+ "Alchemical Symbols": range(128768, 128896),
+ "Geometric Shapes Extended": range(128896, 129024),
+ "Supplemental Arrows-C": range(129024, 129280),
+ "Supplemental Symbols and Pictographs": range(129280, 129536),
+ "Chess Symbols": range(129536, 129648),
+ "Symbols and Pictographs Extended-A": range(129648, 129792),
+ "Symbols for Legacy Computing": range(129792, 130048),
+ "CJK Unified Ideographs Extension B": range(131072, 173792),
+ "CJK Unified Ideographs Extension C": range(173824, 177984),
+ "CJK Unified Ideographs Extension D": range(177984, 178208),
+ "CJK Unified Ideographs Extension E": range(178208, 183984),
+ "CJK Unified Ideographs Extension F": range(183984, 191472),
+ "CJK Compatibility Ideographs Supplement": range(194560, 195104),
+ "CJK Unified Ideographs Extension G": range(196608, 201552),
+ "CJK Unified Ideographs Extension H": range(201552, 205744),
+ "Tags": range(917504, 917632),
+ "Variation Selectors Supplement": range(917760, 918000),
+ "Supplementary Private Use Area-A": range(983040, 1048576),
+ "Supplementary Private Use Area-B": range(1048576, 1114112),
+}
+
+
+UNICODE_SECONDARY_RANGE_KEYWORD: list[str] = [
+ "Supplement",
+ "Extended",
+ "Extensions",
+ "Modifier",
+ "Marks",
+ "Punctuation",
+ "Symbols",
+ "Forms",
+ "Operators",
+ "Miscellaneous",
+ "Drawing",
+ "Block",
+ "Shapes",
+ "Supplemental",
+ "Tags",
+]
+
+RE_POSSIBLE_ENCODING_INDICATION = re_compile(
+ r"(?:(?:encoding)|(?:charset)|(?:coding))(?:[\:= ]{1,10})(?:[\"\']?)([a-zA-Z0-9\-_]+)(?:[\"\']?)",
+ IGNORECASE,
+)
+
+IANA_NO_ALIASES = [
+ "cp720",
+ "cp737",
+ "cp856",
+ "cp874",
+ "cp875",
+ "cp1006",
+ "koi8_r",
+ "koi8_t",
+ "koi8_u",
+]
+
+IANA_SUPPORTED: list[str] = sorted(
+ filter(
+ lambda x: x.endswith("_codec") is False
+ and x not in {"rot_13", "tactis", "mbcs"},
+ list(set(aliases.values())) + IANA_NO_ALIASES,
+ )
+)
+
+IANA_SUPPORTED_COUNT: int = len(IANA_SUPPORTED)
+
+# pre-computed code page that are similar using the function cp_similarity.
+IANA_SUPPORTED_SIMILAR: dict[str, list[str]] = {
+ "cp037": ["cp1026", "cp1140", "cp273", "cp500"],
+ "cp1026": ["cp037", "cp1140", "cp273", "cp500"],
+ "cp1125": ["cp866"],
+ "cp1140": ["cp037", "cp1026", "cp273", "cp500"],
+ "cp1250": ["iso8859_2"],
+ "cp1251": ["kz1048", "ptcp154"],
+ "cp1252": ["iso8859_15", "iso8859_9", "latin_1"],
+ "cp1253": ["iso8859_7"],
+ "cp1254": ["iso8859_15", "iso8859_9", "latin_1"],
+ "cp1257": ["iso8859_13"],
+ "cp273": ["cp037", "cp1026", "cp1140", "cp500"],
+ "cp437": ["cp850", "cp858", "cp860", "cp861", "cp862", "cp863", "cp865"],
+ "cp500": ["cp037", "cp1026", "cp1140", "cp273"],
+ "cp850": ["cp437", "cp857", "cp858", "cp865"],
+ "cp857": ["cp850", "cp858", "cp865"],
+ "cp858": ["cp437", "cp850", "cp857", "cp865"],
+ "cp860": ["cp437", "cp861", "cp862", "cp863", "cp865"],
+ "cp861": ["cp437", "cp860", "cp862", "cp863", "cp865"],
+ "cp862": ["cp437", "cp860", "cp861", "cp863", "cp865"],
+ "cp863": ["cp437", "cp860", "cp861", "cp862", "cp865"],
+ "cp865": ["cp437", "cp850", "cp857", "cp858", "cp860", "cp861", "cp862", "cp863"],
+ "cp866": ["cp1125"],
+ "iso8859_10": ["iso8859_14", "iso8859_15", "iso8859_4", "iso8859_9", "latin_1"],
+ "iso8859_11": ["tis_620"],
+ "iso8859_13": ["cp1257"],
+ "iso8859_14": [
+ "iso8859_10",
+ "iso8859_15",
+ "iso8859_16",
+ "iso8859_3",
+ "iso8859_9",
+ "latin_1",
+ ],
+ "iso8859_15": [
+ "cp1252",
+ "cp1254",
+ "iso8859_10",
+ "iso8859_14",
+ "iso8859_16",
+ "iso8859_3",
+ "iso8859_9",
+ "latin_1",
+ ],
+ "iso8859_16": [
+ "iso8859_14",
+ "iso8859_15",
+ "iso8859_2",
+ "iso8859_3",
+ "iso8859_9",
+ "latin_1",
+ ],
+ "iso8859_2": ["cp1250", "iso8859_16", "iso8859_4"],
+ "iso8859_3": ["iso8859_14", "iso8859_15", "iso8859_16", "iso8859_9", "latin_1"],
+ "iso8859_4": ["iso8859_10", "iso8859_2", "iso8859_9", "latin_1"],
+ "iso8859_7": ["cp1253"],
+ "iso8859_9": [
+ "cp1252",
+ "cp1254",
+ "cp1258",
+ "iso8859_10",
+ "iso8859_14",
+ "iso8859_15",
+ "iso8859_16",
+ "iso8859_3",
+ "iso8859_4",
+ "latin_1",
+ ],
+ "kz1048": ["cp1251", "ptcp154"],
+ "latin_1": [
+ "cp1252",
+ "cp1254",
+ "cp1258",
+ "iso8859_10",
+ "iso8859_14",
+ "iso8859_15",
+ "iso8859_16",
+ "iso8859_3",
+ "iso8859_4",
+ "iso8859_9",
+ ],
+ "mac_iceland": ["mac_roman", "mac_turkish"],
+ "mac_roman": ["mac_iceland", "mac_turkish"],
+ "mac_turkish": ["mac_iceland", "mac_roman"],
+ "ptcp154": ["cp1251", "kz1048"],
+ "tis_620": ["iso8859_11"],
+}
+
+
+CHARDET_CORRESPONDENCE: dict[str, str] = {
+ "iso2022_kr": "ISO-2022-KR",
+ "iso2022_jp": "ISO-2022-JP",
+ "euc_kr": "EUC-KR",
+ "tis_620": "TIS-620",
+ "utf_32": "UTF-32",
+ "euc_jp": "EUC-JP",
+ "koi8_r": "KOI8-R",
+ "iso8859_1": "ISO-8859-1",
+ "iso8859_2": "ISO-8859-2",
+ "iso8859_5": "ISO-8859-5",
+ "iso8859_6": "ISO-8859-6",
+ "iso8859_7": "ISO-8859-7",
+ "iso8859_8": "ISO-8859-8",
+ "utf_16": "UTF-16",
+ "cp855": "IBM855",
+ "mac_cyrillic": "MacCyrillic",
+ "gb2312": "GB2312",
+ "gb18030": "GB18030",
+ "cp932": "CP932",
+ "cp866": "IBM866",
+ "utf_8": "utf-8",
+ "utf_8_sig": "UTF-8-SIG",
+ "shift_jis": "SHIFT_JIS",
+ "big5": "Big5",
+ "cp1250": "windows-1250",
+ "cp1251": "windows-1251",
+ "cp1252": "Windows-1252",
+ "cp1253": "windows-1253",
+ "cp1255": "windows-1255",
+ "cp1256": "windows-1256",
+ "cp1254": "Windows-1254",
+ "cp949": "CP949",
+}
+
+
+COMMON_SAFE_ASCII_CHARACTERS: set[str] = {
+ "<",
+ ">",
+ "=",
+ ":",
+ "/",
+ "&",
+ ";",
+ "{",
+ "}",
+ "[",
+ "]",
+ ",",
+ "|",
+ '"',
+ "-",
+ "(",
+ ")",
+}
+
+
+KO_NAMES: set[str] = {"johab", "cp949", "euc_kr"}
+ZH_NAMES: set[str] = {"big5", "cp950", "big5hkscs", "hz"}
+
+# Logging LEVEL below DEBUG
+TRACE: int = 5
+
+
+# Language label that contain the em dash "—"
+# character are to be considered alternative seq to origin
+FREQUENCIES: dict[str, list[str]] = {
+ "English": [
+ "e",
+ "a",
+ "t",
+ "i",
+ "o",
+ "n",
+ "s",
+ "r",
+ "h",
+ "l",
+ "d",
+ "c",
+ "u",
+ "m",
+ "f",
+ "p",
+ "g",
+ "w",
+ "y",
+ "b",
+ "v",
+ "k",
+ "x",
+ "j",
+ "z",
+ "q",
+ ],
+ "English—": [
+ "e",
+ "a",
+ "t",
+ "i",
+ "o",
+ "n",
+ "s",
+ "r",
+ "h",
+ "l",
+ "d",
+ "c",
+ "m",
+ "u",
+ "f",
+ "p",
+ "g",
+ "w",
+ "b",
+ "y",
+ "v",
+ "k",
+ "j",
+ "x",
+ "z",
+ "q",
+ ],
+ "German": [
+ "e",
+ "n",
+ "i",
+ "r",
+ "s",
+ "t",
+ "a",
+ "d",
+ "h",
+ "u",
+ "l",
+ "g",
+ "o",
+ "c",
+ "m",
+ "b",
+ "f",
+ "k",
+ "w",
+ "z",
+ "p",
+ "v",
+ "ü",
+ "ä",
+ "ö",
+ "j",
+ ],
+ "French": [
+ "e",
+ "a",
+ "s",
+ "n",
+ "i",
+ "t",
+ "r",
+ "l",
+ "u",
+ "o",
+ "d",
+ "c",
+ "p",
+ "m",
+ "é",
+ "v",
+ "g",
+ "f",
+ "b",
+ "h",
+ "q",
+ "à",
+ "x",
+ "è",
+ "y",
+ "j",
+ ],
+ "Dutch": [
+ "e",
+ "n",
+ "a",
+ "i",
+ "r",
+ "t",
+ "o",
+ "d",
+ "s",
+ "l",
+ "g",
+ "h",
+ "v",
+ "m",
+ "u",
+ "k",
+ "c",
+ "p",
+ "b",
+ "w",
+ "j",
+ "z",
+ "f",
+ "y",
+ "x",
+ "ë",
+ ],
+ "Italian": [
+ "e",
+ "i",
+ "a",
+ "o",
+ "n",
+ "l",
+ "t",
+ "r",
+ "s",
+ "c",
+ "d",
+ "u",
+ "p",
+ "m",
+ "g",
+ "v",
+ "f",
+ "b",
+ "z",
+ "h",
+ "q",
+ "è",
+ "à",
+ "k",
+ "y",
+ "ò",
+ ],
+ "Polish": [
+ "a",
+ "i",
+ "o",
+ "e",
+ "n",
+ "r",
+ "z",
+ "w",
+ "s",
+ "c",
+ "t",
+ "k",
+ "y",
+ "d",
+ "p",
+ "m",
+ "u",
+ "l",
+ "j",
+ "ł",
+ "g",
+ "b",
+ "h",
+ "ą",
+ "ę",
+ "ó",
+ ],
+ "Spanish": [
+ "e",
+ "a",
+ "o",
+ "n",
+ "s",
+ "r",
+ "i",
+ "l",
+ "d",
+ "t",
+ "c",
+ "u",
+ "m",
+ "p",
+ "b",
+ "g",
+ "v",
+ "f",
+ "y",
+ "ó",
+ "h",
+ "q",
+ "í",
+ "j",
+ "z",
+ "á",
+ ],
+ "Russian": [
+ "о",
+ "а",
+ "е",
+ "и",
+ "н",
+ "с",
+ "т",
+ "р",
+ "в",
+ "л",
+ "к",
+ "м",
+ "д",
+ "п",
+ "у",
+ "г",
+ "я",
+ "ы",
+ "з",
+ "б",
+ "й",
+ "ь",
+ "ч",
+ "х",
+ "ж",
+ "ц",
+ ],
+ # Jap-Kanji
+ "Japanese": [
+ "人",
+ "一",
+ "大",
+ "亅",
+ "丁",
+ "丨",
+ "竹",
+ "笑",
+ "口",
+ "日",
+ "今",
+ "二",
+ "彳",
+ "行",
+ "十",
+ "土",
+ "丶",
+ "寸",
+ "寺",
+ "時",
+ "乙",
+ "丿",
+ "乂",
+ "气",
+ "気",
+ "冂",
+ "巾",
+ "亠",
+ "市",
+ "目",
+ "儿",
+ "見",
+ "八",
+ "小",
+ "凵",
+ "県",
+ "月",
+ "彐",
+ "門",
+ "間",
+ "木",
+ "東",
+ "山",
+ "出",
+ "本",
+ "中",
+ "刀",
+ "分",
+ "耳",
+ "又",
+ "取",
+ "最",
+ "言",
+ "田",
+ "心",
+ "思",
+ "刂",
+ "前",
+ "京",
+ "尹",
+ "事",
+ "生",
+ "厶",
+ "云",
+ "会",
+ "未",
+ "来",
+ "白",
+ "冫",
+ "楽",
+ "灬",
+ "馬",
+ "尸",
+ "尺",
+ "駅",
+ "明",
+ "耂",
+ "者",
+ "了",
+ "阝",
+ "都",
+ "高",
+ "卜",
+ "占",
+ "厂",
+ "广",
+ "店",
+ "子",
+ "申",
+ "奄",
+ "亻",
+ "俺",
+ "上",
+ "方",
+ "冖",
+ "学",
+ "衣",
+ "艮",
+ "食",
+ "自",
+ ],
+ # Jap-Katakana
+ "Japanese—": [
+ "ー",
+ "ン",
+ "ス",
+ "・",
+ "ル",
+ "ト",
+ "リ",
+ "イ",
+ "ア",
+ "ラ",
+ "ッ",
+ "ク",
+ "ド",
+ "シ",
+ "レ",
+ "ジ",
+ "タ",
+ "フ",
+ "ロ",
+ "カ",
+ "テ",
+ "マ",
+ "ィ",
+ "グ",
+ "バ",
+ "ム",
+ "プ",
+ "オ",
+ "コ",
+ "デ",
+ "ニ",
+ "ウ",
+ "メ",
+ "サ",
+ "ビ",
+ "ナ",
+ "ブ",
+ "ャ",
+ "エ",
+ "ュ",
+ "チ",
+ "キ",
+ "ズ",
+ "ダ",
+ "パ",
+ "ミ",
+ "ェ",
+ "ョ",
+ "ハ",
+ "セ",
+ "ベ",
+ "ガ",
+ "モ",
+ "ツ",
+ "ネ",
+ "ボ",
+ "ソ",
+ "ノ",
+ "ァ",
+ "ヴ",
+ "ワ",
+ "ポ",
+ "ペ",
+ "ピ",
+ "ケ",
+ "ゴ",
+ "ギ",
+ "ザ",
+ "ホ",
+ "ゲ",
+ "ォ",
+ "ヤ",
+ "ヒ",
+ "ユ",
+ "ヨ",
+ "ヘ",
+ "ゼ",
+ "ヌ",
+ "ゥ",
+ "ゾ",
+ "ヶ",
+ "ヂ",
+ "ヲ",
+ "ヅ",
+ "ヵ",
+ "ヱ",
+ "ヰ",
+ "ヮ",
+ "ヽ",
+ "゠",
+ "ヾ",
+ "ヷ",
+ "ヿ",
+ "ヸ",
+ "ヹ",
+ "ヺ",
+ ],
+ # Jap-Hiragana
+ "Japanese——": [
+ "の",
+ "に",
+ "る",
+ "た",
+ "と",
+ "は",
+ "し",
+ "い",
+ "を",
+ "で",
+ "て",
+ "が",
+ "な",
+ "れ",
+ "か",
+ "ら",
+ "さ",
+ "っ",
+ "り",
+ "す",
+ "あ",
+ "も",
+ "こ",
+ "ま",
+ "う",
+ "く",
+ "よ",
+ "き",
+ "ん",
+ "め",
+ "お",
+ "け",
+ "そ",
+ "つ",
+ "だ",
+ "や",
+ "え",
+ "ど",
+ "わ",
+ "ち",
+ "み",
+ "せ",
+ "じ",
+ "ば",
+ "へ",
+ "び",
+ "ず",
+ "ろ",
+ "ほ",
+ "げ",
+ "む",
+ "べ",
+ "ひ",
+ "ょ",
+ "ゆ",
+ "ぶ",
+ "ご",
+ "ゃ",
+ "ね",
+ "ふ",
+ "ぐ",
+ "ぎ",
+ "ぼ",
+ "ゅ",
+ "づ",
+ "ざ",
+ "ぞ",
+ "ぬ",
+ "ぜ",
+ "ぱ",
+ "ぽ",
+ "ぷ",
+ "ぴ",
+ "ぃ",
+ "ぁ",
+ "ぇ",
+ "ぺ",
+ "ゞ",
+ "ぢ",
+ "ぉ",
+ "ぅ",
+ "ゐ",
+ "ゝ",
+ "ゑ",
+ "゛",
+ "゜",
+ "ゎ",
+ "ゔ",
+ "゚",
+ "ゟ",
+ "゙",
+ "ゕ",
+ "ゖ",
+ ],
+ "Portuguese": [
+ "a",
+ "e",
+ "o",
+ "s",
+ "i",
+ "r",
+ "d",
+ "n",
+ "t",
+ "m",
+ "u",
+ "c",
+ "l",
+ "p",
+ "g",
+ "v",
+ "b",
+ "f",
+ "h",
+ "ã",
+ "q",
+ "é",
+ "ç",
+ "á",
+ "z",
+ "í",
+ ],
+ "Swedish": [
+ "e",
+ "a",
+ "n",
+ "r",
+ "t",
+ "s",
+ "i",
+ "l",
+ "d",
+ "o",
+ "m",
+ "k",
+ "g",
+ "v",
+ "h",
+ "f",
+ "u",
+ "p",
+ "ä",
+ "c",
+ "b",
+ "ö",
+ "å",
+ "y",
+ "j",
+ "x",
+ ],
+ "Chinese": [
+ "的",
+ "一",
+ "是",
+ "不",
+ "了",
+ "在",
+ "人",
+ "有",
+ "我",
+ "他",
+ "这",
+ "个",
+ "们",
+ "中",
+ "来",
+ "上",
+ "大",
+ "为",
+ "和",
+ "国",
+ "地",
+ "到",
+ "以",
+ "说",
+ "时",
+ "要",
+ "就",
+ "出",
+ "会",
+ "可",
+ "也",
+ "你",
+ "对",
+ "生",
+ "能",
+ "而",
+ "子",
+ "那",
+ "得",
+ "于",
+ "着",
+ "下",
+ "自",
+ "之",
+ "年",
+ "过",
+ "发",
+ "后",
+ "作",
+ "里",
+ "用",
+ "道",
+ "行",
+ "所",
+ "然",
+ "家",
+ "种",
+ "事",
+ "成",
+ "方",
+ "多",
+ "经",
+ "么",
+ "去",
+ "法",
+ "学",
+ "如",
+ "都",
+ "同",
+ "现",
+ "当",
+ "没",
+ "动",
+ "面",
+ "起",
+ "看",
+ "定",
+ "天",
+ "分",
+ "还",
+ "进",
+ "好",
+ "小",
+ "部",
+ "其",
+ "些",
+ "主",
+ "样",
+ "理",
+ "心",
+ "她",
+ "本",
+ "前",
+ "开",
+ "但",
+ "因",
+ "只",
+ "从",
+ "想",
+ "实",
+ ],
+ "Ukrainian": [
+ "о",
+ "а",
+ "н",
+ "і",
+ "и",
+ "р",
+ "в",
+ "т",
+ "е",
+ "с",
+ "к",
+ "л",
+ "у",
+ "д",
+ "м",
+ "п",
+ "з",
+ "я",
+ "ь",
+ "б",
+ "г",
+ "й",
+ "ч",
+ "х",
+ "ц",
+ "ї",
+ ],
+ "Norwegian": [
+ "e",
+ "r",
+ "n",
+ "t",
+ "a",
+ "s",
+ "i",
+ "o",
+ "l",
+ "d",
+ "g",
+ "k",
+ "m",
+ "v",
+ "f",
+ "p",
+ "u",
+ "b",
+ "h",
+ "å",
+ "y",
+ "j",
+ "ø",
+ "c",
+ "æ",
+ "w",
+ ],
+ "Finnish": [
+ "a",
+ "i",
+ "n",
+ "t",
+ "e",
+ "s",
+ "l",
+ "o",
+ "u",
+ "k",
+ "ä",
+ "m",
+ "r",
+ "v",
+ "j",
+ "h",
+ "p",
+ "y",
+ "d",
+ "ö",
+ "g",
+ "c",
+ "b",
+ "f",
+ "w",
+ "z",
+ ],
+ "Vietnamese": [
+ "n",
+ "h",
+ "t",
+ "i",
+ "c",
+ "g",
+ "a",
+ "o",
+ "u",
+ "m",
+ "l",
+ "r",
+ "à",
+ "đ",
+ "s",
+ "e",
+ "v",
+ "p",
+ "b",
+ "y",
+ "ư",
+ "d",
+ "á",
+ "k",
+ "ộ",
+ "ế",
+ ],
+ "Czech": [
+ "o",
+ "e",
+ "a",
+ "n",
+ "t",
+ "s",
+ "i",
+ "l",
+ "v",
+ "r",
+ "k",
+ "d",
+ "u",
+ "m",
+ "p",
+ "í",
+ "c",
+ "h",
+ "z",
+ "á",
+ "y",
+ "j",
+ "b",
+ "ě",
+ "é",
+ "ř",
+ ],
+ "Hungarian": [
+ "e",
+ "a",
+ "t",
+ "l",
+ "s",
+ "n",
+ "k",
+ "r",
+ "i",
+ "o",
+ "z",
+ "á",
+ "é",
+ "g",
+ "m",
+ "b",
+ "y",
+ "v",
+ "d",
+ "h",
+ "u",
+ "p",
+ "j",
+ "ö",
+ "f",
+ "c",
+ ],
+ "Korean": [
+ "이",
+ "다",
+ "에",
+ "의",
+ "는",
+ "로",
+ "하",
+ "을",
+ "가",
+ "고",
+ "지",
+ "서",
+ "한",
+ "은",
+ "기",
+ "으",
+ "년",
+ "대",
+ "사",
+ "시",
+ "를",
+ "리",
+ "도",
+ "인",
+ "스",
+ "일",
+ ],
+ "Indonesian": [
+ "a",
+ "n",
+ "e",
+ "i",
+ "r",
+ "t",
+ "u",
+ "s",
+ "d",
+ "k",
+ "m",
+ "l",
+ "g",
+ "p",
+ "b",
+ "o",
+ "h",
+ "y",
+ "j",
+ "c",
+ "w",
+ "f",
+ "v",
+ "z",
+ "x",
+ "q",
+ ],
+ "Turkish": [
+ "a",
+ "e",
+ "i",
+ "n",
+ "r",
+ "l",
+ "ı",
+ "k",
+ "d",
+ "t",
+ "s",
+ "m",
+ "y",
+ "u",
+ "o",
+ "b",
+ "ü",
+ "ş",
+ "v",
+ "g",
+ "z",
+ "h",
+ "c",
+ "p",
+ "ç",
+ "ğ",
+ ],
+ "Romanian": [
+ "e",
+ "i",
+ "a",
+ "r",
+ "n",
+ "t",
+ "u",
+ "l",
+ "o",
+ "c",
+ "s",
+ "d",
+ "p",
+ "m",
+ "ă",
+ "f",
+ "v",
+ "î",
+ "g",
+ "b",
+ "ș",
+ "ț",
+ "z",
+ "h",
+ "â",
+ "j",
+ ],
+ "Farsi": [
+ "ا",
+ "ی",
+ "ر",
+ "د",
+ "ن",
+ "ه",
+ "و",
+ "م",
+ "ت",
+ "ب",
+ "س",
+ "ل",
+ "ک",
+ "ش",
+ "ز",
+ "ف",
+ "گ",
+ "ع",
+ "خ",
+ "ق",
+ "ج",
+ "آ",
+ "پ",
+ "ح",
+ "ط",
+ "ص",
+ ],
+ "Arabic": [
+ "ا",
+ "ل",
+ "ي",
+ "م",
+ "و",
+ "ن",
+ "ر",
+ "ت",
+ "ب",
+ "ة",
+ "ع",
+ "د",
+ "س",
+ "ف",
+ "ه",
+ "ك",
+ "ق",
+ "أ",
+ "ح",
+ "ج",
+ "ش",
+ "ط",
+ "ص",
+ "ى",
+ "خ",
+ "إ",
+ ],
+ "Danish": [
+ "e",
+ "r",
+ "n",
+ "t",
+ "a",
+ "i",
+ "s",
+ "d",
+ "l",
+ "o",
+ "g",
+ "m",
+ "k",
+ "f",
+ "v",
+ "u",
+ "b",
+ "h",
+ "p",
+ "å",
+ "y",
+ "ø",
+ "æ",
+ "c",
+ "j",
+ "w",
+ ],
+ "Serbian": [
+ "а",
+ "и",
+ "о",
+ "е",
+ "н",
+ "р",
+ "с",
+ "у",
+ "т",
+ "к",
+ "ј",
+ "в",
+ "д",
+ "м",
+ "п",
+ "л",
+ "г",
+ "з",
+ "б",
+ "a",
+ "i",
+ "e",
+ "o",
+ "n",
+ "ц",
+ "ш",
+ ],
+ "Lithuanian": [
+ "i",
+ "a",
+ "s",
+ "o",
+ "r",
+ "e",
+ "t",
+ "n",
+ "u",
+ "k",
+ "m",
+ "l",
+ "p",
+ "v",
+ "d",
+ "j",
+ "g",
+ "ė",
+ "b",
+ "y",
+ "ų",
+ "š",
+ "ž",
+ "c",
+ "ą",
+ "į",
+ ],
+ "Slovene": [
+ "e",
+ "a",
+ "i",
+ "o",
+ "n",
+ "r",
+ "s",
+ "l",
+ "t",
+ "j",
+ "v",
+ "k",
+ "d",
+ "p",
+ "m",
+ "u",
+ "z",
+ "b",
+ "g",
+ "h",
+ "č",
+ "c",
+ "š",
+ "ž",
+ "f",
+ "y",
+ ],
+ "Slovak": [
+ "o",
+ "a",
+ "e",
+ "n",
+ "i",
+ "r",
+ "v",
+ "t",
+ "s",
+ "l",
+ "k",
+ "d",
+ "m",
+ "p",
+ "u",
+ "c",
+ "h",
+ "j",
+ "b",
+ "z",
+ "á",
+ "y",
+ "ý",
+ "í",
+ "č",
+ "é",
+ ],
+ "Hebrew": [
+ "י",
+ "ו",
+ "ה",
+ "ל",
+ "ר",
+ "ב",
+ "ת",
+ "מ",
+ "א",
+ "ש",
+ "נ",
+ "ע",
+ "ם",
+ "ד",
+ "ק",
+ "ח",
+ "פ",
+ "ס",
+ "כ",
+ "ג",
+ "ט",
+ "צ",
+ "ן",
+ "ז",
+ "ך",
+ ],
+ "Bulgarian": [
+ "а",
+ "и",
+ "о",
+ "е",
+ "н",
+ "т",
+ "р",
+ "с",
+ "в",
+ "л",
+ "к",
+ "д",
+ "п",
+ "м",
+ "з",
+ "г",
+ "я",
+ "ъ",
+ "у",
+ "б",
+ "ч",
+ "ц",
+ "й",
+ "ж",
+ "щ",
+ "х",
+ ],
+ "Croatian": [
+ "a",
+ "i",
+ "o",
+ "e",
+ "n",
+ "r",
+ "j",
+ "s",
+ "t",
+ "u",
+ "k",
+ "l",
+ "v",
+ "d",
+ "m",
+ "p",
+ "g",
+ "z",
+ "b",
+ "c",
+ "č",
+ "h",
+ "š",
+ "ž",
+ "ć",
+ "f",
+ ],
+ "Hindi": [
+ "क",
+ "र",
+ "स",
+ "न",
+ "त",
+ "म",
+ "ह",
+ "प",
+ "य",
+ "ल",
+ "व",
+ "ज",
+ "द",
+ "ग",
+ "ब",
+ "श",
+ "ट",
+ "अ",
+ "ए",
+ "थ",
+ "भ",
+ "ड",
+ "च",
+ "ध",
+ "ष",
+ "इ",
+ ],
+ "Estonian": [
+ "a",
+ "i",
+ "e",
+ "s",
+ "t",
+ "l",
+ "u",
+ "n",
+ "o",
+ "k",
+ "r",
+ "d",
+ "m",
+ "v",
+ "g",
+ "p",
+ "j",
+ "h",
+ "ä",
+ "b",
+ "õ",
+ "ü",
+ "f",
+ "c",
+ "ö",
+ "y",
+ ],
+ "Thai": [
+ "า",
+ "น",
+ "ร",
+ "อ",
+ "ก",
+ "เ",
+ "ง",
+ "ม",
+ "ย",
+ "ล",
+ "ว",
+ "ด",
+ "ท",
+ "ส",
+ "ต",
+ "ะ",
+ "ป",
+ "บ",
+ "ค",
+ "ห",
+ "แ",
+ "จ",
+ "พ",
+ "ช",
+ "ข",
+ "ใ",
+ ],
+ "Greek": [
+ "α",
+ "τ",
+ "ο",
+ "ι",
+ "ε",
+ "ν",
+ "ρ",
+ "σ",
+ "κ",
+ "η",
+ "π",
+ "ς",
+ "υ",
+ "μ",
+ "λ",
+ "ί",
+ "ό",
+ "ά",
+ "γ",
+ "έ",
+ "δ",
+ "ή",
+ "ω",
+ "χ",
+ "θ",
+ "ύ",
+ ],
+ "Tamil": [
+ "க",
+ "த",
+ "ப",
+ "ட",
+ "ர",
+ "ம",
+ "ல",
+ "ன",
+ "வ",
+ "ற",
+ "ய",
+ "ள",
+ "ச",
+ "ந",
+ "இ",
+ "ண",
+ "அ",
+ "ஆ",
+ "ழ",
+ "ங",
+ "எ",
+ "உ",
+ "ஒ",
+ "ஸ",
+ ],
+ "Kazakh": [
+ "а",
+ "ы",
+ "е",
+ "н",
+ "т",
+ "р",
+ "л",
+ "і",
+ "д",
+ "с",
+ "м",
+ "қ",
+ "к",
+ "о",
+ "б",
+ "и",
+ "у",
+ "ғ",
+ "ж",
+ "ң",
+ "з",
+ "ш",
+ "й",
+ "п",
+ "г",
+ "ө",
+ ],
+}
+
+LANGUAGE_SUPPORTED_COUNT: int = len(FREQUENCIES)
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/legacy.py b/testcline/lib/python3.12/site-packages/charset_normalizer/legacy.py
new file mode 100644
index 0000000..a2f5345
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/legacy.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any
+from warnings import warn
+
+from .api import from_bytes
+from .constant import CHARDET_CORRESPONDENCE
+
+# TODO: remove this check when dropping Python 3.7 support
+if TYPE_CHECKING:
+ from typing_extensions import TypedDict
+
+ class ResultDict(TypedDict):
+ encoding: str | None
+ language: str
+ confidence: float | None
+
+
+def detect(
+ byte_str: bytes, should_rename_legacy: bool = False, **kwargs: Any
+) -> ResultDict:
+ """
+ chardet legacy method
+ Detect the encoding of the given byte string. It should be mostly backward-compatible.
+ Encoding name will match Chardet own writing whenever possible. (Not on encoding name unsupported by it)
+ This function is deprecated and should be used to migrate your project easily, consult the documentation for
+ further information. Not planned for removal.
+
+ :param byte_str: The byte sequence to examine.
+ :param should_rename_legacy: Should we rename legacy encodings
+ to their more modern equivalents?
+ """
+ if len(kwargs):
+ warn(
+ f"charset-normalizer disregard arguments '{','.join(list(kwargs.keys()))}' in legacy function detect()"
+ )
+
+ if not isinstance(byte_str, (bytearray, bytes)):
+ raise TypeError( # pragma: nocover
+ "Expected object of type bytes or bytearray, got: " "{}".format(
+ type(byte_str)
+ )
+ )
+
+ if isinstance(byte_str, bytearray):
+ byte_str = bytes(byte_str)
+
+ r = from_bytes(byte_str).best()
+
+ encoding = r.encoding if r is not None else None
+ language = r.language if r is not None and r.language != "Unknown" else ""
+ confidence = 1.0 - r.chaos if r is not None else None
+
+ # Note: CharsetNormalizer does not return 'UTF-8-SIG' as the sig get stripped in the detection/normalization process
+ # but chardet does return 'utf-8-sig' and it is a valid codec name.
+ if r is not None and encoding == "utf_8" and r.bom:
+ encoding += "_sig"
+
+ if should_rename_legacy is False and encoding in CHARDET_CORRESPONDENCE:
+ encoding = CHARDET_CORRESPONDENCE[encoding]
+
+ return {
+ "encoding": encoding,
+ "language": language,
+ "confidence": confidence,
+ }
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/md.cpython-312-x86_64-linux-gnu.so b/testcline/lib/python3.12/site-packages/charset_normalizer/md.cpython-312-x86_64-linux-gnu.so
new file mode 100755
index 0000000..3d0b46a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/md.cpython-312-x86_64-linux-gnu.so differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/md.py b/testcline/lib/python3.12/site-packages/charset_normalizer/md.py
new file mode 100644
index 0000000..9ed59a8
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/md.py
@@ -0,0 +1,630 @@
+from __future__ import annotations
+
+from functools import lru_cache
+from logging import getLogger
+
+from .constant import (
+ COMMON_SAFE_ASCII_CHARACTERS,
+ TRACE,
+ UNICODE_SECONDARY_RANGE_KEYWORD,
+)
+from .utils import (
+ is_accentuated,
+ is_arabic,
+ is_arabic_isolated_form,
+ is_case_variable,
+ is_cjk,
+ is_emoticon,
+ is_hangul,
+ is_hiragana,
+ is_katakana,
+ is_latin,
+ is_punctuation,
+ is_separator,
+ is_symbol,
+ is_thai,
+ is_unprintable,
+ remove_accent,
+ unicode_range,
+)
+
+
+class MessDetectorPlugin:
+ """
+ Base abstract class used for mess detection plugins.
+ All detectors MUST extend and implement given methods.
+ """
+
+ def eligible(self, character: str) -> bool:
+ """
+ Determine if given character should be fed in.
+ """
+ raise NotImplementedError # pragma: nocover
+
+ def feed(self, character: str) -> None:
+ """
+ The main routine to be executed upon character.
+ Insert the logic in witch the text would be considered chaotic.
+ """
+ raise NotImplementedError # pragma: nocover
+
+ def reset(self) -> None: # pragma: no cover
+ """
+ Permit to reset the plugin to the initial state.
+ """
+ raise NotImplementedError
+
+ @property
+ def ratio(self) -> float:
+ """
+ Compute the chaos ratio based on what your feed() has seen.
+ Must NOT be lower than 0.; No restriction gt 0.
+ """
+ raise NotImplementedError # pragma: nocover
+
+
+class TooManySymbolOrPunctuationPlugin(MessDetectorPlugin):
+ def __init__(self) -> None:
+ self._punctuation_count: int = 0
+ self._symbol_count: int = 0
+ self._character_count: int = 0
+
+ self._last_printable_char: str | None = None
+ self._frenzy_symbol_in_word: bool = False
+
+ def eligible(self, character: str) -> bool:
+ return character.isprintable()
+
+ def feed(self, character: str) -> None:
+ self._character_count += 1
+
+ if (
+ character != self._last_printable_char
+ and character not in COMMON_SAFE_ASCII_CHARACTERS
+ ):
+ if is_punctuation(character):
+ self._punctuation_count += 1
+ elif (
+ character.isdigit() is False
+ and is_symbol(character)
+ and is_emoticon(character) is False
+ ):
+ self._symbol_count += 2
+
+ self._last_printable_char = character
+
+ def reset(self) -> None: # Abstract
+ self._punctuation_count = 0
+ self._character_count = 0
+ self._symbol_count = 0
+
+ @property
+ def ratio(self) -> float:
+ if self._character_count == 0:
+ return 0.0
+
+ ratio_of_punctuation: float = (
+ self._punctuation_count + self._symbol_count
+ ) / self._character_count
+
+ return ratio_of_punctuation if ratio_of_punctuation >= 0.3 else 0.0
+
+
+class TooManyAccentuatedPlugin(MessDetectorPlugin):
+ def __init__(self) -> None:
+ self._character_count: int = 0
+ self._accentuated_count: int = 0
+
+ def eligible(self, character: str) -> bool:
+ return character.isalpha()
+
+ def feed(self, character: str) -> None:
+ self._character_count += 1
+
+ if is_accentuated(character):
+ self._accentuated_count += 1
+
+ def reset(self) -> None: # Abstract
+ self._character_count = 0
+ self._accentuated_count = 0
+
+ @property
+ def ratio(self) -> float:
+ if self._character_count < 8:
+ return 0.0
+
+ ratio_of_accentuation: float = self._accentuated_count / self._character_count
+ return ratio_of_accentuation if ratio_of_accentuation >= 0.35 else 0.0
+
+
+class UnprintablePlugin(MessDetectorPlugin):
+ def __init__(self) -> None:
+ self._unprintable_count: int = 0
+ self._character_count: int = 0
+
+ def eligible(self, character: str) -> bool:
+ return True
+
+ def feed(self, character: str) -> None:
+ if is_unprintable(character):
+ self._unprintable_count += 1
+ self._character_count += 1
+
+ def reset(self) -> None: # Abstract
+ self._unprintable_count = 0
+
+ @property
+ def ratio(self) -> float:
+ if self._character_count == 0:
+ return 0.0
+
+ return (self._unprintable_count * 8) / self._character_count
+
+
+class SuspiciousDuplicateAccentPlugin(MessDetectorPlugin):
+ def __init__(self) -> None:
+ self._successive_count: int = 0
+ self._character_count: int = 0
+
+ self._last_latin_character: str | None = None
+
+ def eligible(self, character: str) -> bool:
+ return character.isalpha() and is_latin(character)
+
+ def feed(self, character: str) -> None:
+ self._character_count += 1
+ if (
+ self._last_latin_character is not None
+ and is_accentuated(character)
+ and is_accentuated(self._last_latin_character)
+ ):
+ if character.isupper() and self._last_latin_character.isupper():
+ self._successive_count += 1
+ # Worse if its the same char duplicated with different accent.
+ if remove_accent(character) == remove_accent(self._last_latin_character):
+ self._successive_count += 1
+ self._last_latin_character = character
+
+ def reset(self) -> None: # Abstract
+ self._successive_count = 0
+ self._character_count = 0
+ self._last_latin_character = None
+
+ @property
+ def ratio(self) -> float:
+ if self._character_count == 0:
+ return 0.0
+
+ return (self._successive_count * 2) / self._character_count
+
+
+class SuspiciousRange(MessDetectorPlugin):
+ def __init__(self) -> None:
+ self._suspicious_successive_range_count: int = 0
+ self._character_count: int = 0
+ self._last_printable_seen: str | None = None
+
+ def eligible(self, character: str) -> bool:
+ return character.isprintable()
+
+ def feed(self, character: str) -> None:
+ self._character_count += 1
+
+ if (
+ character.isspace()
+ or is_punctuation(character)
+ or character in COMMON_SAFE_ASCII_CHARACTERS
+ ):
+ self._last_printable_seen = None
+ return
+
+ if self._last_printable_seen is None:
+ self._last_printable_seen = character
+ return
+
+ unicode_range_a: str | None = unicode_range(self._last_printable_seen)
+ unicode_range_b: str | None = unicode_range(character)
+
+ if is_suspiciously_successive_range(unicode_range_a, unicode_range_b):
+ self._suspicious_successive_range_count += 1
+
+ self._last_printable_seen = character
+
+ def reset(self) -> None: # Abstract
+ self._character_count = 0
+ self._suspicious_successive_range_count = 0
+ self._last_printable_seen = None
+
+ @property
+ def ratio(self) -> float:
+ if self._character_count <= 13:
+ return 0.0
+
+ ratio_of_suspicious_range_usage: float = (
+ self._suspicious_successive_range_count * 2
+ ) / self._character_count
+
+ return ratio_of_suspicious_range_usage
+
+
+class SuperWeirdWordPlugin(MessDetectorPlugin):
+ def __init__(self) -> None:
+ self._word_count: int = 0
+ self._bad_word_count: int = 0
+ self._foreign_long_count: int = 0
+
+ self._is_current_word_bad: bool = False
+ self._foreign_long_watch: bool = False
+
+ self._character_count: int = 0
+ self._bad_character_count: int = 0
+
+ self._buffer: str = ""
+ self._buffer_accent_count: int = 0
+ self._buffer_glyph_count: int = 0
+
+ def eligible(self, character: str) -> bool:
+ return True
+
+ def feed(self, character: str) -> None:
+ if character.isalpha():
+ self._buffer += character
+ if is_accentuated(character):
+ self._buffer_accent_count += 1
+ if (
+ self._foreign_long_watch is False
+ and (is_latin(character) is False or is_accentuated(character))
+ and is_cjk(character) is False
+ and is_hangul(character) is False
+ and is_katakana(character) is False
+ and is_hiragana(character) is False
+ and is_thai(character) is False
+ ):
+ self._foreign_long_watch = True
+ if (
+ is_cjk(character)
+ or is_hangul(character)
+ or is_katakana(character)
+ or is_hiragana(character)
+ or is_thai(character)
+ ):
+ self._buffer_glyph_count += 1
+ return
+ if not self._buffer:
+ return
+ if (
+ character.isspace() or is_punctuation(character) or is_separator(character)
+ ) and self._buffer:
+ self._word_count += 1
+ buffer_length: int = len(self._buffer)
+
+ self._character_count += buffer_length
+
+ if buffer_length >= 4:
+ if self._buffer_accent_count / buffer_length >= 0.5:
+ self._is_current_word_bad = True
+ # Word/Buffer ending with an upper case accentuated letter are so rare,
+ # that we will consider them all as suspicious. Same weight as foreign_long suspicious.
+ elif (
+ is_accentuated(self._buffer[-1])
+ and self._buffer[-1].isupper()
+ and all(_.isupper() for _ in self._buffer) is False
+ ):
+ self._foreign_long_count += 1
+ self._is_current_word_bad = True
+ elif self._buffer_glyph_count == 1:
+ self._is_current_word_bad = True
+ self._foreign_long_count += 1
+ if buffer_length >= 24 and self._foreign_long_watch:
+ camel_case_dst = [
+ i
+ for c, i in zip(self._buffer, range(0, buffer_length))
+ if c.isupper()
+ ]
+ probable_camel_cased: bool = False
+
+ if camel_case_dst and (len(camel_case_dst) / buffer_length <= 0.3):
+ probable_camel_cased = True
+
+ if not probable_camel_cased:
+ self._foreign_long_count += 1
+ self._is_current_word_bad = True
+
+ if self._is_current_word_bad:
+ self._bad_word_count += 1
+ self._bad_character_count += len(self._buffer)
+ self._is_current_word_bad = False
+
+ self._foreign_long_watch = False
+ self._buffer = ""
+ self._buffer_accent_count = 0
+ self._buffer_glyph_count = 0
+ elif (
+ character not in {"<", ">", "-", "=", "~", "|", "_"}
+ and character.isdigit() is False
+ and is_symbol(character)
+ ):
+ self._is_current_word_bad = True
+ self._buffer += character
+
+ def reset(self) -> None: # Abstract
+ self._buffer = ""
+ self._is_current_word_bad = False
+ self._foreign_long_watch = False
+ self._bad_word_count = 0
+ self._word_count = 0
+ self._character_count = 0
+ self._bad_character_count = 0
+ self._foreign_long_count = 0
+
+ @property
+ def ratio(self) -> float:
+ if self._word_count <= 10 and self._foreign_long_count == 0:
+ return 0.0
+
+ return self._bad_character_count / self._character_count
+
+
+class CjkInvalidStopPlugin(MessDetectorPlugin):
+ """
+ GB(Chinese) based encoding often render the stop incorrectly when the content does not fit and
+ can be easily detected. Searching for the overuse of '丅' and '丄'.
+ """
+
+ def __init__(self) -> None:
+ self._wrong_stop_count: int = 0
+ self._cjk_character_count: int = 0
+
+ def eligible(self, character: str) -> bool:
+ return True
+
+ def feed(self, character: str) -> None:
+ if character in {"丅", "丄"}:
+ self._wrong_stop_count += 1
+ return
+ if is_cjk(character):
+ self._cjk_character_count += 1
+
+ def reset(self) -> None: # Abstract
+ self._wrong_stop_count = 0
+ self._cjk_character_count = 0
+
+ @property
+ def ratio(self) -> float:
+ if self._cjk_character_count < 16:
+ return 0.0
+ return self._wrong_stop_count / self._cjk_character_count
+
+
+class ArchaicUpperLowerPlugin(MessDetectorPlugin):
+ def __init__(self) -> None:
+ self._buf: bool = False
+
+ self._character_count_since_last_sep: int = 0
+
+ self._successive_upper_lower_count: int = 0
+ self._successive_upper_lower_count_final: int = 0
+
+ self._character_count: int = 0
+
+ self._last_alpha_seen: str | None = None
+ self._current_ascii_only: bool = True
+
+ def eligible(self, character: str) -> bool:
+ return True
+
+ def feed(self, character: str) -> None:
+ is_concerned = character.isalpha() and is_case_variable(character)
+ chunk_sep = is_concerned is False
+
+ if chunk_sep and self._character_count_since_last_sep > 0:
+ if (
+ self._character_count_since_last_sep <= 64
+ and character.isdigit() is False
+ and self._current_ascii_only is False
+ ):
+ self._successive_upper_lower_count_final += (
+ self._successive_upper_lower_count
+ )
+
+ self._successive_upper_lower_count = 0
+ self._character_count_since_last_sep = 0
+ self._last_alpha_seen = None
+ self._buf = False
+ self._character_count += 1
+ self._current_ascii_only = True
+
+ return
+
+ if self._current_ascii_only is True and character.isascii() is False:
+ self._current_ascii_only = False
+
+ if self._last_alpha_seen is not None:
+ if (character.isupper() and self._last_alpha_seen.islower()) or (
+ character.islower() and self._last_alpha_seen.isupper()
+ ):
+ if self._buf is True:
+ self._successive_upper_lower_count += 2
+ self._buf = False
+ else:
+ self._buf = True
+ else:
+ self._buf = False
+
+ self._character_count += 1
+ self._character_count_since_last_sep += 1
+ self._last_alpha_seen = character
+
+ def reset(self) -> None: # Abstract
+ self._character_count = 0
+ self._character_count_since_last_sep = 0
+ self._successive_upper_lower_count = 0
+ self._successive_upper_lower_count_final = 0
+ self._last_alpha_seen = None
+ self._buf = False
+ self._current_ascii_only = True
+
+ @property
+ def ratio(self) -> float:
+ if self._character_count == 0:
+ return 0.0
+
+ return self._successive_upper_lower_count_final / self._character_count
+
+
+class ArabicIsolatedFormPlugin(MessDetectorPlugin):
+ def __init__(self) -> None:
+ self._character_count: int = 0
+ self._isolated_form_count: int = 0
+
+ def reset(self) -> None: # Abstract
+ self._character_count = 0
+ self._isolated_form_count = 0
+
+ def eligible(self, character: str) -> bool:
+ return is_arabic(character)
+
+ def feed(self, character: str) -> None:
+ self._character_count += 1
+
+ if is_arabic_isolated_form(character):
+ self._isolated_form_count += 1
+
+ @property
+ def ratio(self) -> float:
+ if self._character_count < 8:
+ return 0.0
+
+ isolated_form_usage: float = self._isolated_form_count / self._character_count
+
+ return isolated_form_usage
+
+
+@lru_cache(maxsize=1024)
+def is_suspiciously_successive_range(
+ unicode_range_a: str | None, unicode_range_b: str | None
+) -> bool:
+ """
+ Determine if two Unicode range seen next to each other can be considered as suspicious.
+ """
+ if unicode_range_a is None or unicode_range_b is None:
+ return True
+
+ if unicode_range_a == unicode_range_b:
+ return False
+
+ if "Latin" in unicode_range_a and "Latin" in unicode_range_b:
+ return False
+
+ if "Emoticons" in unicode_range_a or "Emoticons" in unicode_range_b:
+ return False
+
+ # Latin characters can be accompanied with a combining diacritical mark
+ # eg. Vietnamese.
+ if ("Latin" in unicode_range_a or "Latin" in unicode_range_b) and (
+ "Combining" in unicode_range_a or "Combining" in unicode_range_b
+ ):
+ return False
+
+ keywords_range_a, keywords_range_b = (
+ unicode_range_a.split(" "),
+ unicode_range_b.split(" "),
+ )
+
+ for el in keywords_range_a:
+ if el in UNICODE_SECONDARY_RANGE_KEYWORD:
+ continue
+ if el in keywords_range_b:
+ return False
+
+ # Japanese Exception
+ range_a_jp_chars, range_b_jp_chars = (
+ unicode_range_a
+ in (
+ "Hiragana",
+ "Katakana",
+ ),
+ unicode_range_b in ("Hiragana", "Katakana"),
+ )
+ if (range_a_jp_chars or range_b_jp_chars) and (
+ "CJK" in unicode_range_a or "CJK" in unicode_range_b
+ ):
+ return False
+ if range_a_jp_chars and range_b_jp_chars:
+ return False
+
+ if "Hangul" in unicode_range_a or "Hangul" in unicode_range_b:
+ if "CJK" in unicode_range_a or "CJK" in unicode_range_b:
+ return False
+ if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin":
+ return False
+
+ # Chinese/Japanese use dedicated range for punctuation and/or separators.
+ if ("CJK" in unicode_range_a or "CJK" in unicode_range_b) or (
+ unicode_range_a in ["Katakana", "Hiragana"]
+ and unicode_range_b in ["Katakana", "Hiragana"]
+ ):
+ if "Punctuation" in unicode_range_a or "Punctuation" in unicode_range_b:
+ return False
+ if "Forms" in unicode_range_a or "Forms" in unicode_range_b:
+ return False
+ if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin":
+ return False
+
+ return True
+
+
+@lru_cache(maxsize=2048)
+def mess_ratio(
+ decoded_sequence: str, maximum_threshold: float = 0.2, debug: bool = False
+) -> float:
+ """
+ Compute a mess ratio given a decoded bytes sequence. The maximum threshold does stop the computation earlier.
+ """
+
+ detectors: list[MessDetectorPlugin] = [
+ md_class() for md_class in MessDetectorPlugin.__subclasses__()
+ ]
+
+ length: int = len(decoded_sequence) + 1
+
+ mean_mess_ratio: float = 0.0
+
+ if length < 512:
+ intermediary_mean_mess_ratio_calc: int = 32
+ elif length <= 1024:
+ intermediary_mean_mess_ratio_calc = 64
+ else:
+ intermediary_mean_mess_ratio_calc = 128
+
+ for character, index in zip(decoded_sequence + "\n", range(length)):
+ for detector in detectors:
+ if detector.eligible(character):
+ detector.feed(character)
+
+ if (
+ index > 0 and index % intermediary_mean_mess_ratio_calc == 0
+ ) or index == length - 1:
+ mean_mess_ratio = sum(dt.ratio for dt in detectors)
+
+ if mean_mess_ratio >= maximum_threshold:
+ break
+
+ if debug:
+ logger = getLogger("charset_normalizer")
+
+ logger.log(
+ TRACE,
+ "Mess-detector extended-analysis start. "
+ f"intermediary_mean_mess_ratio_calc={intermediary_mean_mess_ratio_calc} mean_mess_ratio={mean_mess_ratio} "
+ f"maximum_threshold={maximum_threshold}",
+ )
+
+ if len(decoded_sequence) > 16:
+ logger.log(TRACE, f"Starting with: {decoded_sequence[:16]}")
+ logger.log(TRACE, f"Ending with: {decoded_sequence[-16::]}")
+
+ for dt in detectors:
+ logger.log(TRACE, f"{dt.__class__}: {dt.ratio}")
+
+ return round(mean_mess_ratio, 3)
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/md__mypyc.cpython-312-x86_64-linux-gnu.so b/testcline/lib/python3.12/site-packages/charset_normalizer/md__mypyc.cpython-312-x86_64-linux-gnu.so
new file mode 100755
index 0000000..245cc20
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/charset_normalizer/md__mypyc.cpython-312-x86_64-linux-gnu.so differ
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/models.py b/testcline/lib/python3.12/site-packages/charset_normalizer/models.py
new file mode 100644
index 0000000..1042758
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/models.py
@@ -0,0 +1,360 @@
+from __future__ import annotations
+
+from encodings.aliases import aliases
+from hashlib import sha256
+from json import dumps
+from re import sub
+from typing import Any, Iterator, List, Tuple
+
+from .constant import RE_POSSIBLE_ENCODING_INDICATION, TOO_BIG_SEQUENCE
+from .utils import iana_name, is_multi_byte_encoding, unicode_range
+
+
+class CharsetMatch:
+ def __init__(
+ self,
+ payload: bytes,
+ guessed_encoding: str,
+ mean_mess_ratio: float,
+ has_sig_or_bom: bool,
+ languages: CoherenceMatches,
+ decoded_payload: str | None = None,
+ preemptive_declaration: str | None = None,
+ ):
+ self._payload: bytes = payload
+
+ self._encoding: str = guessed_encoding
+ self._mean_mess_ratio: float = mean_mess_ratio
+ self._languages: CoherenceMatches = languages
+ self._has_sig_or_bom: bool = has_sig_or_bom
+ self._unicode_ranges: list[str] | None = None
+
+ self._leaves: list[CharsetMatch] = []
+ self._mean_coherence_ratio: float = 0.0
+
+ self._output_payload: bytes | None = None
+ self._output_encoding: str | None = None
+
+ self._string: str | None = decoded_payload
+
+ self._preemptive_declaration: str | None = preemptive_declaration
+
+ def __eq__(self, other: object) -> bool:
+ if not isinstance(other, CharsetMatch):
+ if isinstance(other, str):
+ return iana_name(other) == self.encoding
+ return False
+ return self.encoding == other.encoding and self.fingerprint == other.fingerprint
+
+ def __lt__(self, other: object) -> bool:
+ """
+ Implemented to make sorted available upon CharsetMatches items.
+ """
+ if not isinstance(other, CharsetMatch):
+ raise ValueError
+
+ chaos_difference: float = abs(self.chaos - other.chaos)
+ coherence_difference: float = abs(self.coherence - other.coherence)
+
+ # Below 1% difference --> Use Coherence
+ if chaos_difference < 0.01 and coherence_difference > 0.02:
+ return self.coherence > other.coherence
+ elif chaos_difference < 0.01 and coherence_difference <= 0.02:
+ # When having a difficult decision, use the result that decoded as many multi-byte as possible.
+ # preserve RAM usage!
+ if len(self._payload) >= TOO_BIG_SEQUENCE:
+ return self.chaos < other.chaos
+ return self.multi_byte_usage > other.multi_byte_usage
+
+ return self.chaos < other.chaos
+
+ @property
+ def multi_byte_usage(self) -> float:
+ return 1.0 - (len(str(self)) / len(self.raw))
+
+ def __str__(self) -> str:
+ # Lazy Str Loading
+ if self._string is None:
+ self._string = str(self._payload, self._encoding, "strict")
+ return self._string
+
+ def __repr__(self) -> str:
+ return f""
+
+ def add_submatch(self, other: CharsetMatch) -> None:
+ if not isinstance(other, CharsetMatch) or other == self:
+ raise ValueError(
+ "Unable to add instance <{}> as a submatch of a CharsetMatch".format(
+ other.__class__
+ )
+ )
+
+ other._string = None # Unload RAM usage; dirty trick.
+ self._leaves.append(other)
+
+ @property
+ def encoding(self) -> str:
+ return self._encoding
+
+ @property
+ def encoding_aliases(self) -> list[str]:
+ """
+ Encoding name are known by many name, using this could help when searching for IBM855 when it's listed as CP855.
+ """
+ also_known_as: list[str] = []
+ for u, p in aliases.items():
+ if self.encoding == u:
+ also_known_as.append(p)
+ elif self.encoding == p:
+ also_known_as.append(u)
+ return also_known_as
+
+ @property
+ def bom(self) -> bool:
+ return self._has_sig_or_bom
+
+ @property
+ def byte_order_mark(self) -> bool:
+ return self._has_sig_or_bom
+
+ @property
+ def languages(self) -> list[str]:
+ """
+ Return the complete list of possible languages found in decoded sequence.
+ Usually not really useful. Returned list may be empty even if 'language' property return something != 'Unknown'.
+ """
+ return [e[0] for e in self._languages]
+
+ @property
+ def language(self) -> str:
+ """
+ Most probable language found in decoded sequence. If none were detected or inferred, the property will return
+ "Unknown".
+ """
+ if not self._languages:
+ # Trying to infer the language based on the given encoding
+ # Its either English or we should not pronounce ourselves in certain cases.
+ if "ascii" in self.could_be_from_charset:
+ return "English"
+
+ # doing it there to avoid circular import
+ from charset_normalizer.cd import encoding_languages, mb_encoding_languages
+
+ languages = (
+ mb_encoding_languages(self.encoding)
+ if is_multi_byte_encoding(self.encoding)
+ else encoding_languages(self.encoding)
+ )
+
+ if len(languages) == 0 or "Latin Based" in languages:
+ return "Unknown"
+
+ return languages[0]
+
+ return self._languages[0][0]
+
+ @property
+ def chaos(self) -> float:
+ return self._mean_mess_ratio
+
+ @property
+ def coherence(self) -> float:
+ if not self._languages:
+ return 0.0
+ return self._languages[0][1]
+
+ @property
+ def percent_chaos(self) -> float:
+ return round(self.chaos * 100, ndigits=3)
+
+ @property
+ def percent_coherence(self) -> float:
+ return round(self.coherence * 100, ndigits=3)
+
+ @property
+ def raw(self) -> bytes:
+ """
+ Original untouched bytes.
+ """
+ return self._payload
+
+ @property
+ def submatch(self) -> list[CharsetMatch]:
+ return self._leaves
+
+ @property
+ def has_submatch(self) -> bool:
+ return len(self._leaves) > 0
+
+ @property
+ def alphabets(self) -> list[str]:
+ if self._unicode_ranges is not None:
+ return self._unicode_ranges
+ # list detected ranges
+ detected_ranges: list[str | None] = [unicode_range(char) for char in str(self)]
+ # filter and sort
+ self._unicode_ranges = sorted(list({r for r in detected_ranges if r}))
+ return self._unicode_ranges
+
+ @property
+ def could_be_from_charset(self) -> list[str]:
+ """
+ The complete list of encoding that output the exact SAME str result and therefore could be the originating
+ encoding.
+ This list does include the encoding available in property 'encoding'.
+ """
+ return [self._encoding] + [m.encoding for m in self._leaves]
+
+ def output(self, encoding: str = "utf_8") -> bytes:
+ """
+ Method to get re-encoded bytes payload using given target encoding. Default to UTF-8.
+ Any errors will be simply ignored by the encoder NOT replaced.
+ """
+ if self._output_encoding is None or self._output_encoding != encoding:
+ self._output_encoding = encoding
+ decoded_string = str(self)
+ if (
+ self._preemptive_declaration is not None
+ and self._preemptive_declaration.lower()
+ not in ["utf-8", "utf8", "utf_8"]
+ ):
+ patched_header = sub(
+ RE_POSSIBLE_ENCODING_INDICATION,
+ lambda m: m.string[m.span()[0] : m.span()[1]].replace(
+ m.groups()[0],
+ iana_name(self._output_encoding).replace("_", "-"), # type: ignore[arg-type]
+ ),
+ decoded_string[:8192],
+ count=1,
+ )
+
+ decoded_string = patched_header + decoded_string[8192:]
+
+ self._output_payload = decoded_string.encode(encoding, "replace")
+
+ return self._output_payload # type: ignore
+
+ @property
+ def fingerprint(self) -> str:
+ """
+ Retrieve the unique SHA256 computed using the transformed (re-encoded) payload. Not the original one.
+ """
+ return sha256(self.output()).hexdigest()
+
+
+class CharsetMatches:
+ """
+ Container with every CharsetMatch items ordered by default from most probable to the less one.
+ Act like a list(iterable) but does not implements all related methods.
+ """
+
+ def __init__(self, results: list[CharsetMatch] | None = None):
+ self._results: list[CharsetMatch] = sorted(results) if results else []
+
+ def __iter__(self) -> Iterator[CharsetMatch]:
+ yield from self._results
+
+ def __getitem__(self, item: int | str) -> CharsetMatch:
+ """
+ Retrieve a single item either by its position or encoding name (alias may be used here).
+ Raise KeyError upon invalid index or encoding not present in results.
+ """
+ if isinstance(item, int):
+ return self._results[item]
+ if isinstance(item, str):
+ item = iana_name(item, False)
+ for result in self._results:
+ if item in result.could_be_from_charset:
+ return result
+ raise KeyError
+
+ def __len__(self) -> int:
+ return len(self._results)
+
+ def __bool__(self) -> bool:
+ return len(self._results) > 0
+
+ def append(self, item: CharsetMatch) -> None:
+ """
+ Insert a single match. Will be inserted accordingly to preserve sort.
+ Can be inserted as a submatch.
+ """
+ if not isinstance(item, CharsetMatch):
+ raise ValueError(
+ "Cannot append instance '{}' to CharsetMatches".format(
+ str(item.__class__)
+ )
+ )
+ # We should disable the submatch factoring when the input file is too heavy (conserve RAM usage)
+ if len(item.raw) < TOO_BIG_SEQUENCE:
+ for match in self._results:
+ if match.fingerprint == item.fingerprint and match.chaos == item.chaos:
+ match.add_submatch(item)
+ return
+ self._results.append(item)
+ self._results = sorted(self._results)
+
+ def best(self) -> CharsetMatch | None:
+ """
+ Simply return the first match. Strict equivalent to matches[0].
+ """
+ if not self._results:
+ return None
+ return self._results[0]
+
+ def first(self) -> CharsetMatch | None:
+ """
+ Redundant method, call the method best(). Kept for BC reasons.
+ """
+ return self.best()
+
+
+CoherenceMatch = Tuple[str, float]
+CoherenceMatches = List[CoherenceMatch]
+
+
+class CliDetectionResult:
+ def __init__(
+ self,
+ path: str,
+ encoding: str | None,
+ encoding_aliases: list[str],
+ alternative_encodings: list[str],
+ language: str,
+ alphabets: list[str],
+ has_sig_or_bom: bool,
+ chaos: float,
+ coherence: float,
+ unicode_path: str | None,
+ is_preferred: bool,
+ ):
+ self.path: str = path
+ self.unicode_path: str | None = unicode_path
+ self.encoding: str | None = encoding
+ self.encoding_aliases: list[str] = encoding_aliases
+ self.alternative_encodings: list[str] = alternative_encodings
+ self.language: str = language
+ self.alphabets: list[str] = alphabets
+ self.has_sig_or_bom: bool = has_sig_or_bom
+ self.chaos: float = chaos
+ self.coherence: float = coherence
+ self.is_preferred: bool = is_preferred
+
+ @property
+ def __dict__(self) -> dict[str, Any]: # type: ignore
+ return {
+ "path": self.path,
+ "encoding": self.encoding,
+ "encoding_aliases": self.encoding_aliases,
+ "alternative_encodings": self.alternative_encodings,
+ "language": self.language,
+ "alphabets": self.alphabets,
+ "has_sig_or_bom": self.has_sig_or_bom,
+ "chaos": self.chaos,
+ "coherence": self.coherence,
+ "unicode_path": self.unicode_path,
+ "is_preferred": self.is_preferred,
+ }
+
+ def to_json(self) -> str:
+ return dumps(self.__dict__, ensure_ascii=True, indent=4)
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__init__.py b/testcline/lib/python3.12/site-packages/charset_normalizer/py.typed
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__init__.py
rename to testcline/lib/python3.12/site-packages/charset_normalizer/py.typed
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/utils.py b/testcline/lib/python3.12/site-packages/charset_normalizer/utils.py
new file mode 100644
index 0000000..0175e0a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/utils.py
@@ -0,0 +1,408 @@
+from __future__ import annotations
+
+import importlib
+import logging
+import unicodedata
+from codecs import IncrementalDecoder
+from encodings.aliases import aliases
+from functools import lru_cache
+from re import findall
+from typing import Generator
+
+from _multibytecodec import ( # type: ignore[import-not-found,import]
+ MultibyteIncrementalDecoder,
+)
+
+from .constant import (
+ ENCODING_MARKS,
+ IANA_SUPPORTED_SIMILAR,
+ RE_POSSIBLE_ENCODING_INDICATION,
+ UNICODE_RANGES_COMBINED,
+ UNICODE_SECONDARY_RANGE_KEYWORD,
+ UTF8_MAXIMAL_ALLOCATION,
+)
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_accentuated(character: str) -> bool:
+ try:
+ description: str = unicodedata.name(character)
+ except ValueError: # Defensive: unicode database outdated?
+ return False
+ return (
+ "WITH GRAVE" in description
+ or "WITH ACUTE" in description
+ or "WITH CEDILLA" in description
+ or "WITH DIAERESIS" in description
+ or "WITH CIRCUMFLEX" in description
+ or "WITH TILDE" in description
+ or "WITH MACRON" in description
+ or "WITH RING ABOVE" in description
+ )
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def remove_accent(character: str) -> str:
+ decomposed: str = unicodedata.decomposition(character)
+ if not decomposed:
+ return character
+
+ codes: list[str] = decomposed.split(" ")
+
+ return chr(int(codes[0], 16))
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def unicode_range(character: str) -> str | None:
+ """
+ Retrieve the Unicode range official name from a single character.
+ """
+ character_ord: int = ord(character)
+
+ for range_name, ord_range in UNICODE_RANGES_COMBINED.items():
+ if character_ord in ord_range:
+ return range_name
+
+ return None
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_latin(character: str) -> bool:
+ try:
+ description: str = unicodedata.name(character)
+ except ValueError: # Defensive: unicode database outdated?
+ return False
+ return "LATIN" in description
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_punctuation(character: str) -> bool:
+ character_category: str = unicodedata.category(character)
+
+ if "P" in character_category:
+ return True
+
+ character_range: str | None = unicode_range(character)
+
+ if character_range is None:
+ return False
+
+ return "Punctuation" in character_range
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_symbol(character: str) -> bool:
+ character_category: str = unicodedata.category(character)
+
+ if "S" in character_category or "N" in character_category:
+ return True
+
+ character_range: str | None = unicode_range(character)
+
+ if character_range is None:
+ return False
+
+ return "Forms" in character_range and character_category != "Lo"
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_emoticon(character: str) -> bool:
+ character_range: str | None = unicode_range(character)
+
+ if character_range is None:
+ return False
+
+ return "Emoticons" in character_range or "Pictographs" in character_range
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_separator(character: str) -> bool:
+ if character.isspace() or character in {"|", "+", "<", ">"}:
+ return True
+
+ character_category: str = unicodedata.category(character)
+
+ return "Z" in character_category or character_category in {"Po", "Pd", "Pc"}
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_case_variable(character: str) -> bool:
+ return character.islower() != character.isupper()
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_cjk(character: str) -> bool:
+ try:
+ character_name = unicodedata.name(character)
+ except ValueError: # Defensive: unicode database outdated?
+ return False
+
+ return "CJK" in character_name
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_hiragana(character: str) -> bool:
+ try:
+ character_name = unicodedata.name(character)
+ except ValueError: # Defensive: unicode database outdated?
+ return False
+
+ return "HIRAGANA" in character_name
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_katakana(character: str) -> bool:
+ try:
+ character_name = unicodedata.name(character)
+ except ValueError: # Defensive: unicode database outdated?
+ return False
+
+ return "KATAKANA" in character_name
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_hangul(character: str) -> bool:
+ try:
+ character_name = unicodedata.name(character)
+ except ValueError: # Defensive: unicode database outdated?
+ return False
+
+ return "HANGUL" in character_name
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_thai(character: str) -> bool:
+ try:
+ character_name = unicodedata.name(character)
+ except ValueError: # Defensive: unicode database outdated?
+ return False
+
+ return "THAI" in character_name
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_arabic(character: str) -> bool:
+ try:
+ character_name = unicodedata.name(character)
+ except ValueError: # Defensive: unicode database outdated?
+ return False
+
+ return "ARABIC" in character_name
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_arabic_isolated_form(character: str) -> bool:
+ try:
+ character_name = unicodedata.name(character)
+ except ValueError: # Defensive: unicode database outdated?
+ return False
+
+ return "ARABIC" in character_name and "ISOLATED FORM" in character_name
+
+
+@lru_cache(maxsize=len(UNICODE_RANGES_COMBINED))
+def is_unicode_range_secondary(range_name: str) -> bool:
+ return any(keyword in range_name for keyword in UNICODE_SECONDARY_RANGE_KEYWORD)
+
+
+@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION)
+def is_unprintable(character: str) -> bool:
+ return (
+ character.isspace() is False # includes \n \t \r \v
+ and character.isprintable() is False
+ and character != "\x1a" # Why? Its the ASCII substitute character.
+ and character != "\ufeff" # bug discovered in Python,
+ # Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space.
+ )
+
+
+def any_specified_encoding(sequence: bytes, search_zone: int = 8192) -> str | None:
+ """
+ Extract using ASCII-only decoder any specified encoding in the first n-bytes.
+ """
+ if not isinstance(sequence, bytes):
+ raise TypeError
+
+ seq_len: int = len(sequence)
+
+ results: list[str] = findall(
+ RE_POSSIBLE_ENCODING_INDICATION,
+ sequence[: min(seq_len, search_zone)].decode("ascii", errors="ignore"),
+ )
+
+ if len(results) == 0:
+ return None
+
+ for specified_encoding in results:
+ specified_encoding = specified_encoding.lower().replace("-", "_")
+
+ encoding_alias: str
+ encoding_iana: str
+
+ for encoding_alias, encoding_iana in aliases.items():
+ if encoding_alias == specified_encoding:
+ return encoding_iana
+ if encoding_iana == specified_encoding:
+ return encoding_iana
+
+ return None
+
+
+@lru_cache(maxsize=128)
+def is_multi_byte_encoding(name: str) -> bool:
+ """
+ Verify is a specific encoding is a multi byte one based on it IANA name
+ """
+ return name in {
+ "utf_8",
+ "utf_8_sig",
+ "utf_16",
+ "utf_16_be",
+ "utf_16_le",
+ "utf_32",
+ "utf_32_le",
+ "utf_32_be",
+ "utf_7",
+ } or issubclass(
+ importlib.import_module(f"encodings.{name}").IncrementalDecoder,
+ MultibyteIncrementalDecoder,
+ )
+
+
+def identify_sig_or_bom(sequence: bytes) -> tuple[str | None, bytes]:
+ """
+ Identify and extract SIG/BOM in given sequence.
+ """
+
+ for iana_encoding in ENCODING_MARKS:
+ marks: bytes | list[bytes] = ENCODING_MARKS[iana_encoding]
+
+ if isinstance(marks, bytes):
+ marks = [marks]
+
+ for mark in marks:
+ if sequence.startswith(mark):
+ return iana_encoding, mark
+
+ return None, b""
+
+
+def should_strip_sig_or_bom(iana_encoding: str) -> bool:
+ return iana_encoding not in {"utf_16", "utf_32"}
+
+
+def iana_name(cp_name: str, strict: bool = True) -> str:
+ """Returns the Python normalized encoding name (Not the IANA official name)."""
+ cp_name = cp_name.lower().replace("-", "_")
+
+ encoding_alias: str
+ encoding_iana: str
+
+ for encoding_alias, encoding_iana in aliases.items():
+ if cp_name in [encoding_alias, encoding_iana]:
+ return encoding_iana
+
+ if strict:
+ raise ValueError(f"Unable to retrieve IANA for '{cp_name}'")
+
+ return cp_name
+
+
+def cp_similarity(iana_name_a: str, iana_name_b: str) -> float:
+ if is_multi_byte_encoding(iana_name_a) or is_multi_byte_encoding(iana_name_b):
+ return 0.0
+
+ decoder_a = importlib.import_module(f"encodings.{iana_name_a}").IncrementalDecoder
+ decoder_b = importlib.import_module(f"encodings.{iana_name_b}").IncrementalDecoder
+
+ id_a: IncrementalDecoder = decoder_a(errors="ignore")
+ id_b: IncrementalDecoder = decoder_b(errors="ignore")
+
+ character_match_count: int = 0
+
+ for i in range(255):
+ to_be_decoded: bytes = bytes([i])
+ if id_a.decode(to_be_decoded) == id_b.decode(to_be_decoded):
+ character_match_count += 1
+
+ return character_match_count / 254
+
+
+def is_cp_similar(iana_name_a: str, iana_name_b: str) -> bool:
+ """
+ Determine if two code page are at least 80% similar. IANA_SUPPORTED_SIMILAR dict was generated using
+ the function cp_similarity.
+ """
+ return (
+ iana_name_a in IANA_SUPPORTED_SIMILAR
+ and iana_name_b in IANA_SUPPORTED_SIMILAR[iana_name_a]
+ )
+
+
+def set_logging_handler(
+ name: str = "charset_normalizer",
+ level: int = logging.INFO,
+ format_string: str = "%(asctime)s | %(levelname)s | %(message)s",
+) -> None:
+ logger = logging.getLogger(name)
+ logger.setLevel(level)
+
+ handler = logging.StreamHandler()
+ handler.setFormatter(logging.Formatter(format_string))
+ logger.addHandler(handler)
+
+
+def cut_sequence_chunks(
+ sequences: bytes,
+ encoding_iana: str,
+ offsets: range,
+ chunk_size: int,
+ bom_or_sig_available: bool,
+ strip_sig_or_bom: bool,
+ sig_payload: bytes,
+ is_multi_byte_decoder: bool,
+ decoded_payload: str | None = None,
+) -> Generator[str, None, None]:
+ if decoded_payload and is_multi_byte_decoder is False:
+ for i in offsets:
+ chunk = decoded_payload[i : i + chunk_size]
+ if not chunk:
+ break
+ yield chunk
+ else:
+ for i in offsets:
+ chunk_end = i + chunk_size
+ if chunk_end > len(sequences) + 8:
+ continue
+
+ cut_sequence = sequences[i : i + chunk_size]
+
+ if bom_or_sig_available and strip_sig_or_bom is False:
+ cut_sequence = sig_payload + cut_sequence
+
+ chunk = cut_sequence.decode(
+ encoding_iana,
+ errors="ignore" if is_multi_byte_decoder else "strict",
+ )
+
+ # multi-byte bad cutting detector and adjustment
+ # not the cleanest way to perform that fix but clever enough for now.
+ if is_multi_byte_decoder and i > 0:
+ chunk_partial_size_chk: int = min(chunk_size, 16)
+
+ if (
+ decoded_payload
+ and chunk[:chunk_partial_size_chk] not in decoded_payload
+ ):
+ for j in range(i, i - 4, -1):
+ cut_sequence = sequences[j:chunk_end]
+
+ if bom_or_sig_available and strip_sig_or_bom is False:
+ cut_sequence = sig_payload + cut_sequence
+
+ chunk = cut_sequence.decode(encoding_iana, errors="ignore")
+
+ if chunk[:chunk_partial_size_chk] in decoded_payload:
+ break
+
+ yield chunk
diff --git a/testcline/lib/python3.12/site-packages/charset_normalizer/version.py b/testcline/lib/python3.12/site-packages/charset_normalizer/version.py
new file mode 100644
index 0000000..f85e892
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/charset_normalizer/version.py
@@ -0,0 +1,8 @@
+"""
+Expose version
+"""
+
+from __future__ import annotations
+
+__version__ = "3.4.1"
+VERSION = __version__.split(".")
diff --git a/testcline/lib/python3.12/site-packages/distutils-precedence.pth b/testcline/lib/python3.12/site-packages/distutils-precedence.pth
new file mode 100644
index 0000000..7f009fe
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/distutils-precedence.pth
@@ -0,0 +1 @@
+import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'local') == 'local'; enabled and __import__('_distutils_hack').add_shim();
diff --git a/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/LICENSE.md b/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/LICENSE.md
new file mode 100644
index 0000000..19b6b45
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/LICENSE.md
@@ -0,0 +1,31 @@
+BSD 3-Clause License
+
+Copyright (c) 2013-2024, Kim Davies and contributors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/METADATA b/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/METADATA
new file mode 100644
index 0000000..c42623e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/METADATA
@@ -0,0 +1,250 @@
+Metadata-Version: 2.1
+Name: idna
+Version: 3.10
+Summary: Internationalized Domain Names in Applications (IDNA)
+Author-email: Kim Davies
+Requires-Python: >=3.6
+Description-Content-Type: text/x-rst
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+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 :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Internet :: Name Service (DNS)
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Utilities
+Requires-Dist: ruff >= 0.6.2 ; extra == "all"
+Requires-Dist: mypy >= 1.11.2 ; extra == "all"
+Requires-Dist: pytest >= 8.3.2 ; extra == "all"
+Requires-Dist: flake8 >= 7.1.1 ; extra == "all"
+Project-URL: Changelog, https://github.com/kjd/idna/blob/master/HISTORY.rst
+Project-URL: Issue tracker, https://github.com/kjd/idna/issues
+Project-URL: Source, https://github.com/kjd/idna
+Provides-Extra: all
+
+Internationalized Domain Names in Applications (IDNA)
+=====================================================
+
+Support for the Internationalized Domain Names in
+Applications (IDNA) protocol as specified in `RFC 5891
+`_. This is the latest version of
+the protocol and is sometimes referred to as “IDNA 2008”.
+
+This library also provides support for Unicode Technical
+Standard 46, `Unicode IDNA Compatibility Processing
+`_.
+
+This acts as a suitable replacement for the “encodings.idna”
+module that comes with the Python standard library, but which
+only supports the older superseded IDNA specification (`RFC 3490
+`_).
+
+Basic functions are simply executed:
+
+.. code-block:: pycon
+
+ >>> import idna
+ >>> idna.encode('ドメイン.テスト')
+ b'xn--eckwd4c7c.xn--zckzah'
+ >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah'))
+ ドメイン.テスト
+
+
+Installation
+------------
+
+This package is available for installation from PyPI:
+
+.. code-block:: bash
+
+ $ python3 -m pip install idna
+
+
+Usage
+-----
+
+For typical usage, the ``encode`` and ``decode`` functions will take a
+domain name argument and perform a conversion to A-labels or U-labels
+respectively.
+
+.. code-block:: pycon
+
+ >>> import idna
+ >>> idna.encode('ドメイン.テスト')
+ b'xn--eckwd4c7c.xn--zckzah'
+ >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah'))
+ ドメイン.テスト
+
+You may use the codec encoding and decoding methods using the
+``idna.codec`` module:
+
+.. code-block:: pycon
+
+ >>> import idna.codec
+ >>> print('домен.испытание'.encode('idna2008'))
+ b'xn--d1acufc.xn--80akhbyknj4f'
+ >>> print(b'xn--d1acufc.xn--80akhbyknj4f'.decode('idna2008'))
+ домен.испытание
+
+Conversions can be applied at a per-label basis using the ``ulabel`` or
+``alabel`` functions if necessary:
+
+.. code-block:: pycon
+
+ >>> idna.alabel('测试')
+ b'xn--0zwm56d'
+
+Compatibility Mapping (UTS #46)
++++++++++++++++++++++++++++++++
+
+As described in `RFC 5895 `_, the
+IDNA specification does not normalize input from different potential
+ways a user may input a domain name. This functionality, known as
+a “mapping”, is considered by the specification to be a local
+user-interface issue distinct from IDNA conversion functionality.
+
+This library provides one such mapping that was developed by the
+Unicode Consortium. Known as `Unicode IDNA Compatibility Processing
+`_, it provides for both a regular
+mapping for typical applications, as well as a transitional mapping to
+help migrate from older IDNA 2003 applications. Strings are
+preprocessed according to Section 4.4 “Preprocessing for IDNA2008”
+prior to the IDNA operations.
+
+For example, “Königsgäßchen” is not a permissible label as *LATIN
+CAPITAL LETTER K* is not allowed (nor are capital letters in general).
+UTS 46 will convert this into lower case prior to applying the IDNA
+conversion.
+
+.. code-block:: pycon
+
+ >>> import idna
+ >>> idna.encode('Königsgäßchen')
+ ...
+ idna.core.InvalidCodepoint: Codepoint U+004B at position 1 of 'Königsgäßchen' not allowed
+ >>> idna.encode('Königsgäßchen', uts46=True)
+ b'xn--knigsgchen-b4a3dun'
+ >>> print(idna.decode('xn--knigsgchen-b4a3dun'))
+ königsgäßchen
+
+Transitional processing provides conversions to help transition from
+the older 2003 standard to the current standard. For example, in the
+original IDNA specification, the *LATIN SMALL LETTER SHARP S* (ß) was
+converted into two *LATIN SMALL LETTER S* (ss), whereas in the current
+IDNA specification this conversion is not performed.
+
+.. code-block:: pycon
+
+ >>> idna.encode('Königsgäßchen', uts46=True, transitional=True)
+ 'xn--knigsgsschen-lcb0w'
+
+Implementers should use transitional processing with caution, only in
+rare cases where conversion from legacy labels to current labels must be
+performed (i.e. IDNA implementations that pre-date 2008). For typical
+applications that just need to convert labels, transitional processing
+is unlikely to be beneficial and could produce unexpected incompatible
+results.
+
+``encodings.idna`` Compatibility
+++++++++++++++++++++++++++++++++
+
+Function calls from the Python built-in ``encodings.idna`` module are
+mapped to their IDNA 2008 equivalents using the ``idna.compat`` module.
+Simply substitute the ``import`` clause in your code to refer to the new
+module name.
+
+Exceptions
+----------
+
+All errors raised during the conversion following the specification
+should raise an exception derived from the ``idna.IDNAError`` base
+class.
+
+More specific exceptions that may be generated as ``idna.IDNABidiError``
+when the error reflects an illegal combination of left-to-right and
+right-to-left characters in a label; ``idna.InvalidCodepoint`` when
+a specific codepoint is an illegal character in an IDN label (i.e.
+INVALID); and ``idna.InvalidCodepointContext`` when the codepoint is
+illegal based on its positional context (i.e. it is CONTEXTO or CONTEXTJ
+but the contextual requirements are not satisfied.)
+
+Building and Diagnostics
+------------------------
+
+The IDNA and UTS 46 functionality relies upon pre-calculated lookup
+tables for performance. These tables are derived from computing against
+eligibility criteria in the respective standards. These tables are
+computed using the command-line script ``tools/idna-data``.
+
+This tool will fetch relevant codepoint data from the Unicode repository
+and perform the required calculations to identify eligibility. There are
+three main modes:
+
+* ``idna-data make-libdata``. Generates ``idnadata.py`` and
+ ``uts46data.py``, the pre-calculated lookup tables used for IDNA and
+ UTS 46 conversions. Implementers who wish to track this library against
+ a different Unicode version may use this tool to manually generate a
+ different version of the ``idnadata.py`` and ``uts46data.py`` files.
+
+* ``idna-data make-table``. Generate a table of the IDNA disposition
+ (e.g. PVALID, CONTEXTJ, CONTEXTO) in the format found in Appendix
+ B.1 of RFC 5892 and the pre-computed tables published by `IANA
+ `_.
+
+* ``idna-data U+0061``. Prints debugging output on the various
+ properties associated with an individual Unicode codepoint (in this
+ case, U+0061), that are used to assess the IDNA and UTS 46 status of a
+ codepoint. This is helpful in debugging or analysis.
+
+The tool accepts a number of arguments, described using ``idna-data
+-h``. Most notably, the ``--version`` argument allows the specification
+of the version of Unicode to be used in computing the table data. For
+example, ``idna-data --version 9.0.0 make-libdata`` will generate
+library data against Unicode 9.0.0.
+
+
+Additional Notes
+----------------
+
+* **Packages**. The latest tagged release version is published in the
+ `Python Package Index `_.
+
+* **Version support**. This library supports Python 3.6 and higher.
+ As this library serves as a low-level toolkit for a variety of
+ applications, many of which strive for broad compatibility with older
+ Python versions, there is no rush to remove older interpreter support.
+ Removing support for older versions should be well justified in that the
+ maintenance burden has become too high.
+
+* **Python 2**. Python 2 is supported by version 2.x of this library.
+ Use "idna<3" in your requirements file if you need this library for
+ a Python 2 application. Be advised that these versions are no longer
+ actively developed.
+
+* **Testing**. The library has a test suite based on each rule of the
+ IDNA specification, as well as tests that are provided as part of the
+ Unicode Technical Standard 46, `Unicode IDNA Compatibility Processing
+ `_.
+
+* **Emoji**. It is an occasional request to support emoji domains in
+ this library. Encoding of symbols like emoji is expressly prohibited by
+ the technical standard IDNA 2008 and emoji domains are broadly phased
+ out across the domain industry due to associated security risks. For
+ now, applications that need to support these non-compliant labels
+ may wish to consider trying the encode/decode operation in this library
+ first, and then falling back to using `encodings.idna`. See `the Github
+ project `_ for more discussion.
+
diff --git a/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/RECORD b/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/RECORD
new file mode 100644
index 0000000..9cfce7f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/RECORD
@@ -0,0 +1,22 @@
+idna-3.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+idna-3.10.dist-info/LICENSE.md,sha256=pZ8LDvNjWHQQmkRhykT_enDVBpboFHZ7-vch1Mmw2w8,1541
+idna-3.10.dist-info/METADATA,sha256=URR5ZyDfQ1PCEGhkYoojqfi2Ra0tau2--lhwG4XSfjI,10158
+idna-3.10.dist-info/RECORD,,
+idna-3.10.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
+idna/__init__.py,sha256=MPqNDLZbXqGaNdXxAFhiqFPKEQXju2jNQhCey6-5eJM,868
+idna/__pycache__/__init__.cpython-312.pyc,,
+idna/__pycache__/codec.cpython-312.pyc,,
+idna/__pycache__/compat.cpython-312.pyc,,
+idna/__pycache__/core.cpython-312.pyc,,
+idna/__pycache__/idnadata.cpython-312.pyc,,
+idna/__pycache__/intranges.cpython-312.pyc,,
+idna/__pycache__/package_data.cpython-312.pyc,,
+idna/__pycache__/uts46data.cpython-312.pyc,,
+idna/codec.py,sha256=PEew3ItwzjW4hymbasnty2N2OXvNcgHB-JjrBuxHPYY,3422
+idna/compat.py,sha256=RzLy6QQCdl9784aFhb2EX9EKGCJjg0P3PilGdeXXcx8,316
+idna/core.py,sha256=YJYyAMnwiQEPjVC4-Fqu_p4CJ6yKKuDGmppBNQNQpFs,13239
+idna/idnadata.py,sha256=W30GcIGvtOWYwAjZj4ZjuouUutC6ffgNuyjJy7fZ-lo,78306
+idna/intranges.py,sha256=amUtkdhYcQG8Zr-CoMM_kVRacxkivC1WgxN1b63KKdU,1898
+idna/package_data.py,sha256=q59S3OXsc5VI8j6vSD0sGBMyk6zZ4vWFREE88yCJYKs,21
+idna/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+idna/uts46data.py,sha256=rt90K9J40gUSwppDPCrhjgi5AA6pWM65dEGRSf6rIhM,239289
diff --git a/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/WHEEL
new file mode 100644
index 0000000..3b5e64b
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna-3.10.dist-info/WHEEL
@@ -0,0 +1,4 @@
+Wheel-Version: 1.0
+Generator: flit 3.9.0
+Root-Is-Purelib: true
+Tag: py3-none-any
diff --git a/testcline/lib/python3.12/site-packages/idna/__init__.py b/testcline/lib/python3.12/site-packages/idna/__init__.py
new file mode 100644
index 0000000..cfdc030
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna/__init__.py
@@ -0,0 +1,45 @@
+from .core import (
+ IDNABidiError,
+ IDNAError,
+ InvalidCodepoint,
+ InvalidCodepointContext,
+ alabel,
+ check_bidi,
+ check_hyphen_ok,
+ check_initial_combiner,
+ check_label,
+ check_nfc,
+ decode,
+ encode,
+ ulabel,
+ uts46_remap,
+ valid_contextj,
+ valid_contexto,
+ valid_label_length,
+ valid_string_length,
+)
+from .intranges import intranges_contain
+from .package_data import __version__
+
+__all__ = [
+ "__version__",
+ "IDNABidiError",
+ "IDNAError",
+ "InvalidCodepoint",
+ "InvalidCodepointContext",
+ "alabel",
+ "check_bidi",
+ "check_hyphen_ok",
+ "check_initial_combiner",
+ "check_label",
+ "check_nfc",
+ "decode",
+ "encode",
+ "intranges_contain",
+ "ulabel",
+ "uts46_remap",
+ "valid_contextj",
+ "valid_contexto",
+ "valid_label_length",
+ "valid_string_length",
+]
diff --git a/testcline/lib/python3.12/site-packages/idna/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/idna/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..857eb1c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/idna/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/idna/__pycache__/codec.cpython-312.pyc b/testcline/lib/python3.12/site-packages/idna/__pycache__/codec.cpython-312.pyc
new file mode 100644
index 0000000..6cd6e8e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/idna/__pycache__/codec.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/idna/__pycache__/compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/idna/__pycache__/compat.cpython-312.pyc
new file mode 100644
index 0000000..4dadb6f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/idna/__pycache__/compat.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/idna/__pycache__/core.cpython-312.pyc b/testcline/lib/python3.12/site-packages/idna/__pycache__/core.cpython-312.pyc
new file mode 100644
index 0000000..83f2869
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/idna/__pycache__/core.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/idna/__pycache__/idnadata.cpython-312.pyc b/testcline/lib/python3.12/site-packages/idna/__pycache__/idnadata.cpython-312.pyc
new file mode 100644
index 0000000..e761a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/idna/__pycache__/idnadata.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/idna/__pycache__/intranges.cpython-312.pyc b/testcline/lib/python3.12/site-packages/idna/__pycache__/intranges.cpython-312.pyc
new file mode 100644
index 0000000..9384183
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/idna/__pycache__/intranges.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/idna/__pycache__/package_data.cpython-312.pyc b/testcline/lib/python3.12/site-packages/idna/__pycache__/package_data.cpython-312.pyc
new file mode 100644
index 0000000..85da58f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/idna/__pycache__/package_data.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/idna/__pycache__/uts46data.cpython-312.pyc b/testcline/lib/python3.12/site-packages/idna/__pycache__/uts46data.cpython-312.pyc
new file mode 100644
index 0000000..af8b12a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/idna/__pycache__/uts46data.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/idna/codec.py b/testcline/lib/python3.12/site-packages/idna/codec.py
new file mode 100644
index 0000000..913abfd
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna/codec.py
@@ -0,0 +1,122 @@
+import codecs
+import re
+from typing import Any, Optional, Tuple
+
+from .core import IDNAError, alabel, decode, encode, ulabel
+
+_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]")
+
+
+class Codec(codecs.Codec):
+ def encode(self, data: str, errors: str = "strict") -> Tuple[bytes, int]:
+ if errors != "strict":
+ raise IDNAError('Unsupported error handling "{}"'.format(errors))
+
+ if not data:
+ return b"", 0
+
+ return encode(data), len(data)
+
+ def decode(self, data: bytes, errors: str = "strict") -> Tuple[str, int]:
+ if errors != "strict":
+ raise IDNAError('Unsupported error handling "{}"'.format(errors))
+
+ if not data:
+ return "", 0
+
+ return decode(data), len(data)
+
+
+class IncrementalEncoder(codecs.BufferedIncrementalEncoder):
+ def _buffer_encode(self, data: str, errors: str, final: bool) -> Tuple[bytes, int]:
+ if errors != "strict":
+ raise IDNAError('Unsupported error handling "{}"'.format(errors))
+
+ if not data:
+ return b"", 0
+
+ labels = _unicode_dots_re.split(data)
+ trailing_dot = b""
+ if labels:
+ if not labels[-1]:
+ trailing_dot = b"."
+ del labels[-1]
+ elif not final:
+ # Keep potentially unfinished label until the next call
+ del labels[-1]
+ if labels:
+ trailing_dot = b"."
+
+ result = []
+ size = 0
+ for label in labels:
+ result.append(alabel(label))
+ if size:
+ size += 1
+ size += len(label)
+
+ # Join with U+002E
+ result_bytes = b".".join(result) + trailing_dot
+ size += len(trailing_dot)
+ return result_bytes, size
+
+
+class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
+ def _buffer_decode(self, data: Any, errors: str, final: bool) -> Tuple[str, int]:
+ if errors != "strict":
+ raise IDNAError('Unsupported error handling "{}"'.format(errors))
+
+ if not data:
+ return ("", 0)
+
+ if not isinstance(data, str):
+ data = str(data, "ascii")
+
+ labels = _unicode_dots_re.split(data)
+ trailing_dot = ""
+ if labels:
+ if not labels[-1]:
+ trailing_dot = "."
+ del labels[-1]
+ elif not final:
+ # Keep potentially unfinished label until the next call
+ del labels[-1]
+ if labels:
+ trailing_dot = "."
+
+ result = []
+ size = 0
+ for label in labels:
+ result.append(ulabel(label))
+ if size:
+ size += 1
+ size += len(label)
+
+ result_str = ".".join(result) + trailing_dot
+ size += len(trailing_dot)
+ return (result_str, size)
+
+
+class StreamWriter(Codec, codecs.StreamWriter):
+ pass
+
+
+class StreamReader(Codec, codecs.StreamReader):
+ pass
+
+
+def search_function(name: str) -> Optional[codecs.CodecInfo]:
+ if name != "idna2008":
+ return None
+ return codecs.CodecInfo(
+ name=name,
+ encode=Codec().encode,
+ decode=Codec().decode,
+ incrementalencoder=IncrementalEncoder,
+ incrementaldecoder=IncrementalDecoder,
+ streamwriter=StreamWriter,
+ streamreader=StreamReader,
+ )
+
+
+codecs.register(search_function)
diff --git a/testcline/lib/python3.12/site-packages/idna/compat.py b/testcline/lib/python3.12/site-packages/idna/compat.py
new file mode 100644
index 0000000..1df9f2a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna/compat.py
@@ -0,0 +1,15 @@
+from typing import Any, Union
+
+from .core import decode, encode
+
+
+def ToASCII(label: str) -> bytes:
+ return encode(label)
+
+
+def ToUnicode(label: Union[bytes, bytearray]) -> str:
+ return decode(label)
+
+
+def nameprep(s: Any) -> None:
+ raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol")
diff --git a/testcline/lib/python3.12/site-packages/idna/core.py b/testcline/lib/python3.12/site-packages/idna/core.py
new file mode 100644
index 0000000..9115f12
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna/core.py
@@ -0,0 +1,437 @@
+import bisect
+import re
+import unicodedata
+from typing import Optional, Union
+
+from . import idnadata
+from .intranges import intranges_contain
+
+_virama_combining_class = 9
+_alabel_prefix = b"xn--"
+_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]")
+
+
+class IDNAError(UnicodeError):
+ """Base exception for all IDNA-encoding related problems"""
+
+ pass
+
+
+class IDNABidiError(IDNAError):
+ """Exception when bidirectional requirements are not satisfied"""
+
+ pass
+
+
+class InvalidCodepoint(IDNAError):
+ """Exception when a disallowed or unallocated codepoint is used"""
+
+ pass
+
+
+class InvalidCodepointContext(IDNAError):
+ """Exception when the codepoint is not valid in the context it is used"""
+
+ pass
+
+
+def _combining_class(cp: int) -> int:
+ v = unicodedata.combining(chr(cp))
+ if v == 0:
+ if not unicodedata.name(chr(cp)):
+ raise ValueError("Unknown character in unicodedata")
+ return v
+
+
+def _is_script(cp: str, script: str) -> bool:
+ return intranges_contain(ord(cp), idnadata.scripts[script])
+
+
+def _punycode(s: str) -> bytes:
+ return s.encode("punycode")
+
+
+def _unot(s: int) -> str:
+ return "U+{:04X}".format(s)
+
+
+def valid_label_length(label: Union[bytes, str]) -> bool:
+ if len(label) > 63:
+ return False
+ return True
+
+
+def valid_string_length(label: Union[bytes, str], trailing_dot: bool) -> bool:
+ if len(label) > (254 if trailing_dot else 253):
+ return False
+ return True
+
+
+def check_bidi(label: str, check_ltr: bool = False) -> bool:
+ # Bidi rules should only be applied if string contains RTL characters
+ bidi_label = False
+ for idx, cp in enumerate(label, 1):
+ direction = unicodedata.bidirectional(cp)
+ if direction == "":
+ # String likely comes from a newer version of Unicode
+ raise IDNABidiError("Unknown directionality in label {} at position {}".format(repr(label), idx))
+ if direction in ["R", "AL", "AN"]:
+ bidi_label = True
+ if not bidi_label and not check_ltr:
+ return True
+
+ # Bidi rule 1
+ direction = unicodedata.bidirectional(label[0])
+ if direction in ["R", "AL"]:
+ rtl = True
+ elif direction == "L":
+ rtl = False
+ else:
+ raise IDNABidiError("First codepoint in label {} must be directionality L, R or AL".format(repr(label)))
+
+ valid_ending = False
+ number_type: Optional[str] = None
+ for idx, cp in enumerate(label, 1):
+ direction = unicodedata.bidirectional(cp)
+
+ if rtl:
+ # Bidi rule 2
+ if direction not in [
+ "R",
+ "AL",
+ "AN",
+ "EN",
+ "ES",
+ "CS",
+ "ET",
+ "ON",
+ "BN",
+ "NSM",
+ ]:
+ raise IDNABidiError("Invalid direction for codepoint at position {} in a right-to-left label".format(idx))
+ # Bidi rule 3
+ if direction in ["R", "AL", "EN", "AN"]:
+ valid_ending = True
+ elif direction != "NSM":
+ valid_ending = False
+ # Bidi rule 4
+ if direction in ["AN", "EN"]:
+ if not number_type:
+ number_type = direction
+ else:
+ if number_type != direction:
+ raise IDNABidiError("Can not mix numeral types in a right-to-left label")
+ else:
+ # Bidi rule 5
+ if direction not in ["L", "EN", "ES", "CS", "ET", "ON", "BN", "NSM"]:
+ raise IDNABidiError("Invalid direction for codepoint at position {} in a left-to-right label".format(idx))
+ # Bidi rule 6
+ if direction in ["L", "EN"]:
+ valid_ending = True
+ elif direction != "NSM":
+ valid_ending = False
+
+ if not valid_ending:
+ raise IDNABidiError("Label ends with illegal codepoint directionality")
+
+ return True
+
+
+def check_initial_combiner(label: str) -> bool:
+ if unicodedata.category(label[0])[0] == "M":
+ raise IDNAError("Label begins with an illegal combining character")
+ return True
+
+
+def check_hyphen_ok(label: str) -> bool:
+ if label[2:4] == "--":
+ raise IDNAError("Label has disallowed hyphens in 3rd and 4th position")
+ if label[0] == "-" or label[-1] == "-":
+ raise IDNAError("Label must not start or end with a hyphen")
+ return True
+
+
+def check_nfc(label: str) -> None:
+ if unicodedata.normalize("NFC", label) != label:
+ raise IDNAError("Label must be in Normalization Form C")
+
+
+def valid_contextj(label: str, pos: int) -> bool:
+ cp_value = ord(label[pos])
+
+ if cp_value == 0x200C:
+ if pos > 0:
+ if _combining_class(ord(label[pos - 1])) == _virama_combining_class:
+ return True
+
+ ok = False
+ for i in range(pos - 1, -1, -1):
+ joining_type = idnadata.joining_types.get(ord(label[i]))
+ if joining_type == ord("T"):
+ continue
+ elif joining_type in [ord("L"), ord("D")]:
+ ok = True
+ break
+ else:
+ break
+
+ if not ok:
+ return False
+
+ ok = False
+ for i in range(pos + 1, len(label)):
+ joining_type = idnadata.joining_types.get(ord(label[i]))
+ if joining_type == ord("T"):
+ continue
+ elif joining_type in [ord("R"), ord("D")]:
+ ok = True
+ break
+ else:
+ break
+ return ok
+
+ if cp_value == 0x200D:
+ if pos > 0:
+ if _combining_class(ord(label[pos - 1])) == _virama_combining_class:
+ return True
+ return False
+
+ else:
+ return False
+
+
+def valid_contexto(label: str, pos: int, exception: bool = False) -> bool:
+ cp_value = ord(label[pos])
+
+ if cp_value == 0x00B7:
+ if 0 < pos < len(label) - 1:
+ if ord(label[pos - 1]) == 0x006C and ord(label[pos + 1]) == 0x006C:
+ return True
+ return False
+
+ elif cp_value == 0x0375:
+ if pos < len(label) - 1 and len(label) > 1:
+ return _is_script(label[pos + 1], "Greek")
+ return False
+
+ elif cp_value == 0x05F3 or cp_value == 0x05F4:
+ if pos > 0:
+ return _is_script(label[pos - 1], "Hebrew")
+ return False
+
+ elif cp_value == 0x30FB:
+ for cp in label:
+ if cp == "\u30fb":
+ continue
+ if _is_script(cp, "Hiragana") or _is_script(cp, "Katakana") or _is_script(cp, "Han"):
+ return True
+ return False
+
+ elif 0x660 <= cp_value <= 0x669:
+ for cp in label:
+ if 0x6F0 <= ord(cp) <= 0x06F9:
+ return False
+ return True
+
+ elif 0x6F0 <= cp_value <= 0x6F9:
+ for cp in label:
+ if 0x660 <= ord(cp) <= 0x0669:
+ return False
+ return True
+
+ return False
+
+
+def check_label(label: Union[str, bytes, bytearray]) -> None:
+ if isinstance(label, (bytes, bytearray)):
+ label = label.decode("utf-8")
+ if len(label) == 0:
+ raise IDNAError("Empty Label")
+
+ check_nfc(label)
+ check_hyphen_ok(label)
+ check_initial_combiner(label)
+
+ for pos, cp in enumerate(label):
+ cp_value = ord(cp)
+ if intranges_contain(cp_value, idnadata.codepoint_classes["PVALID"]):
+ continue
+ elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTJ"]):
+ try:
+ if not valid_contextj(label, pos):
+ raise InvalidCodepointContext(
+ "Joiner {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label))
+ )
+ except ValueError:
+ raise IDNAError(
+ "Unknown codepoint adjacent to joiner {} at position {} in {}".format(
+ _unot(cp_value), pos + 1, repr(label)
+ )
+ )
+ elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTO"]):
+ if not valid_contexto(label, pos):
+ raise InvalidCodepointContext(
+ "Codepoint {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label))
+ )
+ else:
+ raise InvalidCodepoint(
+ "Codepoint {} at position {} of {} not allowed".format(_unot(cp_value), pos + 1, repr(label))
+ )
+
+ check_bidi(label)
+
+
+def alabel(label: str) -> bytes:
+ try:
+ label_bytes = label.encode("ascii")
+ ulabel(label_bytes)
+ if not valid_label_length(label_bytes):
+ raise IDNAError("Label too long")
+ return label_bytes
+ except UnicodeEncodeError:
+ pass
+
+ check_label(label)
+ label_bytes = _alabel_prefix + _punycode(label)
+
+ if not valid_label_length(label_bytes):
+ raise IDNAError("Label too long")
+
+ return label_bytes
+
+
+def ulabel(label: Union[str, bytes, bytearray]) -> str:
+ if not isinstance(label, (bytes, bytearray)):
+ try:
+ label_bytes = label.encode("ascii")
+ except UnicodeEncodeError:
+ check_label(label)
+ return label
+ else:
+ label_bytes = label
+
+ label_bytes = label_bytes.lower()
+ if label_bytes.startswith(_alabel_prefix):
+ label_bytes = label_bytes[len(_alabel_prefix) :]
+ if not label_bytes:
+ raise IDNAError("Malformed A-label, no Punycode eligible content found")
+ if label_bytes.decode("ascii")[-1] == "-":
+ raise IDNAError("A-label must not end with a hyphen")
+ else:
+ check_label(label_bytes)
+ return label_bytes.decode("ascii")
+
+ try:
+ label = label_bytes.decode("punycode")
+ except UnicodeError:
+ raise IDNAError("Invalid A-label")
+ check_label(label)
+ return label
+
+
+def uts46_remap(domain: str, std3_rules: bool = True, transitional: bool = False) -> str:
+ """Re-map the characters in the string according to UTS46 processing."""
+ from .uts46data import uts46data
+
+ output = ""
+
+ for pos, char in enumerate(domain):
+ code_point = ord(char)
+ try:
+ uts46row = uts46data[code_point if code_point < 256 else bisect.bisect_left(uts46data, (code_point, "Z")) - 1]
+ status = uts46row[1]
+ replacement: Optional[str] = None
+ if len(uts46row) == 3:
+ replacement = uts46row[2]
+ if (
+ status == "V"
+ or (status == "D" and not transitional)
+ or (status == "3" and not std3_rules and replacement is None)
+ ):
+ output += char
+ elif replacement is not None and (
+ status == "M" or (status == "3" and not std3_rules) or (status == "D" and transitional)
+ ):
+ output += replacement
+ elif status != "I":
+ raise IndexError()
+ except IndexError:
+ raise InvalidCodepoint(
+ "Codepoint {} not allowed at position {} in {}".format(_unot(code_point), pos + 1, repr(domain))
+ )
+
+ return unicodedata.normalize("NFC", output)
+
+
+def encode(
+ s: Union[str, bytes, bytearray],
+ strict: bool = False,
+ uts46: bool = False,
+ std3_rules: bool = False,
+ transitional: bool = False,
+) -> bytes:
+ if not isinstance(s, str):
+ try:
+ s = str(s, "ascii")
+ except UnicodeDecodeError:
+ raise IDNAError("should pass a unicode string to the function rather than a byte string.")
+ if uts46:
+ s = uts46_remap(s, std3_rules, transitional)
+ trailing_dot = False
+ result = []
+ if strict:
+ labels = s.split(".")
+ else:
+ labels = _unicode_dots_re.split(s)
+ if not labels or labels == [""]:
+ raise IDNAError("Empty domain")
+ if labels[-1] == "":
+ del labels[-1]
+ trailing_dot = True
+ for label in labels:
+ s = alabel(label)
+ if s:
+ result.append(s)
+ else:
+ raise IDNAError("Empty label")
+ if trailing_dot:
+ result.append(b"")
+ s = b".".join(result)
+ if not valid_string_length(s, trailing_dot):
+ raise IDNAError("Domain too long")
+ return s
+
+
+def decode(
+ s: Union[str, bytes, bytearray],
+ strict: bool = False,
+ uts46: bool = False,
+ std3_rules: bool = False,
+) -> str:
+ try:
+ if not isinstance(s, str):
+ s = str(s, "ascii")
+ except UnicodeDecodeError:
+ raise IDNAError("Invalid ASCII in A-label")
+ if uts46:
+ s = uts46_remap(s, std3_rules, False)
+ trailing_dot = False
+ result = []
+ if not strict:
+ labels = _unicode_dots_re.split(s)
+ else:
+ labels = s.split(".")
+ if not labels or labels == [""]:
+ raise IDNAError("Empty domain")
+ if not labels[-1]:
+ del labels[-1]
+ trailing_dot = True
+ for label in labels:
+ s = ulabel(label)
+ if s:
+ result.append(s)
+ else:
+ raise IDNAError("Empty label")
+ if trailing_dot:
+ result.append("")
+ return ".".join(result)
diff --git a/testcline/lib/python3.12/site-packages/idna/idnadata.py b/testcline/lib/python3.12/site-packages/idna/idnadata.py
new file mode 100644
index 0000000..4be6004
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna/idnadata.py
@@ -0,0 +1,4243 @@
+# This file is automatically generated by tools/idna-data
+
+__version__ = "15.1.0"
+scripts = {
+ "Greek": (
+ 0x37000000374,
+ 0x37500000378,
+ 0x37A0000037E,
+ 0x37F00000380,
+ 0x38400000385,
+ 0x38600000387,
+ 0x3880000038B,
+ 0x38C0000038D,
+ 0x38E000003A2,
+ 0x3A3000003E2,
+ 0x3F000000400,
+ 0x1D2600001D2B,
+ 0x1D5D00001D62,
+ 0x1D6600001D6B,
+ 0x1DBF00001DC0,
+ 0x1F0000001F16,
+ 0x1F1800001F1E,
+ 0x1F2000001F46,
+ 0x1F4800001F4E,
+ 0x1F5000001F58,
+ 0x1F5900001F5A,
+ 0x1F5B00001F5C,
+ 0x1F5D00001F5E,
+ 0x1F5F00001F7E,
+ 0x1F8000001FB5,
+ 0x1FB600001FC5,
+ 0x1FC600001FD4,
+ 0x1FD600001FDC,
+ 0x1FDD00001FF0,
+ 0x1FF200001FF5,
+ 0x1FF600001FFF,
+ 0x212600002127,
+ 0xAB650000AB66,
+ 0x101400001018F,
+ 0x101A0000101A1,
+ 0x1D2000001D246,
+ ),
+ "Han": (
+ 0x2E8000002E9A,
+ 0x2E9B00002EF4,
+ 0x2F0000002FD6,
+ 0x300500003006,
+ 0x300700003008,
+ 0x30210000302A,
+ 0x30380000303C,
+ 0x340000004DC0,
+ 0x4E000000A000,
+ 0xF9000000FA6E,
+ 0xFA700000FADA,
+ 0x16FE200016FE4,
+ 0x16FF000016FF2,
+ 0x200000002A6E0,
+ 0x2A7000002B73A,
+ 0x2B7400002B81E,
+ 0x2B8200002CEA2,
+ 0x2CEB00002EBE1,
+ 0x2EBF00002EE5E,
+ 0x2F8000002FA1E,
+ 0x300000003134B,
+ 0x31350000323B0,
+ ),
+ "Hebrew": (
+ 0x591000005C8,
+ 0x5D0000005EB,
+ 0x5EF000005F5,
+ 0xFB1D0000FB37,
+ 0xFB380000FB3D,
+ 0xFB3E0000FB3F,
+ 0xFB400000FB42,
+ 0xFB430000FB45,
+ 0xFB460000FB50,
+ ),
+ "Hiragana": (
+ 0x304100003097,
+ 0x309D000030A0,
+ 0x1B0010001B120,
+ 0x1B1320001B133,
+ 0x1B1500001B153,
+ 0x1F2000001F201,
+ ),
+ "Katakana": (
+ 0x30A1000030FB,
+ 0x30FD00003100,
+ 0x31F000003200,
+ 0x32D0000032FF,
+ 0x330000003358,
+ 0xFF660000FF70,
+ 0xFF710000FF9E,
+ 0x1AFF00001AFF4,
+ 0x1AFF50001AFFC,
+ 0x1AFFD0001AFFF,
+ 0x1B0000001B001,
+ 0x1B1200001B123,
+ 0x1B1550001B156,
+ 0x1B1640001B168,
+ ),
+}
+joining_types = {
+ 0xAD: 84,
+ 0x300: 84,
+ 0x301: 84,
+ 0x302: 84,
+ 0x303: 84,
+ 0x304: 84,
+ 0x305: 84,
+ 0x306: 84,
+ 0x307: 84,
+ 0x308: 84,
+ 0x309: 84,
+ 0x30A: 84,
+ 0x30B: 84,
+ 0x30C: 84,
+ 0x30D: 84,
+ 0x30E: 84,
+ 0x30F: 84,
+ 0x310: 84,
+ 0x311: 84,
+ 0x312: 84,
+ 0x313: 84,
+ 0x314: 84,
+ 0x315: 84,
+ 0x316: 84,
+ 0x317: 84,
+ 0x318: 84,
+ 0x319: 84,
+ 0x31A: 84,
+ 0x31B: 84,
+ 0x31C: 84,
+ 0x31D: 84,
+ 0x31E: 84,
+ 0x31F: 84,
+ 0x320: 84,
+ 0x321: 84,
+ 0x322: 84,
+ 0x323: 84,
+ 0x324: 84,
+ 0x325: 84,
+ 0x326: 84,
+ 0x327: 84,
+ 0x328: 84,
+ 0x329: 84,
+ 0x32A: 84,
+ 0x32B: 84,
+ 0x32C: 84,
+ 0x32D: 84,
+ 0x32E: 84,
+ 0x32F: 84,
+ 0x330: 84,
+ 0x331: 84,
+ 0x332: 84,
+ 0x333: 84,
+ 0x334: 84,
+ 0x335: 84,
+ 0x336: 84,
+ 0x337: 84,
+ 0x338: 84,
+ 0x339: 84,
+ 0x33A: 84,
+ 0x33B: 84,
+ 0x33C: 84,
+ 0x33D: 84,
+ 0x33E: 84,
+ 0x33F: 84,
+ 0x340: 84,
+ 0x341: 84,
+ 0x342: 84,
+ 0x343: 84,
+ 0x344: 84,
+ 0x345: 84,
+ 0x346: 84,
+ 0x347: 84,
+ 0x348: 84,
+ 0x349: 84,
+ 0x34A: 84,
+ 0x34B: 84,
+ 0x34C: 84,
+ 0x34D: 84,
+ 0x34E: 84,
+ 0x34F: 84,
+ 0x350: 84,
+ 0x351: 84,
+ 0x352: 84,
+ 0x353: 84,
+ 0x354: 84,
+ 0x355: 84,
+ 0x356: 84,
+ 0x357: 84,
+ 0x358: 84,
+ 0x359: 84,
+ 0x35A: 84,
+ 0x35B: 84,
+ 0x35C: 84,
+ 0x35D: 84,
+ 0x35E: 84,
+ 0x35F: 84,
+ 0x360: 84,
+ 0x361: 84,
+ 0x362: 84,
+ 0x363: 84,
+ 0x364: 84,
+ 0x365: 84,
+ 0x366: 84,
+ 0x367: 84,
+ 0x368: 84,
+ 0x369: 84,
+ 0x36A: 84,
+ 0x36B: 84,
+ 0x36C: 84,
+ 0x36D: 84,
+ 0x36E: 84,
+ 0x36F: 84,
+ 0x483: 84,
+ 0x484: 84,
+ 0x485: 84,
+ 0x486: 84,
+ 0x487: 84,
+ 0x488: 84,
+ 0x489: 84,
+ 0x591: 84,
+ 0x592: 84,
+ 0x593: 84,
+ 0x594: 84,
+ 0x595: 84,
+ 0x596: 84,
+ 0x597: 84,
+ 0x598: 84,
+ 0x599: 84,
+ 0x59A: 84,
+ 0x59B: 84,
+ 0x59C: 84,
+ 0x59D: 84,
+ 0x59E: 84,
+ 0x59F: 84,
+ 0x5A0: 84,
+ 0x5A1: 84,
+ 0x5A2: 84,
+ 0x5A3: 84,
+ 0x5A4: 84,
+ 0x5A5: 84,
+ 0x5A6: 84,
+ 0x5A7: 84,
+ 0x5A8: 84,
+ 0x5A9: 84,
+ 0x5AA: 84,
+ 0x5AB: 84,
+ 0x5AC: 84,
+ 0x5AD: 84,
+ 0x5AE: 84,
+ 0x5AF: 84,
+ 0x5B0: 84,
+ 0x5B1: 84,
+ 0x5B2: 84,
+ 0x5B3: 84,
+ 0x5B4: 84,
+ 0x5B5: 84,
+ 0x5B6: 84,
+ 0x5B7: 84,
+ 0x5B8: 84,
+ 0x5B9: 84,
+ 0x5BA: 84,
+ 0x5BB: 84,
+ 0x5BC: 84,
+ 0x5BD: 84,
+ 0x5BF: 84,
+ 0x5C1: 84,
+ 0x5C2: 84,
+ 0x5C4: 84,
+ 0x5C5: 84,
+ 0x5C7: 84,
+ 0x610: 84,
+ 0x611: 84,
+ 0x612: 84,
+ 0x613: 84,
+ 0x614: 84,
+ 0x615: 84,
+ 0x616: 84,
+ 0x617: 84,
+ 0x618: 84,
+ 0x619: 84,
+ 0x61A: 84,
+ 0x61C: 84,
+ 0x620: 68,
+ 0x622: 82,
+ 0x623: 82,
+ 0x624: 82,
+ 0x625: 82,
+ 0x626: 68,
+ 0x627: 82,
+ 0x628: 68,
+ 0x629: 82,
+ 0x62A: 68,
+ 0x62B: 68,
+ 0x62C: 68,
+ 0x62D: 68,
+ 0x62E: 68,
+ 0x62F: 82,
+ 0x630: 82,
+ 0x631: 82,
+ 0x632: 82,
+ 0x633: 68,
+ 0x634: 68,
+ 0x635: 68,
+ 0x636: 68,
+ 0x637: 68,
+ 0x638: 68,
+ 0x639: 68,
+ 0x63A: 68,
+ 0x63B: 68,
+ 0x63C: 68,
+ 0x63D: 68,
+ 0x63E: 68,
+ 0x63F: 68,
+ 0x640: 67,
+ 0x641: 68,
+ 0x642: 68,
+ 0x643: 68,
+ 0x644: 68,
+ 0x645: 68,
+ 0x646: 68,
+ 0x647: 68,
+ 0x648: 82,
+ 0x649: 68,
+ 0x64A: 68,
+ 0x64B: 84,
+ 0x64C: 84,
+ 0x64D: 84,
+ 0x64E: 84,
+ 0x64F: 84,
+ 0x650: 84,
+ 0x651: 84,
+ 0x652: 84,
+ 0x653: 84,
+ 0x654: 84,
+ 0x655: 84,
+ 0x656: 84,
+ 0x657: 84,
+ 0x658: 84,
+ 0x659: 84,
+ 0x65A: 84,
+ 0x65B: 84,
+ 0x65C: 84,
+ 0x65D: 84,
+ 0x65E: 84,
+ 0x65F: 84,
+ 0x66E: 68,
+ 0x66F: 68,
+ 0x670: 84,
+ 0x671: 82,
+ 0x672: 82,
+ 0x673: 82,
+ 0x675: 82,
+ 0x676: 82,
+ 0x677: 82,
+ 0x678: 68,
+ 0x679: 68,
+ 0x67A: 68,
+ 0x67B: 68,
+ 0x67C: 68,
+ 0x67D: 68,
+ 0x67E: 68,
+ 0x67F: 68,
+ 0x680: 68,
+ 0x681: 68,
+ 0x682: 68,
+ 0x683: 68,
+ 0x684: 68,
+ 0x685: 68,
+ 0x686: 68,
+ 0x687: 68,
+ 0x688: 82,
+ 0x689: 82,
+ 0x68A: 82,
+ 0x68B: 82,
+ 0x68C: 82,
+ 0x68D: 82,
+ 0x68E: 82,
+ 0x68F: 82,
+ 0x690: 82,
+ 0x691: 82,
+ 0x692: 82,
+ 0x693: 82,
+ 0x694: 82,
+ 0x695: 82,
+ 0x696: 82,
+ 0x697: 82,
+ 0x698: 82,
+ 0x699: 82,
+ 0x69A: 68,
+ 0x69B: 68,
+ 0x69C: 68,
+ 0x69D: 68,
+ 0x69E: 68,
+ 0x69F: 68,
+ 0x6A0: 68,
+ 0x6A1: 68,
+ 0x6A2: 68,
+ 0x6A3: 68,
+ 0x6A4: 68,
+ 0x6A5: 68,
+ 0x6A6: 68,
+ 0x6A7: 68,
+ 0x6A8: 68,
+ 0x6A9: 68,
+ 0x6AA: 68,
+ 0x6AB: 68,
+ 0x6AC: 68,
+ 0x6AD: 68,
+ 0x6AE: 68,
+ 0x6AF: 68,
+ 0x6B0: 68,
+ 0x6B1: 68,
+ 0x6B2: 68,
+ 0x6B3: 68,
+ 0x6B4: 68,
+ 0x6B5: 68,
+ 0x6B6: 68,
+ 0x6B7: 68,
+ 0x6B8: 68,
+ 0x6B9: 68,
+ 0x6BA: 68,
+ 0x6BB: 68,
+ 0x6BC: 68,
+ 0x6BD: 68,
+ 0x6BE: 68,
+ 0x6BF: 68,
+ 0x6C0: 82,
+ 0x6C1: 68,
+ 0x6C2: 68,
+ 0x6C3: 82,
+ 0x6C4: 82,
+ 0x6C5: 82,
+ 0x6C6: 82,
+ 0x6C7: 82,
+ 0x6C8: 82,
+ 0x6C9: 82,
+ 0x6CA: 82,
+ 0x6CB: 82,
+ 0x6CC: 68,
+ 0x6CD: 82,
+ 0x6CE: 68,
+ 0x6CF: 82,
+ 0x6D0: 68,
+ 0x6D1: 68,
+ 0x6D2: 82,
+ 0x6D3: 82,
+ 0x6D5: 82,
+ 0x6D6: 84,
+ 0x6D7: 84,
+ 0x6D8: 84,
+ 0x6D9: 84,
+ 0x6DA: 84,
+ 0x6DB: 84,
+ 0x6DC: 84,
+ 0x6DF: 84,
+ 0x6E0: 84,
+ 0x6E1: 84,
+ 0x6E2: 84,
+ 0x6E3: 84,
+ 0x6E4: 84,
+ 0x6E7: 84,
+ 0x6E8: 84,
+ 0x6EA: 84,
+ 0x6EB: 84,
+ 0x6EC: 84,
+ 0x6ED: 84,
+ 0x6EE: 82,
+ 0x6EF: 82,
+ 0x6FA: 68,
+ 0x6FB: 68,
+ 0x6FC: 68,
+ 0x6FF: 68,
+ 0x70F: 84,
+ 0x710: 82,
+ 0x711: 84,
+ 0x712: 68,
+ 0x713: 68,
+ 0x714: 68,
+ 0x715: 82,
+ 0x716: 82,
+ 0x717: 82,
+ 0x718: 82,
+ 0x719: 82,
+ 0x71A: 68,
+ 0x71B: 68,
+ 0x71C: 68,
+ 0x71D: 68,
+ 0x71E: 82,
+ 0x71F: 68,
+ 0x720: 68,
+ 0x721: 68,
+ 0x722: 68,
+ 0x723: 68,
+ 0x724: 68,
+ 0x725: 68,
+ 0x726: 68,
+ 0x727: 68,
+ 0x728: 82,
+ 0x729: 68,
+ 0x72A: 82,
+ 0x72B: 68,
+ 0x72C: 82,
+ 0x72D: 68,
+ 0x72E: 68,
+ 0x72F: 82,
+ 0x730: 84,
+ 0x731: 84,
+ 0x732: 84,
+ 0x733: 84,
+ 0x734: 84,
+ 0x735: 84,
+ 0x736: 84,
+ 0x737: 84,
+ 0x738: 84,
+ 0x739: 84,
+ 0x73A: 84,
+ 0x73B: 84,
+ 0x73C: 84,
+ 0x73D: 84,
+ 0x73E: 84,
+ 0x73F: 84,
+ 0x740: 84,
+ 0x741: 84,
+ 0x742: 84,
+ 0x743: 84,
+ 0x744: 84,
+ 0x745: 84,
+ 0x746: 84,
+ 0x747: 84,
+ 0x748: 84,
+ 0x749: 84,
+ 0x74A: 84,
+ 0x74D: 82,
+ 0x74E: 68,
+ 0x74F: 68,
+ 0x750: 68,
+ 0x751: 68,
+ 0x752: 68,
+ 0x753: 68,
+ 0x754: 68,
+ 0x755: 68,
+ 0x756: 68,
+ 0x757: 68,
+ 0x758: 68,
+ 0x759: 82,
+ 0x75A: 82,
+ 0x75B: 82,
+ 0x75C: 68,
+ 0x75D: 68,
+ 0x75E: 68,
+ 0x75F: 68,
+ 0x760: 68,
+ 0x761: 68,
+ 0x762: 68,
+ 0x763: 68,
+ 0x764: 68,
+ 0x765: 68,
+ 0x766: 68,
+ 0x767: 68,
+ 0x768: 68,
+ 0x769: 68,
+ 0x76A: 68,
+ 0x76B: 82,
+ 0x76C: 82,
+ 0x76D: 68,
+ 0x76E: 68,
+ 0x76F: 68,
+ 0x770: 68,
+ 0x771: 82,
+ 0x772: 68,
+ 0x773: 82,
+ 0x774: 82,
+ 0x775: 68,
+ 0x776: 68,
+ 0x777: 68,
+ 0x778: 82,
+ 0x779: 82,
+ 0x77A: 68,
+ 0x77B: 68,
+ 0x77C: 68,
+ 0x77D: 68,
+ 0x77E: 68,
+ 0x77F: 68,
+ 0x7A6: 84,
+ 0x7A7: 84,
+ 0x7A8: 84,
+ 0x7A9: 84,
+ 0x7AA: 84,
+ 0x7AB: 84,
+ 0x7AC: 84,
+ 0x7AD: 84,
+ 0x7AE: 84,
+ 0x7AF: 84,
+ 0x7B0: 84,
+ 0x7CA: 68,
+ 0x7CB: 68,
+ 0x7CC: 68,
+ 0x7CD: 68,
+ 0x7CE: 68,
+ 0x7CF: 68,
+ 0x7D0: 68,
+ 0x7D1: 68,
+ 0x7D2: 68,
+ 0x7D3: 68,
+ 0x7D4: 68,
+ 0x7D5: 68,
+ 0x7D6: 68,
+ 0x7D7: 68,
+ 0x7D8: 68,
+ 0x7D9: 68,
+ 0x7DA: 68,
+ 0x7DB: 68,
+ 0x7DC: 68,
+ 0x7DD: 68,
+ 0x7DE: 68,
+ 0x7DF: 68,
+ 0x7E0: 68,
+ 0x7E1: 68,
+ 0x7E2: 68,
+ 0x7E3: 68,
+ 0x7E4: 68,
+ 0x7E5: 68,
+ 0x7E6: 68,
+ 0x7E7: 68,
+ 0x7E8: 68,
+ 0x7E9: 68,
+ 0x7EA: 68,
+ 0x7EB: 84,
+ 0x7EC: 84,
+ 0x7ED: 84,
+ 0x7EE: 84,
+ 0x7EF: 84,
+ 0x7F0: 84,
+ 0x7F1: 84,
+ 0x7F2: 84,
+ 0x7F3: 84,
+ 0x7FA: 67,
+ 0x7FD: 84,
+ 0x816: 84,
+ 0x817: 84,
+ 0x818: 84,
+ 0x819: 84,
+ 0x81B: 84,
+ 0x81C: 84,
+ 0x81D: 84,
+ 0x81E: 84,
+ 0x81F: 84,
+ 0x820: 84,
+ 0x821: 84,
+ 0x822: 84,
+ 0x823: 84,
+ 0x825: 84,
+ 0x826: 84,
+ 0x827: 84,
+ 0x829: 84,
+ 0x82A: 84,
+ 0x82B: 84,
+ 0x82C: 84,
+ 0x82D: 84,
+ 0x840: 82,
+ 0x841: 68,
+ 0x842: 68,
+ 0x843: 68,
+ 0x844: 68,
+ 0x845: 68,
+ 0x846: 82,
+ 0x847: 82,
+ 0x848: 68,
+ 0x849: 82,
+ 0x84A: 68,
+ 0x84B: 68,
+ 0x84C: 68,
+ 0x84D: 68,
+ 0x84E: 68,
+ 0x84F: 68,
+ 0x850: 68,
+ 0x851: 68,
+ 0x852: 68,
+ 0x853: 68,
+ 0x854: 82,
+ 0x855: 68,
+ 0x856: 82,
+ 0x857: 82,
+ 0x858: 82,
+ 0x859: 84,
+ 0x85A: 84,
+ 0x85B: 84,
+ 0x860: 68,
+ 0x862: 68,
+ 0x863: 68,
+ 0x864: 68,
+ 0x865: 68,
+ 0x867: 82,
+ 0x868: 68,
+ 0x869: 82,
+ 0x86A: 82,
+ 0x870: 82,
+ 0x871: 82,
+ 0x872: 82,
+ 0x873: 82,
+ 0x874: 82,
+ 0x875: 82,
+ 0x876: 82,
+ 0x877: 82,
+ 0x878: 82,
+ 0x879: 82,
+ 0x87A: 82,
+ 0x87B: 82,
+ 0x87C: 82,
+ 0x87D: 82,
+ 0x87E: 82,
+ 0x87F: 82,
+ 0x880: 82,
+ 0x881: 82,
+ 0x882: 82,
+ 0x883: 67,
+ 0x884: 67,
+ 0x885: 67,
+ 0x886: 68,
+ 0x889: 68,
+ 0x88A: 68,
+ 0x88B: 68,
+ 0x88C: 68,
+ 0x88D: 68,
+ 0x88E: 82,
+ 0x898: 84,
+ 0x899: 84,
+ 0x89A: 84,
+ 0x89B: 84,
+ 0x89C: 84,
+ 0x89D: 84,
+ 0x89E: 84,
+ 0x89F: 84,
+ 0x8A0: 68,
+ 0x8A1: 68,
+ 0x8A2: 68,
+ 0x8A3: 68,
+ 0x8A4: 68,
+ 0x8A5: 68,
+ 0x8A6: 68,
+ 0x8A7: 68,
+ 0x8A8: 68,
+ 0x8A9: 68,
+ 0x8AA: 82,
+ 0x8AB: 82,
+ 0x8AC: 82,
+ 0x8AE: 82,
+ 0x8AF: 68,
+ 0x8B0: 68,
+ 0x8B1: 82,
+ 0x8B2: 82,
+ 0x8B3: 68,
+ 0x8B4: 68,
+ 0x8B5: 68,
+ 0x8B6: 68,
+ 0x8B7: 68,
+ 0x8B8: 68,
+ 0x8B9: 82,
+ 0x8BA: 68,
+ 0x8BB: 68,
+ 0x8BC: 68,
+ 0x8BD: 68,
+ 0x8BE: 68,
+ 0x8BF: 68,
+ 0x8C0: 68,
+ 0x8C1: 68,
+ 0x8C2: 68,
+ 0x8C3: 68,
+ 0x8C4: 68,
+ 0x8C5: 68,
+ 0x8C6: 68,
+ 0x8C7: 68,
+ 0x8C8: 68,
+ 0x8CA: 84,
+ 0x8CB: 84,
+ 0x8CC: 84,
+ 0x8CD: 84,
+ 0x8CE: 84,
+ 0x8CF: 84,
+ 0x8D0: 84,
+ 0x8D1: 84,
+ 0x8D2: 84,
+ 0x8D3: 84,
+ 0x8D4: 84,
+ 0x8D5: 84,
+ 0x8D6: 84,
+ 0x8D7: 84,
+ 0x8D8: 84,
+ 0x8D9: 84,
+ 0x8DA: 84,
+ 0x8DB: 84,
+ 0x8DC: 84,
+ 0x8DD: 84,
+ 0x8DE: 84,
+ 0x8DF: 84,
+ 0x8E0: 84,
+ 0x8E1: 84,
+ 0x8E3: 84,
+ 0x8E4: 84,
+ 0x8E5: 84,
+ 0x8E6: 84,
+ 0x8E7: 84,
+ 0x8E8: 84,
+ 0x8E9: 84,
+ 0x8EA: 84,
+ 0x8EB: 84,
+ 0x8EC: 84,
+ 0x8ED: 84,
+ 0x8EE: 84,
+ 0x8EF: 84,
+ 0x8F0: 84,
+ 0x8F1: 84,
+ 0x8F2: 84,
+ 0x8F3: 84,
+ 0x8F4: 84,
+ 0x8F5: 84,
+ 0x8F6: 84,
+ 0x8F7: 84,
+ 0x8F8: 84,
+ 0x8F9: 84,
+ 0x8FA: 84,
+ 0x8FB: 84,
+ 0x8FC: 84,
+ 0x8FD: 84,
+ 0x8FE: 84,
+ 0x8FF: 84,
+ 0x900: 84,
+ 0x901: 84,
+ 0x902: 84,
+ 0x93A: 84,
+ 0x93C: 84,
+ 0x941: 84,
+ 0x942: 84,
+ 0x943: 84,
+ 0x944: 84,
+ 0x945: 84,
+ 0x946: 84,
+ 0x947: 84,
+ 0x948: 84,
+ 0x94D: 84,
+ 0x951: 84,
+ 0x952: 84,
+ 0x953: 84,
+ 0x954: 84,
+ 0x955: 84,
+ 0x956: 84,
+ 0x957: 84,
+ 0x962: 84,
+ 0x963: 84,
+ 0x981: 84,
+ 0x9BC: 84,
+ 0x9C1: 84,
+ 0x9C2: 84,
+ 0x9C3: 84,
+ 0x9C4: 84,
+ 0x9CD: 84,
+ 0x9E2: 84,
+ 0x9E3: 84,
+ 0x9FE: 84,
+ 0xA01: 84,
+ 0xA02: 84,
+ 0xA3C: 84,
+ 0xA41: 84,
+ 0xA42: 84,
+ 0xA47: 84,
+ 0xA48: 84,
+ 0xA4B: 84,
+ 0xA4C: 84,
+ 0xA4D: 84,
+ 0xA51: 84,
+ 0xA70: 84,
+ 0xA71: 84,
+ 0xA75: 84,
+ 0xA81: 84,
+ 0xA82: 84,
+ 0xABC: 84,
+ 0xAC1: 84,
+ 0xAC2: 84,
+ 0xAC3: 84,
+ 0xAC4: 84,
+ 0xAC5: 84,
+ 0xAC7: 84,
+ 0xAC8: 84,
+ 0xACD: 84,
+ 0xAE2: 84,
+ 0xAE3: 84,
+ 0xAFA: 84,
+ 0xAFB: 84,
+ 0xAFC: 84,
+ 0xAFD: 84,
+ 0xAFE: 84,
+ 0xAFF: 84,
+ 0xB01: 84,
+ 0xB3C: 84,
+ 0xB3F: 84,
+ 0xB41: 84,
+ 0xB42: 84,
+ 0xB43: 84,
+ 0xB44: 84,
+ 0xB4D: 84,
+ 0xB55: 84,
+ 0xB56: 84,
+ 0xB62: 84,
+ 0xB63: 84,
+ 0xB82: 84,
+ 0xBC0: 84,
+ 0xBCD: 84,
+ 0xC00: 84,
+ 0xC04: 84,
+ 0xC3C: 84,
+ 0xC3E: 84,
+ 0xC3F: 84,
+ 0xC40: 84,
+ 0xC46: 84,
+ 0xC47: 84,
+ 0xC48: 84,
+ 0xC4A: 84,
+ 0xC4B: 84,
+ 0xC4C: 84,
+ 0xC4D: 84,
+ 0xC55: 84,
+ 0xC56: 84,
+ 0xC62: 84,
+ 0xC63: 84,
+ 0xC81: 84,
+ 0xCBC: 84,
+ 0xCBF: 84,
+ 0xCC6: 84,
+ 0xCCC: 84,
+ 0xCCD: 84,
+ 0xCE2: 84,
+ 0xCE3: 84,
+ 0xD00: 84,
+ 0xD01: 84,
+ 0xD3B: 84,
+ 0xD3C: 84,
+ 0xD41: 84,
+ 0xD42: 84,
+ 0xD43: 84,
+ 0xD44: 84,
+ 0xD4D: 84,
+ 0xD62: 84,
+ 0xD63: 84,
+ 0xD81: 84,
+ 0xDCA: 84,
+ 0xDD2: 84,
+ 0xDD3: 84,
+ 0xDD4: 84,
+ 0xDD6: 84,
+ 0xE31: 84,
+ 0xE34: 84,
+ 0xE35: 84,
+ 0xE36: 84,
+ 0xE37: 84,
+ 0xE38: 84,
+ 0xE39: 84,
+ 0xE3A: 84,
+ 0xE47: 84,
+ 0xE48: 84,
+ 0xE49: 84,
+ 0xE4A: 84,
+ 0xE4B: 84,
+ 0xE4C: 84,
+ 0xE4D: 84,
+ 0xE4E: 84,
+ 0xEB1: 84,
+ 0xEB4: 84,
+ 0xEB5: 84,
+ 0xEB6: 84,
+ 0xEB7: 84,
+ 0xEB8: 84,
+ 0xEB9: 84,
+ 0xEBA: 84,
+ 0xEBB: 84,
+ 0xEBC: 84,
+ 0xEC8: 84,
+ 0xEC9: 84,
+ 0xECA: 84,
+ 0xECB: 84,
+ 0xECC: 84,
+ 0xECD: 84,
+ 0xECE: 84,
+ 0xF18: 84,
+ 0xF19: 84,
+ 0xF35: 84,
+ 0xF37: 84,
+ 0xF39: 84,
+ 0xF71: 84,
+ 0xF72: 84,
+ 0xF73: 84,
+ 0xF74: 84,
+ 0xF75: 84,
+ 0xF76: 84,
+ 0xF77: 84,
+ 0xF78: 84,
+ 0xF79: 84,
+ 0xF7A: 84,
+ 0xF7B: 84,
+ 0xF7C: 84,
+ 0xF7D: 84,
+ 0xF7E: 84,
+ 0xF80: 84,
+ 0xF81: 84,
+ 0xF82: 84,
+ 0xF83: 84,
+ 0xF84: 84,
+ 0xF86: 84,
+ 0xF87: 84,
+ 0xF8D: 84,
+ 0xF8E: 84,
+ 0xF8F: 84,
+ 0xF90: 84,
+ 0xF91: 84,
+ 0xF92: 84,
+ 0xF93: 84,
+ 0xF94: 84,
+ 0xF95: 84,
+ 0xF96: 84,
+ 0xF97: 84,
+ 0xF99: 84,
+ 0xF9A: 84,
+ 0xF9B: 84,
+ 0xF9C: 84,
+ 0xF9D: 84,
+ 0xF9E: 84,
+ 0xF9F: 84,
+ 0xFA0: 84,
+ 0xFA1: 84,
+ 0xFA2: 84,
+ 0xFA3: 84,
+ 0xFA4: 84,
+ 0xFA5: 84,
+ 0xFA6: 84,
+ 0xFA7: 84,
+ 0xFA8: 84,
+ 0xFA9: 84,
+ 0xFAA: 84,
+ 0xFAB: 84,
+ 0xFAC: 84,
+ 0xFAD: 84,
+ 0xFAE: 84,
+ 0xFAF: 84,
+ 0xFB0: 84,
+ 0xFB1: 84,
+ 0xFB2: 84,
+ 0xFB3: 84,
+ 0xFB4: 84,
+ 0xFB5: 84,
+ 0xFB6: 84,
+ 0xFB7: 84,
+ 0xFB8: 84,
+ 0xFB9: 84,
+ 0xFBA: 84,
+ 0xFBB: 84,
+ 0xFBC: 84,
+ 0xFC6: 84,
+ 0x102D: 84,
+ 0x102E: 84,
+ 0x102F: 84,
+ 0x1030: 84,
+ 0x1032: 84,
+ 0x1033: 84,
+ 0x1034: 84,
+ 0x1035: 84,
+ 0x1036: 84,
+ 0x1037: 84,
+ 0x1039: 84,
+ 0x103A: 84,
+ 0x103D: 84,
+ 0x103E: 84,
+ 0x1058: 84,
+ 0x1059: 84,
+ 0x105E: 84,
+ 0x105F: 84,
+ 0x1060: 84,
+ 0x1071: 84,
+ 0x1072: 84,
+ 0x1073: 84,
+ 0x1074: 84,
+ 0x1082: 84,
+ 0x1085: 84,
+ 0x1086: 84,
+ 0x108D: 84,
+ 0x109D: 84,
+ 0x135D: 84,
+ 0x135E: 84,
+ 0x135F: 84,
+ 0x1712: 84,
+ 0x1713: 84,
+ 0x1714: 84,
+ 0x1732: 84,
+ 0x1733: 84,
+ 0x1752: 84,
+ 0x1753: 84,
+ 0x1772: 84,
+ 0x1773: 84,
+ 0x17B4: 84,
+ 0x17B5: 84,
+ 0x17B7: 84,
+ 0x17B8: 84,
+ 0x17B9: 84,
+ 0x17BA: 84,
+ 0x17BB: 84,
+ 0x17BC: 84,
+ 0x17BD: 84,
+ 0x17C6: 84,
+ 0x17C9: 84,
+ 0x17CA: 84,
+ 0x17CB: 84,
+ 0x17CC: 84,
+ 0x17CD: 84,
+ 0x17CE: 84,
+ 0x17CF: 84,
+ 0x17D0: 84,
+ 0x17D1: 84,
+ 0x17D2: 84,
+ 0x17D3: 84,
+ 0x17DD: 84,
+ 0x1807: 68,
+ 0x180A: 67,
+ 0x180B: 84,
+ 0x180C: 84,
+ 0x180D: 84,
+ 0x180F: 84,
+ 0x1820: 68,
+ 0x1821: 68,
+ 0x1822: 68,
+ 0x1823: 68,
+ 0x1824: 68,
+ 0x1825: 68,
+ 0x1826: 68,
+ 0x1827: 68,
+ 0x1828: 68,
+ 0x1829: 68,
+ 0x182A: 68,
+ 0x182B: 68,
+ 0x182C: 68,
+ 0x182D: 68,
+ 0x182E: 68,
+ 0x182F: 68,
+ 0x1830: 68,
+ 0x1831: 68,
+ 0x1832: 68,
+ 0x1833: 68,
+ 0x1834: 68,
+ 0x1835: 68,
+ 0x1836: 68,
+ 0x1837: 68,
+ 0x1838: 68,
+ 0x1839: 68,
+ 0x183A: 68,
+ 0x183B: 68,
+ 0x183C: 68,
+ 0x183D: 68,
+ 0x183E: 68,
+ 0x183F: 68,
+ 0x1840: 68,
+ 0x1841: 68,
+ 0x1842: 68,
+ 0x1843: 68,
+ 0x1844: 68,
+ 0x1845: 68,
+ 0x1846: 68,
+ 0x1847: 68,
+ 0x1848: 68,
+ 0x1849: 68,
+ 0x184A: 68,
+ 0x184B: 68,
+ 0x184C: 68,
+ 0x184D: 68,
+ 0x184E: 68,
+ 0x184F: 68,
+ 0x1850: 68,
+ 0x1851: 68,
+ 0x1852: 68,
+ 0x1853: 68,
+ 0x1854: 68,
+ 0x1855: 68,
+ 0x1856: 68,
+ 0x1857: 68,
+ 0x1858: 68,
+ 0x1859: 68,
+ 0x185A: 68,
+ 0x185B: 68,
+ 0x185C: 68,
+ 0x185D: 68,
+ 0x185E: 68,
+ 0x185F: 68,
+ 0x1860: 68,
+ 0x1861: 68,
+ 0x1862: 68,
+ 0x1863: 68,
+ 0x1864: 68,
+ 0x1865: 68,
+ 0x1866: 68,
+ 0x1867: 68,
+ 0x1868: 68,
+ 0x1869: 68,
+ 0x186A: 68,
+ 0x186B: 68,
+ 0x186C: 68,
+ 0x186D: 68,
+ 0x186E: 68,
+ 0x186F: 68,
+ 0x1870: 68,
+ 0x1871: 68,
+ 0x1872: 68,
+ 0x1873: 68,
+ 0x1874: 68,
+ 0x1875: 68,
+ 0x1876: 68,
+ 0x1877: 68,
+ 0x1878: 68,
+ 0x1885: 84,
+ 0x1886: 84,
+ 0x1887: 68,
+ 0x1888: 68,
+ 0x1889: 68,
+ 0x188A: 68,
+ 0x188B: 68,
+ 0x188C: 68,
+ 0x188D: 68,
+ 0x188E: 68,
+ 0x188F: 68,
+ 0x1890: 68,
+ 0x1891: 68,
+ 0x1892: 68,
+ 0x1893: 68,
+ 0x1894: 68,
+ 0x1895: 68,
+ 0x1896: 68,
+ 0x1897: 68,
+ 0x1898: 68,
+ 0x1899: 68,
+ 0x189A: 68,
+ 0x189B: 68,
+ 0x189C: 68,
+ 0x189D: 68,
+ 0x189E: 68,
+ 0x189F: 68,
+ 0x18A0: 68,
+ 0x18A1: 68,
+ 0x18A2: 68,
+ 0x18A3: 68,
+ 0x18A4: 68,
+ 0x18A5: 68,
+ 0x18A6: 68,
+ 0x18A7: 68,
+ 0x18A8: 68,
+ 0x18A9: 84,
+ 0x18AA: 68,
+ 0x1920: 84,
+ 0x1921: 84,
+ 0x1922: 84,
+ 0x1927: 84,
+ 0x1928: 84,
+ 0x1932: 84,
+ 0x1939: 84,
+ 0x193A: 84,
+ 0x193B: 84,
+ 0x1A17: 84,
+ 0x1A18: 84,
+ 0x1A1B: 84,
+ 0x1A56: 84,
+ 0x1A58: 84,
+ 0x1A59: 84,
+ 0x1A5A: 84,
+ 0x1A5B: 84,
+ 0x1A5C: 84,
+ 0x1A5D: 84,
+ 0x1A5E: 84,
+ 0x1A60: 84,
+ 0x1A62: 84,
+ 0x1A65: 84,
+ 0x1A66: 84,
+ 0x1A67: 84,
+ 0x1A68: 84,
+ 0x1A69: 84,
+ 0x1A6A: 84,
+ 0x1A6B: 84,
+ 0x1A6C: 84,
+ 0x1A73: 84,
+ 0x1A74: 84,
+ 0x1A75: 84,
+ 0x1A76: 84,
+ 0x1A77: 84,
+ 0x1A78: 84,
+ 0x1A79: 84,
+ 0x1A7A: 84,
+ 0x1A7B: 84,
+ 0x1A7C: 84,
+ 0x1A7F: 84,
+ 0x1AB0: 84,
+ 0x1AB1: 84,
+ 0x1AB2: 84,
+ 0x1AB3: 84,
+ 0x1AB4: 84,
+ 0x1AB5: 84,
+ 0x1AB6: 84,
+ 0x1AB7: 84,
+ 0x1AB8: 84,
+ 0x1AB9: 84,
+ 0x1ABA: 84,
+ 0x1ABB: 84,
+ 0x1ABC: 84,
+ 0x1ABD: 84,
+ 0x1ABE: 84,
+ 0x1ABF: 84,
+ 0x1AC0: 84,
+ 0x1AC1: 84,
+ 0x1AC2: 84,
+ 0x1AC3: 84,
+ 0x1AC4: 84,
+ 0x1AC5: 84,
+ 0x1AC6: 84,
+ 0x1AC7: 84,
+ 0x1AC8: 84,
+ 0x1AC9: 84,
+ 0x1ACA: 84,
+ 0x1ACB: 84,
+ 0x1ACC: 84,
+ 0x1ACD: 84,
+ 0x1ACE: 84,
+ 0x1B00: 84,
+ 0x1B01: 84,
+ 0x1B02: 84,
+ 0x1B03: 84,
+ 0x1B34: 84,
+ 0x1B36: 84,
+ 0x1B37: 84,
+ 0x1B38: 84,
+ 0x1B39: 84,
+ 0x1B3A: 84,
+ 0x1B3C: 84,
+ 0x1B42: 84,
+ 0x1B6B: 84,
+ 0x1B6C: 84,
+ 0x1B6D: 84,
+ 0x1B6E: 84,
+ 0x1B6F: 84,
+ 0x1B70: 84,
+ 0x1B71: 84,
+ 0x1B72: 84,
+ 0x1B73: 84,
+ 0x1B80: 84,
+ 0x1B81: 84,
+ 0x1BA2: 84,
+ 0x1BA3: 84,
+ 0x1BA4: 84,
+ 0x1BA5: 84,
+ 0x1BA8: 84,
+ 0x1BA9: 84,
+ 0x1BAB: 84,
+ 0x1BAC: 84,
+ 0x1BAD: 84,
+ 0x1BE6: 84,
+ 0x1BE8: 84,
+ 0x1BE9: 84,
+ 0x1BED: 84,
+ 0x1BEF: 84,
+ 0x1BF0: 84,
+ 0x1BF1: 84,
+ 0x1C2C: 84,
+ 0x1C2D: 84,
+ 0x1C2E: 84,
+ 0x1C2F: 84,
+ 0x1C30: 84,
+ 0x1C31: 84,
+ 0x1C32: 84,
+ 0x1C33: 84,
+ 0x1C36: 84,
+ 0x1C37: 84,
+ 0x1CD0: 84,
+ 0x1CD1: 84,
+ 0x1CD2: 84,
+ 0x1CD4: 84,
+ 0x1CD5: 84,
+ 0x1CD6: 84,
+ 0x1CD7: 84,
+ 0x1CD8: 84,
+ 0x1CD9: 84,
+ 0x1CDA: 84,
+ 0x1CDB: 84,
+ 0x1CDC: 84,
+ 0x1CDD: 84,
+ 0x1CDE: 84,
+ 0x1CDF: 84,
+ 0x1CE0: 84,
+ 0x1CE2: 84,
+ 0x1CE3: 84,
+ 0x1CE4: 84,
+ 0x1CE5: 84,
+ 0x1CE6: 84,
+ 0x1CE7: 84,
+ 0x1CE8: 84,
+ 0x1CED: 84,
+ 0x1CF4: 84,
+ 0x1CF8: 84,
+ 0x1CF9: 84,
+ 0x1DC0: 84,
+ 0x1DC1: 84,
+ 0x1DC2: 84,
+ 0x1DC3: 84,
+ 0x1DC4: 84,
+ 0x1DC5: 84,
+ 0x1DC6: 84,
+ 0x1DC7: 84,
+ 0x1DC8: 84,
+ 0x1DC9: 84,
+ 0x1DCA: 84,
+ 0x1DCB: 84,
+ 0x1DCC: 84,
+ 0x1DCD: 84,
+ 0x1DCE: 84,
+ 0x1DCF: 84,
+ 0x1DD0: 84,
+ 0x1DD1: 84,
+ 0x1DD2: 84,
+ 0x1DD3: 84,
+ 0x1DD4: 84,
+ 0x1DD5: 84,
+ 0x1DD6: 84,
+ 0x1DD7: 84,
+ 0x1DD8: 84,
+ 0x1DD9: 84,
+ 0x1DDA: 84,
+ 0x1DDB: 84,
+ 0x1DDC: 84,
+ 0x1DDD: 84,
+ 0x1DDE: 84,
+ 0x1DDF: 84,
+ 0x1DE0: 84,
+ 0x1DE1: 84,
+ 0x1DE2: 84,
+ 0x1DE3: 84,
+ 0x1DE4: 84,
+ 0x1DE5: 84,
+ 0x1DE6: 84,
+ 0x1DE7: 84,
+ 0x1DE8: 84,
+ 0x1DE9: 84,
+ 0x1DEA: 84,
+ 0x1DEB: 84,
+ 0x1DEC: 84,
+ 0x1DED: 84,
+ 0x1DEE: 84,
+ 0x1DEF: 84,
+ 0x1DF0: 84,
+ 0x1DF1: 84,
+ 0x1DF2: 84,
+ 0x1DF3: 84,
+ 0x1DF4: 84,
+ 0x1DF5: 84,
+ 0x1DF6: 84,
+ 0x1DF7: 84,
+ 0x1DF8: 84,
+ 0x1DF9: 84,
+ 0x1DFA: 84,
+ 0x1DFB: 84,
+ 0x1DFC: 84,
+ 0x1DFD: 84,
+ 0x1DFE: 84,
+ 0x1DFF: 84,
+ 0x200B: 84,
+ 0x200D: 67,
+ 0x200E: 84,
+ 0x200F: 84,
+ 0x202A: 84,
+ 0x202B: 84,
+ 0x202C: 84,
+ 0x202D: 84,
+ 0x202E: 84,
+ 0x2060: 84,
+ 0x2061: 84,
+ 0x2062: 84,
+ 0x2063: 84,
+ 0x2064: 84,
+ 0x206A: 84,
+ 0x206B: 84,
+ 0x206C: 84,
+ 0x206D: 84,
+ 0x206E: 84,
+ 0x206F: 84,
+ 0x20D0: 84,
+ 0x20D1: 84,
+ 0x20D2: 84,
+ 0x20D3: 84,
+ 0x20D4: 84,
+ 0x20D5: 84,
+ 0x20D6: 84,
+ 0x20D7: 84,
+ 0x20D8: 84,
+ 0x20D9: 84,
+ 0x20DA: 84,
+ 0x20DB: 84,
+ 0x20DC: 84,
+ 0x20DD: 84,
+ 0x20DE: 84,
+ 0x20DF: 84,
+ 0x20E0: 84,
+ 0x20E1: 84,
+ 0x20E2: 84,
+ 0x20E3: 84,
+ 0x20E4: 84,
+ 0x20E5: 84,
+ 0x20E6: 84,
+ 0x20E7: 84,
+ 0x20E8: 84,
+ 0x20E9: 84,
+ 0x20EA: 84,
+ 0x20EB: 84,
+ 0x20EC: 84,
+ 0x20ED: 84,
+ 0x20EE: 84,
+ 0x20EF: 84,
+ 0x20F0: 84,
+ 0x2CEF: 84,
+ 0x2CF0: 84,
+ 0x2CF1: 84,
+ 0x2D7F: 84,
+ 0x2DE0: 84,
+ 0x2DE1: 84,
+ 0x2DE2: 84,
+ 0x2DE3: 84,
+ 0x2DE4: 84,
+ 0x2DE5: 84,
+ 0x2DE6: 84,
+ 0x2DE7: 84,
+ 0x2DE8: 84,
+ 0x2DE9: 84,
+ 0x2DEA: 84,
+ 0x2DEB: 84,
+ 0x2DEC: 84,
+ 0x2DED: 84,
+ 0x2DEE: 84,
+ 0x2DEF: 84,
+ 0x2DF0: 84,
+ 0x2DF1: 84,
+ 0x2DF2: 84,
+ 0x2DF3: 84,
+ 0x2DF4: 84,
+ 0x2DF5: 84,
+ 0x2DF6: 84,
+ 0x2DF7: 84,
+ 0x2DF8: 84,
+ 0x2DF9: 84,
+ 0x2DFA: 84,
+ 0x2DFB: 84,
+ 0x2DFC: 84,
+ 0x2DFD: 84,
+ 0x2DFE: 84,
+ 0x2DFF: 84,
+ 0x302A: 84,
+ 0x302B: 84,
+ 0x302C: 84,
+ 0x302D: 84,
+ 0x3099: 84,
+ 0x309A: 84,
+ 0xA66F: 84,
+ 0xA670: 84,
+ 0xA671: 84,
+ 0xA672: 84,
+ 0xA674: 84,
+ 0xA675: 84,
+ 0xA676: 84,
+ 0xA677: 84,
+ 0xA678: 84,
+ 0xA679: 84,
+ 0xA67A: 84,
+ 0xA67B: 84,
+ 0xA67C: 84,
+ 0xA67D: 84,
+ 0xA69E: 84,
+ 0xA69F: 84,
+ 0xA6F0: 84,
+ 0xA6F1: 84,
+ 0xA802: 84,
+ 0xA806: 84,
+ 0xA80B: 84,
+ 0xA825: 84,
+ 0xA826: 84,
+ 0xA82C: 84,
+ 0xA840: 68,
+ 0xA841: 68,
+ 0xA842: 68,
+ 0xA843: 68,
+ 0xA844: 68,
+ 0xA845: 68,
+ 0xA846: 68,
+ 0xA847: 68,
+ 0xA848: 68,
+ 0xA849: 68,
+ 0xA84A: 68,
+ 0xA84B: 68,
+ 0xA84C: 68,
+ 0xA84D: 68,
+ 0xA84E: 68,
+ 0xA84F: 68,
+ 0xA850: 68,
+ 0xA851: 68,
+ 0xA852: 68,
+ 0xA853: 68,
+ 0xA854: 68,
+ 0xA855: 68,
+ 0xA856: 68,
+ 0xA857: 68,
+ 0xA858: 68,
+ 0xA859: 68,
+ 0xA85A: 68,
+ 0xA85B: 68,
+ 0xA85C: 68,
+ 0xA85D: 68,
+ 0xA85E: 68,
+ 0xA85F: 68,
+ 0xA860: 68,
+ 0xA861: 68,
+ 0xA862: 68,
+ 0xA863: 68,
+ 0xA864: 68,
+ 0xA865: 68,
+ 0xA866: 68,
+ 0xA867: 68,
+ 0xA868: 68,
+ 0xA869: 68,
+ 0xA86A: 68,
+ 0xA86B: 68,
+ 0xA86C: 68,
+ 0xA86D: 68,
+ 0xA86E: 68,
+ 0xA86F: 68,
+ 0xA870: 68,
+ 0xA871: 68,
+ 0xA872: 76,
+ 0xA8C4: 84,
+ 0xA8C5: 84,
+ 0xA8E0: 84,
+ 0xA8E1: 84,
+ 0xA8E2: 84,
+ 0xA8E3: 84,
+ 0xA8E4: 84,
+ 0xA8E5: 84,
+ 0xA8E6: 84,
+ 0xA8E7: 84,
+ 0xA8E8: 84,
+ 0xA8E9: 84,
+ 0xA8EA: 84,
+ 0xA8EB: 84,
+ 0xA8EC: 84,
+ 0xA8ED: 84,
+ 0xA8EE: 84,
+ 0xA8EF: 84,
+ 0xA8F0: 84,
+ 0xA8F1: 84,
+ 0xA8FF: 84,
+ 0xA926: 84,
+ 0xA927: 84,
+ 0xA928: 84,
+ 0xA929: 84,
+ 0xA92A: 84,
+ 0xA92B: 84,
+ 0xA92C: 84,
+ 0xA92D: 84,
+ 0xA947: 84,
+ 0xA948: 84,
+ 0xA949: 84,
+ 0xA94A: 84,
+ 0xA94B: 84,
+ 0xA94C: 84,
+ 0xA94D: 84,
+ 0xA94E: 84,
+ 0xA94F: 84,
+ 0xA950: 84,
+ 0xA951: 84,
+ 0xA980: 84,
+ 0xA981: 84,
+ 0xA982: 84,
+ 0xA9B3: 84,
+ 0xA9B6: 84,
+ 0xA9B7: 84,
+ 0xA9B8: 84,
+ 0xA9B9: 84,
+ 0xA9BC: 84,
+ 0xA9BD: 84,
+ 0xA9E5: 84,
+ 0xAA29: 84,
+ 0xAA2A: 84,
+ 0xAA2B: 84,
+ 0xAA2C: 84,
+ 0xAA2D: 84,
+ 0xAA2E: 84,
+ 0xAA31: 84,
+ 0xAA32: 84,
+ 0xAA35: 84,
+ 0xAA36: 84,
+ 0xAA43: 84,
+ 0xAA4C: 84,
+ 0xAA7C: 84,
+ 0xAAB0: 84,
+ 0xAAB2: 84,
+ 0xAAB3: 84,
+ 0xAAB4: 84,
+ 0xAAB7: 84,
+ 0xAAB8: 84,
+ 0xAABE: 84,
+ 0xAABF: 84,
+ 0xAAC1: 84,
+ 0xAAEC: 84,
+ 0xAAED: 84,
+ 0xAAF6: 84,
+ 0xABE5: 84,
+ 0xABE8: 84,
+ 0xABED: 84,
+ 0xFB1E: 84,
+ 0xFE00: 84,
+ 0xFE01: 84,
+ 0xFE02: 84,
+ 0xFE03: 84,
+ 0xFE04: 84,
+ 0xFE05: 84,
+ 0xFE06: 84,
+ 0xFE07: 84,
+ 0xFE08: 84,
+ 0xFE09: 84,
+ 0xFE0A: 84,
+ 0xFE0B: 84,
+ 0xFE0C: 84,
+ 0xFE0D: 84,
+ 0xFE0E: 84,
+ 0xFE0F: 84,
+ 0xFE20: 84,
+ 0xFE21: 84,
+ 0xFE22: 84,
+ 0xFE23: 84,
+ 0xFE24: 84,
+ 0xFE25: 84,
+ 0xFE26: 84,
+ 0xFE27: 84,
+ 0xFE28: 84,
+ 0xFE29: 84,
+ 0xFE2A: 84,
+ 0xFE2B: 84,
+ 0xFE2C: 84,
+ 0xFE2D: 84,
+ 0xFE2E: 84,
+ 0xFE2F: 84,
+ 0xFEFF: 84,
+ 0xFFF9: 84,
+ 0xFFFA: 84,
+ 0xFFFB: 84,
+ 0x101FD: 84,
+ 0x102E0: 84,
+ 0x10376: 84,
+ 0x10377: 84,
+ 0x10378: 84,
+ 0x10379: 84,
+ 0x1037A: 84,
+ 0x10A01: 84,
+ 0x10A02: 84,
+ 0x10A03: 84,
+ 0x10A05: 84,
+ 0x10A06: 84,
+ 0x10A0C: 84,
+ 0x10A0D: 84,
+ 0x10A0E: 84,
+ 0x10A0F: 84,
+ 0x10A38: 84,
+ 0x10A39: 84,
+ 0x10A3A: 84,
+ 0x10A3F: 84,
+ 0x10AC0: 68,
+ 0x10AC1: 68,
+ 0x10AC2: 68,
+ 0x10AC3: 68,
+ 0x10AC4: 68,
+ 0x10AC5: 82,
+ 0x10AC7: 82,
+ 0x10AC9: 82,
+ 0x10ACA: 82,
+ 0x10ACD: 76,
+ 0x10ACE: 82,
+ 0x10ACF: 82,
+ 0x10AD0: 82,
+ 0x10AD1: 82,
+ 0x10AD2: 82,
+ 0x10AD3: 68,
+ 0x10AD4: 68,
+ 0x10AD5: 68,
+ 0x10AD6: 68,
+ 0x10AD7: 76,
+ 0x10AD8: 68,
+ 0x10AD9: 68,
+ 0x10ADA: 68,
+ 0x10ADB: 68,
+ 0x10ADC: 68,
+ 0x10ADD: 82,
+ 0x10ADE: 68,
+ 0x10ADF: 68,
+ 0x10AE0: 68,
+ 0x10AE1: 82,
+ 0x10AE4: 82,
+ 0x10AE5: 84,
+ 0x10AE6: 84,
+ 0x10AEB: 68,
+ 0x10AEC: 68,
+ 0x10AED: 68,
+ 0x10AEE: 68,
+ 0x10AEF: 82,
+ 0x10B80: 68,
+ 0x10B81: 82,
+ 0x10B82: 68,
+ 0x10B83: 82,
+ 0x10B84: 82,
+ 0x10B85: 82,
+ 0x10B86: 68,
+ 0x10B87: 68,
+ 0x10B88: 68,
+ 0x10B89: 82,
+ 0x10B8A: 68,
+ 0x10B8B: 68,
+ 0x10B8C: 82,
+ 0x10B8D: 68,
+ 0x10B8E: 82,
+ 0x10B8F: 82,
+ 0x10B90: 68,
+ 0x10B91: 82,
+ 0x10BA9: 82,
+ 0x10BAA: 82,
+ 0x10BAB: 82,
+ 0x10BAC: 82,
+ 0x10BAD: 68,
+ 0x10BAE: 68,
+ 0x10D00: 76,
+ 0x10D01: 68,
+ 0x10D02: 68,
+ 0x10D03: 68,
+ 0x10D04: 68,
+ 0x10D05: 68,
+ 0x10D06: 68,
+ 0x10D07: 68,
+ 0x10D08: 68,
+ 0x10D09: 68,
+ 0x10D0A: 68,
+ 0x10D0B: 68,
+ 0x10D0C: 68,
+ 0x10D0D: 68,
+ 0x10D0E: 68,
+ 0x10D0F: 68,
+ 0x10D10: 68,
+ 0x10D11: 68,
+ 0x10D12: 68,
+ 0x10D13: 68,
+ 0x10D14: 68,
+ 0x10D15: 68,
+ 0x10D16: 68,
+ 0x10D17: 68,
+ 0x10D18: 68,
+ 0x10D19: 68,
+ 0x10D1A: 68,
+ 0x10D1B: 68,
+ 0x10D1C: 68,
+ 0x10D1D: 68,
+ 0x10D1E: 68,
+ 0x10D1F: 68,
+ 0x10D20: 68,
+ 0x10D21: 68,
+ 0x10D22: 82,
+ 0x10D23: 68,
+ 0x10D24: 84,
+ 0x10D25: 84,
+ 0x10D26: 84,
+ 0x10D27: 84,
+ 0x10EAB: 84,
+ 0x10EAC: 84,
+ 0x10EFD: 84,
+ 0x10EFE: 84,
+ 0x10EFF: 84,
+ 0x10F30: 68,
+ 0x10F31: 68,
+ 0x10F32: 68,
+ 0x10F33: 82,
+ 0x10F34: 68,
+ 0x10F35: 68,
+ 0x10F36: 68,
+ 0x10F37: 68,
+ 0x10F38: 68,
+ 0x10F39: 68,
+ 0x10F3A: 68,
+ 0x10F3B: 68,
+ 0x10F3C: 68,
+ 0x10F3D: 68,
+ 0x10F3E: 68,
+ 0x10F3F: 68,
+ 0x10F40: 68,
+ 0x10F41: 68,
+ 0x10F42: 68,
+ 0x10F43: 68,
+ 0x10F44: 68,
+ 0x10F46: 84,
+ 0x10F47: 84,
+ 0x10F48: 84,
+ 0x10F49: 84,
+ 0x10F4A: 84,
+ 0x10F4B: 84,
+ 0x10F4C: 84,
+ 0x10F4D: 84,
+ 0x10F4E: 84,
+ 0x10F4F: 84,
+ 0x10F50: 84,
+ 0x10F51: 68,
+ 0x10F52: 68,
+ 0x10F53: 68,
+ 0x10F54: 82,
+ 0x10F70: 68,
+ 0x10F71: 68,
+ 0x10F72: 68,
+ 0x10F73: 68,
+ 0x10F74: 82,
+ 0x10F75: 82,
+ 0x10F76: 68,
+ 0x10F77: 68,
+ 0x10F78: 68,
+ 0x10F79: 68,
+ 0x10F7A: 68,
+ 0x10F7B: 68,
+ 0x10F7C: 68,
+ 0x10F7D: 68,
+ 0x10F7E: 68,
+ 0x10F7F: 68,
+ 0x10F80: 68,
+ 0x10F81: 68,
+ 0x10F82: 84,
+ 0x10F83: 84,
+ 0x10F84: 84,
+ 0x10F85: 84,
+ 0x10FB0: 68,
+ 0x10FB2: 68,
+ 0x10FB3: 68,
+ 0x10FB4: 82,
+ 0x10FB5: 82,
+ 0x10FB6: 82,
+ 0x10FB8: 68,
+ 0x10FB9: 82,
+ 0x10FBA: 82,
+ 0x10FBB: 68,
+ 0x10FBC: 68,
+ 0x10FBD: 82,
+ 0x10FBE: 68,
+ 0x10FBF: 68,
+ 0x10FC1: 68,
+ 0x10FC2: 82,
+ 0x10FC3: 82,
+ 0x10FC4: 68,
+ 0x10FC9: 82,
+ 0x10FCA: 68,
+ 0x10FCB: 76,
+ 0x11001: 84,
+ 0x11038: 84,
+ 0x11039: 84,
+ 0x1103A: 84,
+ 0x1103B: 84,
+ 0x1103C: 84,
+ 0x1103D: 84,
+ 0x1103E: 84,
+ 0x1103F: 84,
+ 0x11040: 84,
+ 0x11041: 84,
+ 0x11042: 84,
+ 0x11043: 84,
+ 0x11044: 84,
+ 0x11045: 84,
+ 0x11046: 84,
+ 0x11070: 84,
+ 0x11073: 84,
+ 0x11074: 84,
+ 0x1107F: 84,
+ 0x11080: 84,
+ 0x11081: 84,
+ 0x110B3: 84,
+ 0x110B4: 84,
+ 0x110B5: 84,
+ 0x110B6: 84,
+ 0x110B9: 84,
+ 0x110BA: 84,
+ 0x110C2: 84,
+ 0x11100: 84,
+ 0x11101: 84,
+ 0x11102: 84,
+ 0x11127: 84,
+ 0x11128: 84,
+ 0x11129: 84,
+ 0x1112A: 84,
+ 0x1112B: 84,
+ 0x1112D: 84,
+ 0x1112E: 84,
+ 0x1112F: 84,
+ 0x11130: 84,
+ 0x11131: 84,
+ 0x11132: 84,
+ 0x11133: 84,
+ 0x11134: 84,
+ 0x11173: 84,
+ 0x11180: 84,
+ 0x11181: 84,
+ 0x111B6: 84,
+ 0x111B7: 84,
+ 0x111B8: 84,
+ 0x111B9: 84,
+ 0x111BA: 84,
+ 0x111BB: 84,
+ 0x111BC: 84,
+ 0x111BD: 84,
+ 0x111BE: 84,
+ 0x111C9: 84,
+ 0x111CA: 84,
+ 0x111CB: 84,
+ 0x111CC: 84,
+ 0x111CF: 84,
+ 0x1122F: 84,
+ 0x11230: 84,
+ 0x11231: 84,
+ 0x11234: 84,
+ 0x11236: 84,
+ 0x11237: 84,
+ 0x1123E: 84,
+ 0x11241: 84,
+ 0x112DF: 84,
+ 0x112E3: 84,
+ 0x112E4: 84,
+ 0x112E5: 84,
+ 0x112E6: 84,
+ 0x112E7: 84,
+ 0x112E8: 84,
+ 0x112E9: 84,
+ 0x112EA: 84,
+ 0x11300: 84,
+ 0x11301: 84,
+ 0x1133B: 84,
+ 0x1133C: 84,
+ 0x11340: 84,
+ 0x11366: 84,
+ 0x11367: 84,
+ 0x11368: 84,
+ 0x11369: 84,
+ 0x1136A: 84,
+ 0x1136B: 84,
+ 0x1136C: 84,
+ 0x11370: 84,
+ 0x11371: 84,
+ 0x11372: 84,
+ 0x11373: 84,
+ 0x11374: 84,
+ 0x11438: 84,
+ 0x11439: 84,
+ 0x1143A: 84,
+ 0x1143B: 84,
+ 0x1143C: 84,
+ 0x1143D: 84,
+ 0x1143E: 84,
+ 0x1143F: 84,
+ 0x11442: 84,
+ 0x11443: 84,
+ 0x11444: 84,
+ 0x11446: 84,
+ 0x1145E: 84,
+ 0x114B3: 84,
+ 0x114B4: 84,
+ 0x114B5: 84,
+ 0x114B6: 84,
+ 0x114B7: 84,
+ 0x114B8: 84,
+ 0x114BA: 84,
+ 0x114BF: 84,
+ 0x114C0: 84,
+ 0x114C2: 84,
+ 0x114C3: 84,
+ 0x115B2: 84,
+ 0x115B3: 84,
+ 0x115B4: 84,
+ 0x115B5: 84,
+ 0x115BC: 84,
+ 0x115BD: 84,
+ 0x115BF: 84,
+ 0x115C0: 84,
+ 0x115DC: 84,
+ 0x115DD: 84,
+ 0x11633: 84,
+ 0x11634: 84,
+ 0x11635: 84,
+ 0x11636: 84,
+ 0x11637: 84,
+ 0x11638: 84,
+ 0x11639: 84,
+ 0x1163A: 84,
+ 0x1163D: 84,
+ 0x1163F: 84,
+ 0x11640: 84,
+ 0x116AB: 84,
+ 0x116AD: 84,
+ 0x116B0: 84,
+ 0x116B1: 84,
+ 0x116B2: 84,
+ 0x116B3: 84,
+ 0x116B4: 84,
+ 0x116B5: 84,
+ 0x116B7: 84,
+ 0x1171D: 84,
+ 0x1171E: 84,
+ 0x1171F: 84,
+ 0x11722: 84,
+ 0x11723: 84,
+ 0x11724: 84,
+ 0x11725: 84,
+ 0x11727: 84,
+ 0x11728: 84,
+ 0x11729: 84,
+ 0x1172A: 84,
+ 0x1172B: 84,
+ 0x1182F: 84,
+ 0x11830: 84,
+ 0x11831: 84,
+ 0x11832: 84,
+ 0x11833: 84,
+ 0x11834: 84,
+ 0x11835: 84,
+ 0x11836: 84,
+ 0x11837: 84,
+ 0x11839: 84,
+ 0x1183A: 84,
+ 0x1193B: 84,
+ 0x1193C: 84,
+ 0x1193E: 84,
+ 0x11943: 84,
+ 0x119D4: 84,
+ 0x119D5: 84,
+ 0x119D6: 84,
+ 0x119D7: 84,
+ 0x119DA: 84,
+ 0x119DB: 84,
+ 0x119E0: 84,
+ 0x11A01: 84,
+ 0x11A02: 84,
+ 0x11A03: 84,
+ 0x11A04: 84,
+ 0x11A05: 84,
+ 0x11A06: 84,
+ 0x11A07: 84,
+ 0x11A08: 84,
+ 0x11A09: 84,
+ 0x11A0A: 84,
+ 0x11A33: 84,
+ 0x11A34: 84,
+ 0x11A35: 84,
+ 0x11A36: 84,
+ 0x11A37: 84,
+ 0x11A38: 84,
+ 0x11A3B: 84,
+ 0x11A3C: 84,
+ 0x11A3D: 84,
+ 0x11A3E: 84,
+ 0x11A47: 84,
+ 0x11A51: 84,
+ 0x11A52: 84,
+ 0x11A53: 84,
+ 0x11A54: 84,
+ 0x11A55: 84,
+ 0x11A56: 84,
+ 0x11A59: 84,
+ 0x11A5A: 84,
+ 0x11A5B: 84,
+ 0x11A8A: 84,
+ 0x11A8B: 84,
+ 0x11A8C: 84,
+ 0x11A8D: 84,
+ 0x11A8E: 84,
+ 0x11A8F: 84,
+ 0x11A90: 84,
+ 0x11A91: 84,
+ 0x11A92: 84,
+ 0x11A93: 84,
+ 0x11A94: 84,
+ 0x11A95: 84,
+ 0x11A96: 84,
+ 0x11A98: 84,
+ 0x11A99: 84,
+ 0x11C30: 84,
+ 0x11C31: 84,
+ 0x11C32: 84,
+ 0x11C33: 84,
+ 0x11C34: 84,
+ 0x11C35: 84,
+ 0x11C36: 84,
+ 0x11C38: 84,
+ 0x11C39: 84,
+ 0x11C3A: 84,
+ 0x11C3B: 84,
+ 0x11C3C: 84,
+ 0x11C3D: 84,
+ 0x11C3F: 84,
+ 0x11C92: 84,
+ 0x11C93: 84,
+ 0x11C94: 84,
+ 0x11C95: 84,
+ 0x11C96: 84,
+ 0x11C97: 84,
+ 0x11C98: 84,
+ 0x11C99: 84,
+ 0x11C9A: 84,
+ 0x11C9B: 84,
+ 0x11C9C: 84,
+ 0x11C9D: 84,
+ 0x11C9E: 84,
+ 0x11C9F: 84,
+ 0x11CA0: 84,
+ 0x11CA1: 84,
+ 0x11CA2: 84,
+ 0x11CA3: 84,
+ 0x11CA4: 84,
+ 0x11CA5: 84,
+ 0x11CA6: 84,
+ 0x11CA7: 84,
+ 0x11CAA: 84,
+ 0x11CAB: 84,
+ 0x11CAC: 84,
+ 0x11CAD: 84,
+ 0x11CAE: 84,
+ 0x11CAF: 84,
+ 0x11CB0: 84,
+ 0x11CB2: 84,
+ 0x11CB3: 84,
+ 0x11CB5: 84,
+ 0x11CB6: 84,
+ 0x11D31: 84,
+ 0x11D32: 84,
+ 0x11D33: 84,
+ 0x11D34: 84,
+ 0x11D35: 84,
+ 0x11D36: 84,
+ 0x11D3A: 84,
+ 0x11D3C: 84,
+ 0x11D3D: 84,
+ 0x11D3F: 84,
+ 0x11D40: 84,
+ 0x11D41: 84,
+ 0x11D42: 84,
+ 0x11D43: 84,
+ 0x11D44: 84,
+ 0x11D45: 84,
+ 0x11D47: 84,
+ 0x11D90: 84,
+ 0x11D91: 84,
+ 0x11D95: 84,
+ 0x11D97: 84,
+ 0x11EF3: 84,
+ 0x11EF4: 84,
+ 0x11F00: 84,
+ 0x11F01: 84,
+ 0x11F36: 84,
+ 0x11F37: 84,
+ 0x11F38: 84,
+ 0x11F39: 84,
+ 0x11F3A: 84,
+ 0x11F40: 84,
+ 0x11F42: 84,
+ 0x13430: 84,
+ 0x13431: 84,
+ 0x13432: 84,
+ 0x13433: 84,
+ 0x13434: 84,
+ 0x13435: 84,
+ 0x13436: 84,
+ 0x13437: 84,
+ 0x13438: 84,
+ 0x13439: 84,
+ 0x1343A: 84,
+ 0x1343B: 84,
+ 0x1343C: 84,
+ 0x1343D: 84,
+ 0x1343E: 84,
+ 0x1343F: 84,
+ 0x13440: 84,
+ 0x13447: 84,
+ 0x13448: 84,
+ 0x13449: 84,
+ 0x1344A: 84,
+ 0x1344B: 84,
+ 0x1344C: 84,
+ 0x1344D: 84,
+ 0x1344E: 84,
+ 0x1344F: 84,
+ 0x13450: 84,
+ 0x13451: 84,
+ 0x13452: 84,
+ 0x13453: 84,
+ 0x13454: 84,
+ 0x13455: 84,
+ 0x16AF0: 84,
+ 0x16AF1: 84,
+ 0x16AF2: 84,
+ 0x16AF3: 84,
+ 0x16AF4: 84,
+ 0x16B30: 84,
+ 0x16B31: 84,
+ 0x16B32: 84,
+ 0x16B33: 84,
+ 0x16B34: 84,
+ 0x16B35: 84,
+ 0x16B36: 84,
+ 0x16F4F: 84,
+ 0x16F8F: 84,
+ 0x16F90: 84,
+ 0x16F91: 84,
+ 0x16F92: 84,
+ 0x16FE4: 84,
+ 0x1BC9D: 84,
+ 0x1BC9E: 84,
+ 0x1BCA0: 84,
+ 0x1BCA1: 84,
+ 0x1BCA2: 84,
+ 0x1BCA3: 84,
+ 0x1CF00: 84,
+ 0x1CF01: 84,
+ 0x1CF02: 84,
+ 0x1CF03: 84,
+ 0x1CF04: 84,
+ 0x1CF05: 84,
+ 0x1CF06: 84,
+ 0x1CF07: 84,
+ 0x1CF08: 84,
+ 0x1CF09: 84,
+ 0x1CF0A: 84,
+ 0x1CF0B: 84,
+ 0x1CF0C: 84,
+ 0x1CF0D: 84,
+ 0x1CF0E: 84,
+ 0x1CF0F: 84,
+ 0x1CF10: 84,
+ 0x1CF11: 84,
+ 0x1CF12: 84,
+ 0x1CF13: 84,
+ 0x1CF14: 84,
+ 0x1CF15: 84,
+ 0x1CF16: 84,
+ 0x1CF17: 84,
+ 0x1CF18: 84,
+ 0x1CF19: 84,
+ 0x1CF1A: 84,
+ 0x1CF1B: 84,
+ 0x1CF1C: 84,
+ 0x1CF1D: 84,
+ 0x1CF1E: 84,
+ 0x1CF1F: 84,
+ 0x1CF20: 84,
+ 0x1CF21: 84,
+ 0x1CF22: 84,
+ 0x1CF23: 84,
+ 0x1CF24: 84,
+ 0x1CF25: 84,
+ 0x1CF26: 84,
+ 0x1CF27: 84,
+ 0x1CF28: 84,
+ 0x1CF29: 84,
+ 0x1CF2A: 84,
+ 0x1CF2B: 84,
+ 0x1CF2C: 84,
+ 0x1CF2D: 84,
+ 0x1CF30: 84,
+ 0x1CF31: 84,
+ 0x1CF32: 84,
+ 0x1CF33: 84,
+ 0x1CF34: 84,
+ 0x1CF35: 84,
+ 0x1CF36: 84,
+ 0x1CF37: 84,
+ 0x1CF38: 84,
+ 0x1CF39: 84,
+ 0x1CF3A: 84,
+ 0x1CF3B: 84,
+ 0x1CF3C: 84,
+ 0x1CF3D: 84,
+ 0x1CF3E: 84,
+ 0x1CF3F: 84,
+ 0x1CF40: 84,
+ 0x1CF41: 84,
+ 0x1CF42: 84,
+ 0x1CF43: 84,
+ 0x1CF44: 84,
+ 0x1CF45: 84,
+ 0x1CF46: 84,
+ 0x1D167: 84,
+ 0x1D168: 84,
+ 0x1D169: 84,
+ 0x1D173: 84,
+ 0x1D174: 84,
+ 0x1D175: 84,
+ 0x1D176: 84,
+ 0x1D177: 84,
+ 0x1D178: 84,
+ 0x1D179: 84,
+ 0x1D17A: 84,
+ 0x1D17B: 84,
+ 0x1D17C: 84,
+ 0x1D17D: 84,
+ 0x1D17E: 84,
+ 0x1D17F: 84,
+ 0x1D180: 84,
+ 0x1D181: 84,
+ 0x1D182: 84,
+ 0x1D185: 84,
+ 0x1D186: 84,
+ 0x1D187: 84,
+ 0x1D188: 84,
+ 0x1D189: 84,
+ 0x1D18A: 84,
+ 0x1D18B: 84,
+ 0x1D1AA: 84,
+ 0x1D1AB: 84,
+ 0x1D1AC: 84,
+ 0x1D1AD: 84,
+ 0x1D242: 84,
+ 0x1D243: 84,
+ 0x1D244: 84,
+ 0x1DA00: 84,
+ 0x1DA01: 84,
+ 0x1DA02: 84,
+ 0x1DA03: 84,
+ 0x1DA04: 84,
+ 0x1DA05: 84,
+ 0x1DA06: 84,
+ 0x1DA07: 84,
+ 0x1DA08: 84,
+ 0x1DA09: 84,
+ 0x1DA0A: 84,
+ 0x1DA0B: 84,
+ 0x1DA0C: 84,
+ 0x1DA0D: 84,
+ 0x1DA0E: 84,
+ 0x1DA0F: 84,
+ 0x1DA10: 84,
+ 0x1DA11: 84,
+ 0x1DA12: 84,
+ 0x1DA13: 84,
+ 0x1DA14: 84,
+ 0x1DA15: 84,
+ 0x1DA16: 84,
+ 0x1DA17: 84,
+ 0x1DA18: 84,
+ 0x1DA19: 84,
+ 0x1DA1A: 84,
+ 0x1DA1B: 84,
+ 0x1DA1C: 84,
+ 0x1DA1D: 84,
+ 0x1DA1E: 84,
+ 0x1DA1F: 84,
+ 0x1DA20: 84,
+ 0x1DA21: 84,
+ 0x1DA22: 84,
+ 0x1DA23: 84,
+ 0x1DA24: 84,
+ 0x1DA25: 84,
+ 0x1DA26: 84,
+ 0x1DA27: 84,
+ 0x1DA28: 84,
+ 0x1DA29: 84,
+ 0x1DA2A: 84,
+ 0x1DA2B: 84,
+ 0x1DA2C: 84,
+ 0x1DA2D: 84,
+ 0x1DA2E: 84,
+ 0x1DA2F: 84,
+ 0x1DA30: 84,
+ 0x1DA31: 84,
+ 0x1DA32: 84,
+ 0x1DA33: 84,
+ 0x1DA34: 84,
+ 0x1DA35: 84,
+ 0x1DA36: 84,
+ 0x1DA3B: 84,
+ 0x1DA3C: 84,
+ 0x1DA3D: 84,
+ 0x1DA3E: 84,
+ 0x1DA3F: 84,
+ 0x1DA40: 84,
+ 0x1DA41: 84,
+ 0x1DA42: 84,
+ 0x1DA43: 84,
+ 0x1DA44: 84,
+ 0x1DA45: 84,
+ 0x1DA46: 84,
+ 0x1DA47: 84,
+ 0x1DA48: 84,
+ 0x1DA49: 84,
+ 0x1DA4A: 84,
+ 0x1DA4B: 84,
+ 0x1DA4C: 84,
+ 0x1DA4D: 84,
+ 0x1DA4E: 84,
+ 0x1DA4F: 84,
+ 0x1DA50: 84,
+ 0x1DA51: 84,
+ 0x1DA52: 84,
+ 0x1DA53: 84,
+ 0x1DA54: 84,
+ 0x1DA55: 84,
+ 0x1DA56: 84,
+ 0x1DA57: 84,
+ 0x1DA58: 84,
+ 0x1DA59: 84,
+ 0x1DA5A: 84,
+ 0x1DA5B: 84,
+ 0x1DA5C: 84,
+ 0x1DA5D: 84,
+ 0x1DA5E: 84,
+ 0x1DA5F: 84,
+ 0x1DA60: 84,
+ 0x1DA61: 84,
+ 0x1DA62: 84,
+ 0x1DA63: 84,
+ 0x1DA64: 84,
+ 0x1DA65: 84,
+ 0x1DA66: 84,
+ 0x1DA67: 84,
+ 0x1DA68: 84,
+ 0x1DA69: 84,
+ 0x1DA6A: 84,
+ 0x1DA6B: 84,
+ 0x1DA6C: 84,
+ 0x1DA75: 84,
+ 0x1DA84: 84,
+ 0x1DA9B: 84,
+ 0x1DA9C: 84,
+ 0x1DA9D: 84,
+ 0x1DA9E: 84,
+ 0x1DA9F: 84,
+ 0x1DAA1: 84,
+ 0x1DAA2: 84,
+ 0x1DAA3: 84,
+ 0x1DAA4: 84,
+ 0x1DAA5: 84,
+ 0x1DAA6: 84,
+ 0x1DAA7: 84,
+ 0x1DAA8: 84,
+ 0x1DAA9: 84,
+ 0x1DAAA: 84,
+ 0x1DAAB: 84,
+ 0x1DAAC: 84,
+ 0x1DAAD: 84,
+ 0x1DAAE: 84,
+ 0x1DAAF: 84,
+ 0x1E000: 84,
+ 0x1E001: 84,
+ 0x1E002: 84,
+ 0x1E003: 84,
+ 0x1E004: 84,
+ 0x1E005: 84,
+ 0x1E006: 84,
+ 0x1E008: 84,
+ 0x1E009: 84,
+ 0x1E00A: 84,
+ 0x1E00B: 84,
+ 0x1E00C: 84,
+ 0x1E00D: 84,
+ 0x1E00E: 84,
+ 0x1E00F: 84,
+ 0x1E010: 84,
+ 0x1E011: 84,
+ 0x1E012: 84,
+ 0x1E013: 84,
+ 0x1E014: 84,
+ 0x1E015: 84,
+ 0x1E016: 84,
+ 0x1E017: 84,
+ 0x1E018: 84,
+ 0x1E01B: 84,
+ 0x1E01C: 84,
+ 0x1E01D: 84,
+ 0x1E01E: 84,
+ 0x1E01F: 84,
+ 0x1E020: 84,
+ 0x1E021: 84,
+ 0x1E023: 84,
+ 0x1E024: 84,
+ 0x1E026: 84,
+ 0x1E027: 84,
+ 0x1E028: 84,
+ 0x1E029: 84,
+ 0x1E02A: 84,
+ 0x1E08F: 84,
+ 0x1E130: 84,
+ 0x1E131: 84,
+ 0x1E132: 84,
+ 0x1E133: 84,
+ 0x1E134: 84,
+ 0x1E135: 84,
+ 0x1E136: 84,
+ 0x1E2AE: 84,
+ 0x1E2EC: 84,
+ 0x1E2ED: 84,
+ 0x1E2EE: 84,
+ 0x1E2EF: 84,
+ 0x1E4EC: 84,
+ 0x1E4ED: 84,
+ 0x1E4EE: 84,
+ 0x1E4EF: 84,
+ 0x1E8D0: 84,
+ 0x1E8D1: 84,
+ 0x1E8D2: 84,
+ 0x1E8D3: 84,
+ 0x1E8D4: 84,
+ 0x1E8D5: 84,
+ 0x1E8D6: 84,
+ 0x1E900: 68,
+ 0x1E901: 68,
+ 0x1E902: 68,
+ 0x1E903: 68,
+ 0x1E904: 68,
+ 0x1E905: 68,
+ 0x1E906: 68,
+ 0x1E907: 68,
+ 0x1E908: 68,
+ 0x1E909: 68,
+ 0x1E90A: 68,
+ 0x1E90B: 68,
+ 0x1E90C: 68,
+ 0x1E90D: 68,
+ 0x1E90E: 68,
+ 0x1E90F: 68,
+ 0x1E910: 68,
+ 0x1E911: 68,
+ 0x1E912: 68,
+ 0x1E913: 68,
+ 0x1E914: 68,
+ 0x1E915: 68,
+ 0x1E916: 68,
+ 0x1E917: 68,
+ 0x1E918: 68,
+ 0x1E919: 68,
+ 0x1E91A: 68,
+ 0x1E91B: 68,
+ 0x1E91C: 68,
+ 0x1E91D: 68,
+ 0x1E91E: 68,
+ 0x1E91F: 68,
+ 0x1E920: 68,
+ 0x1E921: 68,
+ 0x1E922: 68,
+ 0x1E923: 68,
+ 0x1E924: 68,
+ 0x1E925: 68,
+ 0x1E926: 68,
+ 0x1E927: 68,
+ 0x1E928: 68,
+ 0x1E929: 68,
+ 0x1E92A: 68,
+ 0x1E92B: 68,
+ 0x1E92C: 68,
+ 0x1E92D: 68,
+ 0x1E92E: 68,
+ 0x1E92F: 68,
+ 0x1E930: 68,
+ 0x1E931: 68,
+ 0x1E932: 68,
+ 0x1E933: 68,
+ 0x1E934: 68,
+ 0x1E935: 68,
+ 0x1E936: 68,
+ 0x1E937: 68,
+ 0x1E938: 68,
+ 0x1E939: 68,
+ 0x1E93A: 68,
+ 0x1E93B: 68,
+ 0x1E93C: 68,
+ 0x1E93D: 68,
+ 0x1E93E: 68,
+ 0x1E93F: 68,
+ 0x1E940: 68,
+ 0x1E941: 68,
+ 0x1E942: 68,
+ 0x1E943: 68,
+ 0x1E944: 84,
+ 0x1E945: 84,
+ 0x1E946: 84,
+ 0x1E947: 84,
+ 0x1E948: 84,
+ 0x1E949: 84,
+ 0x1E94A: 84,
+ 0x1E94B: 84,
+ 0xE0001: 84,
+ 0xE0020: 84,
+ 0xE0021: 84,
+ 0xE0022: 84,
+ 0xE0023: 84,
+ 0xE0024: 84,
+ 0xE0025: 84,
+ 0xE0026: 84,
+ 0xE0027: 84,
+ 0xE0028: 84,
+ 0xE0029: 84,
+ 0xE002A: 84,
+ 0xE002B: 84,
+ 0xE002C: 84,
+ 0xE002D: 84,
+ 0xE002E: 84,
+ 0xE002F: 84,
+ 0xE0030: 84,
+ 0xE0031: 84,
+ 0xE0032: 84,
+ 0xE0033: 84,
+ 0xE0034: 84,
+ 0xE0035: 84,
+ 0xE0036: 84,
+ 0xE0037: 84,
+ 0xE0038: 84,
+ 0xE0039: 84,
+ 0xE003A: 84,
+ 0xE003B: 84,
+ 0xE003C: 84,
+ 0xE003D: 84,
+ 0xE003E: 84,
+ 0xE003F: 84,
+ 0xE0040: 84,
+ 0xE0041: 84,
+ 0xE0042: 84,
+ 0xE0043: 84,
+ 0xE0044: 84,
+ 0xE0045: 84,
+ 0xE0046: 84,
+ 0xE0047: 84,
+ 0xE0048: 84,
+ 0xE0049: 84,
+ 0xE004A: 84,
+ 0xE004B: 84,
+ 0xE004C: 84,
+ 0xE004D: 84,
+ 0xE004E: 84,
+ 0xE004F: 84,
+ 0xE0050: 84,
+ 0xE0051: 84,
+ 0xE0052: 84,
+ 0xE0053: 84,
+ 0xE0054: 84,
+ 0xE0055: 84,
+ 0xE0056: 84,
+ 0xE0057: 84,
+ 0xE0058: 84,
+ 0xE0059: 84,
+ 0xE005A: 84,
+ 0xE005B: 84,
+ 0xE005C: 84,
+ 0xE005D: 84,
+ 0xE005E: 84,
+ 0xE005F: 84,
+ 0xE0060: 84,
+ 0xE0061: 84,
+ 0xE0062: 84,
+ 0xE0063: 84,
+ 0xE0064: 84,
+ 0xE0065: 84,
+ 0xE0066: 84,
+ 0xE0067: 84,
+ 0xE0068: 84,
+ 0xE0069: 84,
+ 0xE006A: 84,
+ 0xE006B: 84,
+ 0xE006C: 84,
+ 0xE006D: 84,
+ 0xE006E: 84,
+ 0xE006F: 84,
+ 0xE0070: 84,
+ 0xE0071: 84,
+ 0xE0072: 84,
+ 0xE0073: 84,
+ 0xE0074: 84,
+ 0xE0075: 84,
+ 0xE0076: 84,
+ 0xE0077: 84,
+ 0xE0078: 84,
+ 0xE0079: 84,
+ 0xE007A: 84,
+ 0xE007B: 84,
+ 0xE007C: 84,
+ 0xE007D: 84,
+ 0xE007E: 84,
+ 0xE007F: 84,
+ 0xE0100: 84,
+ 0xE0101: 84,
+ 0xE0102: 84,
+ 0xE0103: 84,
+ 0xE0104: 84,
+ 0xE0105: 84,
+ 0xE0106: 84,
+ 0xE0107: 84,
+ 0xE0108: 84,
+ 0xE0109: 84,
+ 0xE010A: 84,
+ 0xE010B: 84,
+ 0xE010C: 84,
+ 0xE010D: 84,
+ 0xE010E: 84,
+ 0xE010F: 84,
+ 0xE0110: 84,
+ 0xE0111: 84,
+ 0xE0112: 84,
+ 0xE0113: 84,
+ 0xE0114: 84,
+ 0xE0115: 84,
+ 0xE0116: 84,
+ 0xE0117: 84,
+ 0xE0118: 84,
+ 0xE0119: 84,
+ 0xE011A: 84,
+ 0xE011B: 84,
+ 0xE011C: 84,
+ 0xE011D: 84,
+ 0xE011E: 84,
+ 0xE011F: 84,
+ 0xE0120: 84,
+ 0xE0121: 84,
+ 0xE0122: 84,
+ 0xE0123: 84,
+ 0xE0124: 84,
+ 0xE0125: 84,
+ 0xE0126: 84,
+ 0xE0127: 84,
+ 0xE0128: 84,
+ 0xE0129: 84,
+ 0xE012A: 84,
+ 0xE012B: 84,
+ 0xE012C: 84,
+ 0xE012D: 84,
+ 0xE012E: 84,
+ 0xE012F: 84,
+ 0xE0130: 84,
+ 0xE0131: 84,
+ 0xE0132: 84,
+ 0xE0133: 84,
+ 0xE0134: 84,
+ 0xE0135: 84,
+ 0xE0136: 84,
+ 0xE0137: 84,
+ 0xE0138: 84,
+ 0xE0139: 84,
+ 0xE013A: 84,
+ 0xE013B: 84,
+ 0xE013C: 84,
+ 0xE013D: 84,
+ 0xE013E: 84,
+ 0xE013F: 84,
+ 0xE0140: 84,
+ 0xE0141: 84,
+ 0xE0142: 84,
+ 0xE0143: 84,
+ 0xE0144: 84,
+ 0xE0145: 84,
+ 0xE0146: 84,
+ 0xE0147: 84,
+ 0xE0148: 84,
+ 0xE0149: 84,
+ 0xE014A: 84,
+ 0xE014B: 84,
+ 0xE014C: 84,
+ 0xE014D: 84,
+ 0xE014E: 84,
+ 0xE014F: 84,
+ 0xE0150: 84,
+ 0xE0151: 84,
+ 0xE0152: 84,
+ 0xE0153: 84,
+ 0xE0154: 84,
+ 0xE0155: 84,
+ 0xE0156: 84,
+ 0xE0157: 84,
+ 0xE0158: 84,
+ 0xE0159: 84,
+ 0xE015A: 84,
+ 0xE015B: 84,
+ 0xE015C: 84,
+ 0xE015D: 84,
+ 0xE015E: 84,
+ 0xE015F: 84,
+ 0xE0160: 84,
+ 0xE0161: 84,
+ 0xE0162: 84,
+ 0xE0163: 84,
+ 0xE0164: 84,
+ 0xE0165: 84,
+ 0xE0166: 84,
+ 0xE0167: 84,
+ 0xE0168: 84,
+ 0xE0169: 84,
+ 0xE016A: 84,
+ 0xE016B: 84,
+ 0xE016C: 84,
+ 0xE016D: 84,
+ 0xE016E: 84,
+ 0xE016F: 84,
+ 0xE0170: 84,
+ 0xE0171: 84,
+ 0xE0172: 84,
+ 0xE0173: 84,
+ 0xE0174: 84,
+ 0xE0175: 84,
+ 0xE0176: 84,
+ 0xE0177: 84,
+ 0xE0178: 84,
+ 0xE0179: 84,
+ 0xE017A: 84,
+ 0xE017B: 84,
+ 0xE017C: 84,
+ 0xE017D: 84,
+ 0xE017E: 84,
+ 0xE017F: 84,
+ 0xE0180: 84,
+ 0xE0181: 84,
+ 0xE0182: 84,
+ 0xE0183: 84,
+ 0xE0184: 84,
+ 0xE0185: 84,
+ 0xE0186: 84,
+ 0xE0187: 84,
+ 0xE0188: 84,
+ 0xE0189: 84,
+ 0xE018A: 84,
+ 0xE018B: 84,
+ 0xE018C: 84,
+ 0xE018D: 84,
+ 0xE018E: 84,
+ 0xE018F: 84,
+ 0xE0190: 84,
+ 0xE0191: 84,
+ 0xE0192: 84,
+ 0xE0193: 84,
+ 0xE0194: 84,
+ 0xE0195: 84,
+ 0xE0196: 84,
+ 0xE0197: 84,
+ 0xE0198: 84,
+ 0xE0199: 84,
+ 0xE019A: 84,
+ 0xE019B: 84,
+ 0xE019C: 84,
+ 0xE019D: 84,
+ 0xE019E: 84,
+ 0xE019F: 84,
+ 0xE01A0: 84,
+ 0xE01A1: 84,
+ 0xE01A2: 84,
+ 0xE01A3: 84,
+ 0xE01A4: 84,
+ 0xE01A5: 84,
+ 0xE01A6: 84,
+ 0xE01A7: 84,
+ 0xE01A8: 84,
+ 0xE01A9: 84,
+ 0xE01AA: 84,
+ 0xE01AB: 84,
+ 0xE01AC: 84,
+ 0xE01AD: 84,
+ 0xE01AE: 84,
+ 0xE01AF: 84,
+ 0xE01B0: 84,
+ 0xE01B1: 84,
+ 0xE01B2: 84,
+ 0xE01B3: 84,
+ 0xE01B4: 84,
+ 0xE01B5: 84,
+ 0xE01B6: 84,
+ 0xE01B7: 84,
+ 0xE01B8: 84,
+ 0xE01B9: 84,
+ 0xE01BA: 84,
+ 0xE01BB: 84,
+ 0xE01BC: 84,
+ 0xE01BD: 84,
+ 0xE01BE: 84,
+ 0xE01BF: 84,
+ 0xE01C0: 84,
+ 0xE01C1: 84,
+ 0xE01C2: 84,
+ 0xE01C3: 84,
+ 0xE01C4: 84,
+ 0xE01C5: 84,
+ 0xE01C6: 84,
+ 0xE01C7: 84,
+ 0xE01C8: 84,
+ 0xE01C9: 84,
+ 0xE01CA: 84,
+ 0xE01CB: 84,
+ 0xE01CC: 84,
+ 0xE01CD: 84,
+ 0xE01CE: 84,
+ 0xE01CF: 84,
+ 0xE01D0: 84,
+ 0xE01D1: 84,
+ 0xE01D2: 84,
+ 0xE01D3: 84,
+ 0xE01D4: 84,
+ 0xE01D5: 84,
+ 0xE01D6: 84,
+ 0xE01D7: 84,
+ 0xE01D8: 84,
+ 0xE01D9: 84,
+ 0xE01DA: 84,
+ 0xE01DB: 84,
+ 0xE01DC: 84,
+ 0xE01DD: 84,
+ 0xE01DE: 84,
+ 0xE01DF: 84,
+ 0xE01E0: 84,
+ 0xE01E1: 84,
+ 0xE01E2: 84,
+ 0xE01E3: 84,
+ 0xE01E4: 84,
+ 0xE01E5: 84,
+ 0xE01E6: 84,
+ 0xE01E7: 84,
+ 0xE01E8: 84,
+ 0xE01E9: 84,
+ 0xE01EA: 84,
+ 0xE01EB: 84,
+ 0xE01EC: 84,
+ 0xE01ED: 84,
+ 0xE01EE: 84,
+ 0xE01EF: 84,
+}
+codepoint_classes = {
+ "PVALID": (
+ 0x2D0000002E,
+ 0x300000003A,
+ 0x610000007B,
+ 0xDF000000F7,
+ 0xF800000100,
+ 0x10100000102,
+ 0x10300000104,
+ 0x10500000106,
+ 0x10700000108,
+ 0x1090000010A,
+ 0x10B0000010C,
+ 0x10D0000010E,
+ 0x10F00000110,
+ 0x11100000112,
+ 0x11300000114,
+ 0x11500000116,
+ 0x11700000118,
+ 0x1190000011A,
+ 0x11B0000011C,
+ 0x11D0000011E,
+ 0x11F00000120,
+ 0x12100000122,
+ 0x12300000124,
+ 0x12500000126,
+ 0x12700000128,
+ 0x1290000012A,
+ 0x12B0000012C,
+ 0x12D0000012E,
+ 0x12F00000130,
+ 0x13100000132,
+ 0x13500000136,
+ 0x13700000139,
+ 0x13A0000013B,
+ 0x13C0000013D,
+ 0x13E0000013F,
+ 0x14200000143,
+ 0x14400000145,
+ 0x14600000147,
+ 0x14800000149,
+ 0x14B0000014C,
+ 0x14D0000014E,
+ 0x14F00000150,
+ 0x15100000152,
+ 0x15300000154,
+ 0x15500000156,
+ 0x15700000158,
+ 0x1590000015A,
+ 0x15B0000015C,
+ 0x15D0000015E,
+ 0x15F00000160,
+ 0x16100000162,
+ 0x16300000164,
+ 0x16500000166,
+ 0x16700000168,
+ 0x1690000016A,
+ 0x16B0000016C,
+ 0x16D0000016E,
+ 0x16F00000170,
+ 0x17100000172,
+ 0x17300000174,
+ 0x17500000176,
+ 0x17700000178,
+ 0x17A0000017B,
+ 0x17C0000017D,
+ 0x17E0000017F,
+ 0x18000000181,
+ 0x18300000184,
+ 0x18500000186,
+ 0x18800000189,
+ 0x18C0000018E,
+ 0x19200000193,
+ 0x19500000196,
+ 0x1990000019C,
+ 0x19E0000019F,
+ 0x1A1000001A2,
+ 0x1A3000001A4,
+ 0x1A5000001A6,
+ 0x1A8000001A9,
+ 0x1AA000001AC,
+ 0x1AD000001AE,
+ 0x1B0000001B1,
+ 0x1B4000001B5,
+ 0x1B6000001B7,
+ 0x1B9000001BC,
+ 0x1BD000001C4,
+ 0x1CE000001CF,
+ 0x1D0000001D1,
+ 0x1D2000001D3,
+ 0x1D4000001D5,
+ 0x1D6000001D7,
+ 0x1D8000001D9,
+ 0x1DA000001DB,
+ 0x1DC000001DE,
+ 0x1DF000001E0,
+ 0x1E1000001E2,
+ 0x1E3000001E4,
+ 0x1E5000001E6,
+ 0x1E7000001E8,
+ 0x1E9000001EA,
+ 0x1EB000001EC,
+ 0x1ED000001EE,
+ 0x1EF000001F1,
+ 0x1F5000001F6,
+ 0x1F9000001FA,
+ 0x1FB000001FC,
+ 0x1FD000001FE,
+ 0x1FF00000200,
+ 0x20100000202,
+ 0x20300000204,
+ 0x20500000206,
+ 0x20700000208,
+ 0x2090000020A,
+ 0x20B0000020C,
+ 0x20D0000020E,
+ 0x20F00000210,
+ 0x21100000212,
+ 0x21300000214,
+ 0x21500000216,
+ 0x21700000218,
+ 0x2190000021A,
+ 0x21B0000021C,
+ 0x21D0000021E,
+ 0x21F00000220,
+ 0x22100000222,
+ 0x22300000224,
+ 0x22500000226,
+ 0x22700000228,
+ 0x2290000022A,
+ 0x22B0000022C,
+ 0x22D0000022E,
+ 0x22F00000230,
+ 0x23100000232,
+ 0x2330000023A,
+ 0x23C0000023D,
+ 0x23F00000241,
+ 0x24200000243,
+ 0x24700000248,
+ 0x2490000024A,
+ 0x24B0000024C,
+ 0x24D0000024E,
+ 0x24F000002B0,
+ 0x2B9000002C2,
+ 0x2C6000002D2,
+ 0x2EC000002ED,
+ 0x2EE000002EF,
+ 0x30000000340,
+ 0x34200000343,
+ 0x3460000034F,
+ 0x35000000370,
+ 0x37100000372,
+ 0x37300000374,
+ 0x37700000378,
+ 0x37B0000037E,
+ 0x39000000391,
+ 0x3AC000003CF,
+ 0x3D7000003D8,
+ 0x3D9000003DA,
+ 0x3DB000003DC,
+ 0x3DD000003DE,
+ 0x3DF000003E0,
+ 0x3E1000003E2,
+ 0x3E3000003E4,
+ 0x3E5000003E6,
+ 0x3E7000003E8,
+ 0x3E9000003EA,
+ 0x3EB000003EC,
+ 0x3ED000003EE,
+ 0x3EF000003F0,
+ 0x3F3000003F4,
+ 0x3F8000003F9,
+ 0x3FB000003FD,
+ 0x43000000460,
+ 0x46100000462,
+ 0x46300000464,
+ 0x46500000466,
+ 0x46700000468,
+ 0x4690000046A,
+ 0x46B0000046C,
+ 0x46D0000046E,
+ 0x46F00000470,
+ 0x47100000472,
+ 0x47300000474,
+ 0x47500000476,
+ 0x47700000478,
+ 0x4790000047A,
+ 0x47B0000047C,
+ 0x47D0000047E,
+ 0x47F00000480,
+ 0x48100000482,
+ 0x48300000488,
+ 0x48B0000048C,
+ 0x48D0000048E,
+ 0x48F00000490,
+ 0x49100000492,
+ 0x49300000494,
+ 0x49500000496,
+ 0x49700000498,
+ 0x4990000049A,
+ 0x49B0000049C,
+ 0x49D0000049E,
+ 0x49F000004A0,
+ 0x4A1000004A2,
+ 0x4A3000004A4,
+ 0x4A5000004A6,
+ 0x4A7000004A8,
+ 0x4A9000004AA,
+ 0x4AB000004AC,
+ 0x4AD000004AE,
+ 0x4AF000004B0,
+ 0x4B1000004B2,
+ 0x4B3000004B4,
+ 0x4B5000004B6,
+ 0x4B7000004B8,
+ 0x4B9000004BA,
+ 0x4BB000004BC,
+ 0x4BD000004BE,
+ 0x4BF000004C0,
+ 0x4C2000004C3,
+ 0x4C4000004C5,
+ 0x4C6000004C7,
+ 0x4C8000004C9,
+ 0x4CA000004CB,
+ 0x4CC000004CD,
+ 0x4CE000004D0,
+ 0x4D1000004D2,
+ 0x4D3000004D4,
+ 0x4D5000004D6,
+ 0x4D7000004D8,
+ 0x4D9000004DA,
+ 0x4DB000004DC,
+ 0x4DD000004DE,
+ 0x4DF000004E0,
+ 0x4E1000004E2,
+ 0x4E3000004E4,
+ 0x4E5000004E6,
+ 0x4E7000004E8,
+ 0x4E9000004EA,
+ 0x4EB000004EC,
+ 0x4ED000004EE,
+ 0x4EF000004F0,
+ 0x4F1000004F2,
+ 0x4F3000004F4,
+ 0x4F5000004F6,
+ 0x4F7000004F8,
+ 0x4F9000004FA,
+ 0x4FB000004FC,
+ 0x4FD000004FE,
+ 0x4FF00000500,
+ 0x50100000502,
+ 0x50300000504,
+ 0x50500000506,
+ 0x50700000508,
+ 0x5090000050A,
+ 0x50B0000050C,
+ 0x50D0000050E,
+ 0x50F00000510,
+ 0x51100000512,
+ 0x51300000514,
+ 0x51500000516,
+ 0x51700000518,
+ 0x5190000051A,
+ 0x51B0000051C,
+ 0x51D0000051E,
+ 0x51F00000520,
+ 0x52100000522,
+ 0x52300000524,
+ 0x52500000526,
+ 0x52700000528,
+ 0x5290000052A,
+ 0x52B0000052C,
+ 0x52D0000052E,
+ 0x52F00000530,
+ 0x5590000055A,
+ 0x56000000587,
+ 0x58800000589,
+ 0x591000005BE,
+ 0x5BF000005C0,
+ 0x5C1000005C3,
+ 0x5C4000005C6,
+ 0x5C7000005C8,
+ 0x5D0000005EB,
+ 0x5EF000005F3,
+ 0x6100000061B,
+ 0x62000000640,
+ 0x64100000660,
+ 0x66E00000675,
+ 0x679000006D4,
+ 0x6D5000006DD,
+ 0x6DF000006E9,
+ 0x6EA000006F0,
+ 0x6FA00000700,
+ 0x7100000074B,
+ 0x74D000007B2,
+ 0x7C0000007F6,
+ 0x7FD000007FE,
+ 0x8000000082E,
+ 0x8400000085C,
+ 0x8600000086B,
+ 0x87000000888,
+ 0x8890000088F,
+ 0x898000008E2,
+ 0x8E300000958,
+ 0x96000000964,
+ 0x96600000970,
+ 0x97100000984,
+ 0x9850000098D,
+ 0x98F00000991,
+ 0x993000009A9,
+ 0x9AA000009B1,
+ 0x9B2000009B3,
+ 0x9B6000009BA,
+ 0x9BC000009C5,
+ 0x9C7000009C9,
+ 0x9CB000009CF,
+ 0x9D7000009D8,
+ 0x9E0000009E4,
+ 0x9E6000009F2,
+ 0x9FC000009FD,
+ 0x9FE000009FF,
+ 0xA0100000A04,
+ 0xA0500000A0B,
+ 0xA0F00000A11,
+ 0xA1300000A29,
+ 0xA2A00000A31,
+ 0xA3200000A33,
+ 0xA3500000A36,
+ 0xA3800000A3A,
+ 0xA3C00000A3D,
+ 0xA3E00000A43,
+ 0xA4700000A49,
+ 0xA4B00000A4E,
+ 0xA5100000A52,
+ 0xA5C00000A5D,
+ 0xA6600000A76,
+ 0xA8100000A84,
+ 0xA8500000A8E,
+ 0xA8F00000A92,
+ 0xA9300000AA9,
+ 0xAAA00000AB1,
+ 0xAB200000AB4,
+ 0xAB500000ABA,
+ 0xABC00000AC6,
+ 0xAC700000ACA,
+ 0xACB00000ACE,
+ 0xAD000000AD1,
+ 0xAE000000AE4,
+ 0xAE600000AF0,
+ 0xAF900000B00,
+ 0xB0100000B04,
+ 0xB0500000B0D,
+ 0xB0F00000B11,
+ 0xB1300000B29,
+ 0xB2A00000B31,
+ 0xB3200000B34,
+ 0xB3500000B3A,
+ 0xB3C00000B45,
+ 0xB4700000B49,
+ 0xB4B00000B4E,
+ 0xB5500000B58,
+ 0xB5F00000B64,
+ 0xB6600000B70,
+ 0xB7100000B72,
+ 0xB8200000B84,
+ 0xB8500000B8B,
+ 0xB8E00000B91,
+ 0xB9200000B96,
+ 0xB9900000B9B,
+ 0xB9C00000B9D,
+ 0xB9E00000BA0,
+ 0xBA300000BA5,
+ 0xBA800000BAB,
+ 0xBAE00000BBA,
+ 0xBBE00000BC3,
+ 0xBC600000BC9,
+ 0xBCA00000BCE,
+ 0xBD000000BD1,
+ 0xBD700000BD8,
+ 0xBE600000BF0,
+ 0xC0000000C0D,
+ 0xC0E00000C11,
+ 0xC1200000C29,
+ 0xC2A00000C3A,
+ 0xC3C00000C45,
+ 0xC4600000C49,
+ 0xC4A00000C4E,
+ 0xC5500000C57,
+ 0xC5800000C5B,
+ 0xC5D00000C5E,
+ 0xC6000000C64,
+ 0xC6600000C70,
+ 0xC8000000C84,
+ 0xC8500000C8D,
+ 0xC8E00000C91,
+ 0xC9200000CA9,
+ 0xCAA00000CB4,
+ 0xCB500000CBA,
+ 0xCBC00000CC5,
+ 0xCC600000CC9,
+ 0xCCA00000CCE,
+ 0xCD500000CD7,
+ 0xCDD00000CDF,
+ 0xCE000000CE4,
+ 0xCE600000CF0,
+ 0xCF100000CF4,
+ 0xD0000000D0D,
+ 0xD0E00000D11,
+ 0xD1200000D45,
+ 0xD4600000D49,
+ 0xD4A00000D4F,
+ 0xD5400000D58,
+ 0xD5F00000D64,
+ 0xD6600000D70,
+ 0xD7A00000D80,
+ 0xD8100000D84,
+ 0xD8500000D97,
+ 0xD9A00000DB2,
+ 0xDB300000DBC,
+ 0xDBD00000DBE,
+ 0xDC000000DC7,
+ 0xDCA00000DCB,
+ 0xDCF00000DD5,
+ 0xDD600000DD7,
+ 0xDD800000DE0,
+ 0xDE600000DF0,
+ 0xDF200000DF4,
+ 0xE0100000E33,
+ 0xE3400000E3B,
+ 0xE4000000E4F,
+ 0xE5000000E5A,
+ 0xE8100000E83,
+ 0xE8400000E85,
+ 0xE8600000E8B,
+ 0xE8C00000EA4,
+ 0xEA500000EA6,
+ 0xEA700000EB3,
+ 0xEB400000EBE,
+ 0xEC000000EC5,
+ 0xEC600000EC7,
+ 0xEC800000ECF,
+ 0xED000000EDA,
+ 0xEDE00000EE0,
+ 0xF0000000F01,
+ 0xF0B00000F0C,
+ 0xF1800000F1A,
+ 0xF2000000F2A,
+ 0xF3500000F36,
+ 0xF3700000F38,
+ 0xF3900000F3A,
+ 0xF3E00000F43,
+ 0xF4400000F48,
+ 0xF4900000F4D,
+ 0xF4E00000F52,
+ 0xF5300000F57,
+ 0xF5800000F5C,
+ 0xF5D00000F69,
+ 0xF6A00000F6D,
+ 0xF7100000F73,
+ 0xF7400000F75,
+ 0xF7A00000F81,
+ 0xF8200000F85,
+ 0xF8600000F93,
+ 0xF9400000F98,
+ 0xF9900000F9D,
+ 0xF9E00000FA2,
+ 0xFA300000FA7,
+ 0xFA800000FAC,
+ 0xFAD00000FB9,
+ 0xFBA00000FBD,
+ 0xFC600000FC7,
+ 0x10000000104A,
+ 0x10500000109E,
+ 0x10D0000010FB,
+ 0x10FD00001100,
+ 0x120000001249,
+ 0x124A0000124E,
+ 0x125000001257,
+ 0x125800001259,
+ 0x125A0000125E,
+ 0x126000001289,
+ 0x128A0000128E,
+ 0x1290000012B1,
+ 0x12B2000012B6,
+ 0x12B8000012BF,
+ 0x12C0000012C1,
+ 0x12C2000012C6,
+ 0x12C8000012D7,
+ 0x12D800001311,
+ 0x131200001316,
+ 0x13180000135B,
+ 0x135D00001360,
+ 0x138000001390,
+ 0x13A0000013F6,
+ 0x14010000166D,
+ 0x166F00001680,
+ 0x16810000169B,
+ 0x16A0000016EB,
+ 0x16F1000016F9,
+ 0x170000001716,
+ 0x171F00001735,
+ 0x174000001754,
+ 0x17600000176D,
+ 0x176E00001771,
+ 0x177200001774,
+ 0x1780000017B4,
+ 0x17B6000017D4,
+ 0x17D7000017D8,
+ 0x17DC000017DE,
+ 0x17E0000017EA,
+ 0x18100000181A,
+ 0x182000001879,
+ 0x1880000018AB,
+ 0x18B0000018F6,
+ 0x19000000191F,
+ 0x19200000192C,
+ 0x19300000193C,
+ 0x19460000196E,
+ 0x197000001975,
+ 0x1980000019AC,
+ 0x19B0000019CA,
+ 0x19D0000019DA,
+ 0x1A0000001A1C,
+ 0x1A2000001A5F,
+ 0x1A6000001A7D,
+ 0x1A7F00001A8A,
+ 0x1A9000001A9A,
+ 0x1AA700001AA8,
+ 0x1AB000001ABE,
+ 0x1ABF00001ACF,
+ 0x1B0000001B4D,
+ 0x1B5000001B5A,
+ 0x1B6B00001B74,
+ 0x1B8000001BF4,
+ 0x1C0000001C38,
+ 0x1C4000001C4A,
+ 0x1C4D00001C7E,
+ 0x1CD000001CD3,
+ 0x1CD400001CFB,
+ 0x1D0000001D2C,
+ 0x1D2F00001D30,
+ 0x1D3B00001D3C,
+ 0x1D4E00001D4F,
+ 0x1D6B00001D78,
+ 0x1D7900001D9B,
+ 0x1DC000001E00,
+ 0x1E0100001E02,
+ 0x1E0300001E04,
+ 0x1E0500001E06,
+ 0x1E0700001E08,
+ 0x1E0900001E0A,
+ 0x1E0B00001E0C,
+ 0x1E0D00001E0E,
+ 0x1E0F00001E10,
+ 0x1E1100001E12,
+ 0x1E1300001E14,
+ 0x1E1500001E16,
+ 0x1E1700001E18,
+ 0x1E1900001E1A,
+ 0x1E1B00001E1C,
+ 0x1E1D00001E1E,
+ 0x1E1F00001E20,
+ 0x1E2100001E22,
+ 0x1E2300001E24,
+ 0x1E2500001E26,
+ 0x1E2700001E28,
+ 0x1E2900001E2A,
+ 0x1E2B00001E2C,
+ 0x1E2D00001E2E,
+ 0x1E2F00001E30,
+ 0x1E3100001E32,
+ 0x1E3300001E34,
+ 0x1E3500001E36,
+ 0x1E3700001E38,
+ 0x1E3900001E3A,
+ 0x1E3B00001E3C,
+ 0x1E3D00001E3E,
+ 0x1E3F00001E40,
+ 0x1E4100001E42,
+ 0x1E4300001E44,
+ 0x1E4500001E46,
+ 0x1E4700001E48,
+ 0x1E4900001E4A,
+ 0x1E4B00001E4C,
+ 0x1E4D00001E4E,
+ 0x1E4F00001E50,
+ 0x1E5100001E52,
+ 0x1E5300001E54,
+ 0x1E5500001E56,
+ 0x1E5700001E58,
+ 0x1E5900001E5A,
+ 0x1E5B00001E5C,
+ 0x1E5D00001E5E,
+ 0x1E5F00001E60,
+ 0x1E6100001E62,
+ 0x1E6300001E64,
+ 0x1E6500001E66,
+ 0x1E6700001E68,
+ 0x1E6900001E6A,
+ 0x1E6B00001E6C,
+ 0x1E6D00001E6E,
+ 0x1E6F00001E70,
+ 0x1E7100001E72,
+ 0x1E7300001E74,
+ 0x1E7500001E76,
+ 0x1E7700001E78,
+ 0x1E7900001E7A,
+ 0x1E7B00001E7C,
+ 0x1E7D00001E7E,
+ 0x1E7F00001E80,
+ 0x1E8100001E82,
+ 0x1E8300001E84,
+ 0x1E8500001E86,
+ 0x1E8700001E88,
+ 0x1E8900001E8A,
+ 0x1E8B00001E8C,
+ 0x1E8D00001E8E,
+ 0x1E8F00001E90,
+ 0x1E9100001E92,
+ 0x1E9300001E94,
+ 0x1E9500001E9A,
+ 0x1E9C00001E9E,
+ 0x1E9F00001EA0,
+ 0x1EA100001EA2,
+ 0x1EA300001EA4,
+ 0x1EA500001EA6,
+ 0x1EA700001EA8,
+ 0x1EA900001EAA,
+ 0x1EAB00001EAC,
+ 0x1EAD00001EAE,
+ 0x1EAF00001EB0,
+ 0x1EB100001EB2,
+ 0x1EB300001EB4,
+ 0x1EB500001EB6,
+ 0x1EB700001EB8,
+ 0x1EB900001EBA,
+ 0x1EBB00001EBC,
+ 0x1EBD00001EBE,
+ 0x1EBF00001EC0,
+ 0x1EC100001EC2,
+ 0x1EC300001EC4,
+ 0x1EC500001EC6,
+ 0x1EC700001EC8,
+ 0x1EC900001ECA,
+ 0x1ECB00001ECC,
+ 0x1ECD00001ECE,
+ 0x1ECF00001ED0,
+ 0x1ED100001ED2,
+ 0x1ED300001ED4,
+ 0x1ED500001ED6,
+ 0x1ED700001ED8,
+ 0x1ED900001EDA,
+ 0x1EDB00001EDC,
+ 0x1EDD00001EDE,
+ 0x1EDF00001EE0,
+ 0x1EE100001EE2,
+ 0x1EE300001EE4,
+ 0x1EE500001EE6,
+ 0x1EE700001EE8,
+ 0x1EE900001EEA,
+ 0x1EEB00001EEC,
+ 0x1EED00001EEE,
+ 0x1EEF00001EF0,
+ 0x1EF100001EF2,
+ 0x1EF300001EF4,
+ 0x1EF500001EF6,
+ 0x1EF700001EF8,
+ 0x1EF900001EFA,
+ 0x1EFB00001EFC,
+ 0x1EFD00001EFE,
+ 0x1EFF00001F08,
+ 0x1F1000001F16,
+ 0x1F2000001F28,
+ 0x1F3000001F38,
+ 0x1F4000001F46,
+ 0x1F5000001F58,
+ 0x1F6000001F68,
+ 0x1F7000001F71,
+ 0x1F7200001F73,
+ 0x1F7400001F75,
+ 0x1F7600001F77,
+ 0x1F7800001F79,
+ 0x1F7A00001F7B,
+ 0x1F7C00001F7D,
+ 0x1FB000001FB2,
+ 0x1FB600001FB7,
+ 0x1FC600001FC7,
+ 0x1FD000001FD3,
+ 0x1FD600001FD8,
+ 0x1FE000001FE3,
+ 0x1FE400001FE8,
+ 0x1FF600001FF7,
+ 0x214E0000214F,
+ 0x218400002185,
+ 0x2C3000002C60,
+ 0x2C6100002C62,
+ 0x2C6500002C67,
+ 0x2C6800002C69,
+ 0x2C6A00002C6B,
+ 0x2C6C00002C6D,
+ 0x2C7100002C72,
+ 0x2C7300002C75,
+ 0x2C7600002C7C,
+ 0x2C8100002C82,
+ 0x2C8300002C84,
+ 0x2C8500002C86,
+ 0x2C8700002C88,
+ 0x2C8900002C8A,
+ 0x2C8B00002C8C,
+ 0x2C8D00002C8E,
+ 0x2C8F00002C90,
+ 0x2C9100002C92,
+ 0x2C9300002C94,
+ 0x2C9500002C96,
+ 0x2C9700002C98,
+ 0x2C9900002C9A,
+ 0x2C9B00002C9C,
+ 0x2C9D00002C9E,
+ 0x2C9F00002CA0,
+ 0x2CA100002CA2,
+ 0x2CA300002CA4,
+ 0x2CA500002CA6,
+ 0x2CA700002CA8,
+ 0x2CA900002CAA,
+ 0x2CAB00002CAC,
+ 0x2CAD00002CAE,
+ 0x2CAF00002CB0,
+ 0x2CB100002CB2,
+ 0x2CB300002CB4,
+ 0x2CB500002CB6,
+ 0x2CB700002CB8,
+ 0x2CB900002CBA,
+ 0x2CBB00002CBC,
+ 0x2CBD00002CBE,
+ 0x2CBF00002CC0,
+ 0x2CC100002CC2,
+ 0x2CC300002CC4,
+ 0x2CC500002CC6,
+ 0x2CC700002CC8,
+ 0x2CC900002CCA,
+ 0x2CCB00002CCC,
+ 0x2CCD00002CCE,
+ 0x2CCF00002CD0,
+ 0x2CD100002CD2,
+ 0x2CD300002CD4,
+ 0x2CD500002CD6,
+ 0x2CD700002CD8,
+ 0x2CD900002CDA,
+ 0x2CDB00002CDC,
+ 0x2CDD00002CDE,
+ 0x2CDF00002CE0,
+ 0x2CE100002CE2,
+ 0x2CE300002CE5,
+ 0x2CEC00002CED,
+ 0x2CEE00002CF2,
+ 0x2CF300002CF4,
+ 0x2D0000002D26,
+ 0x2D2700002D28,
+ 0x2D2D00002D2E,
+ 0x2D3000002D68,
+ 0x2D7F00002D97,
+ 0x2DA000002DA7,
+ 0x2DA800002DAF,
+ 0x2DB000002DB7,
+ 0x2DB800002DBF,
+ 0x2DC000002DC7,
+ 0x2DC800002DCF,
+ 0x2DD000002DD7,
+ 0x2DD800002DDF,
+ 0x2DE000002E00,
+ 0x2E2F00002E30,
+ 0x300500003008,
+ 0x302A0000302E,
+ 0x303C0000303D,
+ 0x304100003097,
+ 0x30990000309B,
+ 0x309D0000309F,
+ 0x30A1000030FB,
+ 0x30FC000030FF,
+ 0x310500003130,
+ 0x31A0000031C0,
+ 0x31F000003200,
+ 0x340000004DC0,
+ 0x4E000000A48D,
+ 0xA4D00000A4FE,
+ 0xA5000000A60D,
+ 0xA6100000A62C,
+ 0xA6410000A642,
+ 0xA6430000A644,
+ 0xA6450000A646,
+ 0xA6470000A648,
+ 0xA6490000A64A,
+ 0xA64B0000A64C,
+ 0xA64D0000A64E,
+ 0xA64F0000A650,
+ 0xA6510000A652,
+ 0xA6530000A654,
+ 0xA6550000A656,
+ 0xA6570000A658,
+ 0xA6590000A65A,
+ 0xA65B0000A65C,
+ 0xA65D0000A65E,
+ 0xA65F0000A660,
+ 0xA6610000A662,
+ 0xA6630000A664,
+ 0xA6650000A666,
+ 0xA6670000A668,
+ 0xA6690000A66A,
+ 0xA66B0000A66C,
+ 0xA66D0000A670,
+ 0xA6740000A67E,
+ 0xA67F0000A680,
+ 0xA6810000A682,
+ 0xA6830000A684,
+ 0xA6850000A686,
+ 0xA6870000A688,
+ 0xA6890000A68A,
+ 0xA68B0000A68C,
+ 0xA68D0000A68E,
+ 0xA68F0000A690,
+ 0xA6910000A692,
+ 0xA6930000A694,
+ 0xA6950000A696,
+ 0xA6970000A698,
+ 0xA6990000A69A,
+ 0xA69B0000A69C,
+ 0xA69E0000A6E6,
+ 0xA6F00000A6F2,
+ 0xA7170000A720,
+ 0xA7230000A724,
+ 0xA7250000A726,
+ 0xA7270000A728,
+ 0xA7290000A72A,
+ 0xA72B0000A72C,
+ 0xA72D0000A72E,
+ 0xA72F0000A732,
+ 0xA7330000A734,
+ 0xA7350000A736,
+ 0xA7370000A738,
+ 0xA7390000A73A,
+ 0xA73B0000A73C,
+ 0xA73D0000A73E,
+ 0xA73F0000A740,
+ 0xA7410000A742,
+ 0xA7430000A744,
+ 0xA7450000A746,
+ 0xA7470000A748,
+ 0xA7490000A74A,
+ 0xA74B0000A74C,
+ 0xA74D0000A74E,
+ 0xA74F0000A750,
+ 0xA7510000A752,
+ 0xA7530000A754,
+ 0xA7550000A756,
+ 0xA7570000A758,
+ 0xA7590000A75A,
+ 0xA75B0000A75C,
+ 0xA75D0000A75E,
+ 0xA75F0000A760,
+ 0xA7610000A762,
+ 0xA7630000A764,
+ 0xA7650000A766,
+ 0xA7670000A768,
+ 0xA7690000A76A,
+ 0xA76B0000A76C,
+ 0xA76D0000A76E,
+ 0xA76F0000A770,
+ 0xA7710000A779,
+ 0xA77A0000A77B,
+ 0xA77C0000A77D,
+ 0xA77F0000A780,
+ 0xA7810000A782,
+ 0xA7830000A784,
+ 0xA7850000A786,
+ 0xA7870000A789,
+ 0xA78C0000A78D,
+ 0xA78E0000A790,
+ 0xA7910000A792,
+ 0xA7930000A796,
+ 0xA7970000A798,
+ 0xA7990000A79A,
+ 0xA79B0000A79C,
+ 0xA79D0000A79E,
+ 0xA79F0000A7A0,
+ 0xA7A10000A7A2,
+ 0xA7A30000A7A4,
+ 0xA7A50000A7A6,
+ 0xA7A70000A7A8,
+ 0xA7A90000A7AA,
+ 0xA7AF0000A7B0,
+ 0xA7B50000A7B6,
+ 0xA7B70000A7B8,
+ 0xA7B90000A7BA,
+ 0xA7BB0000A7BC,
+ 0xA7BD0000A7BE,
+ 0xA7BF0000A7C0,
+ 0xA7C10000A7C2,
+ 0xA7C30000A7C4,
+ 0xA7C80000A7C9,
+ 0xA7CA0000A7CB,
+ 0xA7D10000A7D2,
+ 0xA7D30000A7D4,
+ 0xA7D50000A7D6,
+ 0xA7D70000A7D8,
+ 0xA7D90000A7DA,
+ 0xA7F60000A7F8,
+ 0xA7FA0000A828,
+ 0xA82C0000A82D,
+ 0xA8400000A874,
+ 0xA8800000A8C6,
+ 0xA8D00000A8DA,
+ 0xA8E00000A8F8,
+ 0xA8FB0000A8FC,
+ 0xA8FD0000A92E,
+ 0xA9300000A954,
+ 0xA9800000A9C1,
+ 0xA9CF0000A9DA,
+ 0xA9E00000A9FF,
+ 0xAA000000AA37,
+ 0xAA400000AA4E,
+ 0xAA500000AA5A,
+ 0xAA600000AA77,
+ 0xAA7A0000AAC3,
+ 0xAADB0000AADE,
+ 0xAAE00000AAF0,
+ 0xAAF20000AAF7,
+ 0xAB010000AB07,
+ 0xAB090000AB0F,
+ 0xAB110000AB17,
+ 0xAB200000AB27,
+ 0xAB280000AB2F,
+ 0xAB300000AB5B,
+ 0xAB600000AB69,
+ 0xABC00000ABEB,
+ 0xABEC0000ABEE,
+ 0xABF00000ABFA,
+ 0xAC000000D7A4,
+ 0xFA0E0000FA10,
+ 0xFA110000FA12,
+ 0xFA130000FA15,
+ 0xFA1F0000FA20,
+ 0xFA210000FA22,
+ 0xFA230000FA25,
+ 0xFA270000FA2A,
+ 0xFB1E0000FB1F,
+ 0xFE200000FE30,
+ 0xFE730000FE74,
+ 0x100000001000C,
+ 0x1000D00010027,
+ 0x100280001003B,
+ 0x1003C0001003E,
+ 0x1003F0001004E,
+ 0x100500001005E,
+ 0x10080000100FB,
+ 0x101FD000101FE,
+ 0x102800001029D,
+ 0x102A0000102D1,
+ 0x102E0000102E1,
+ 0x1030000010320,
+ 0x1032D00010341,
+ 0x103420001034A,
+ 0x103500001037B,
+ 0x103800001039E,
+ 0x103A0000103C4,
+ 0x103C8000103D0,
+ 0x104280001049E,
+ 0x104A0000104AA,
+ 0x104D8000104FC,
+ 0x1050000010528,
+ 0x1053000010564,
+ 0x10597000105A2,
+ 0x105A3000105B2,
+ 0x105B3000105BA,
+ 0x105BB000105BD,
+ 0x1060000010737,
+ 0x1074000010756,
+ 0x1076000010768,
+ 0x1078000010781,
+ 0x1080000010806,
+ 0x1080800010809,
+ 0x1080A00010836,
+ 0x1083700010839,
+ 0x1083C0001083D,
+ 0x1083F00010856,
+ 0x1086000010877,
+ 0x108800001089F,
+ 0x108E0000108F3,
+ 0x108F4000108F6,
+ 0x1090000010916,
+ 0x109200001093A,
+ 0x10980000109B8,
+ 0x109BE000109C0,
+ 0x10A0000010A04,
+ 0x10A0500010A07,
+ 0x10A0C00010A14,
+ 0x10A1500010A18,
+ 0x10A1900010A36,
+ 0x10A3800010A3B,
+ 0x10A3F00010A40,
+ 0x10A6000010A7D,
+ 0x10A8000010A9D,
+ 0x10AC000010AC8,
+ 0x10AC900010AE7,
+ 0x10B0000010B36,
+ 0x10B4000010B56,
+ 0x10B6000010B73,
+ 0x10B8000010B92,
+ 0x10C0000010C49,
+ 0x10CC000010CF3,
+ 0x10D0000010D28,
+ 0x10D3000010D3A,
+ 0x10E8000010EAA,
+ 0x10EAB00010EAD,
+ 0x10EB000010EB2,
+ 0x10EFD00010F1D,
+ 0x10F2700010F28,
+ 0x10F3000010F51,
+ 0x10F7000010F86,
+ 0x10FB000010FC5,
+ 0x10FE000010FF7,
+ 0x1100000011047,
+ 0x1106600011076,
+ 0x1107F000110BB,
+ 0x110C2000110C3,
+ 0x110D0000110E9,
+ 0x110F0000110FA,
+ 0x1110000011135,
+ 0x1113600011140,
+ 0x1114400011148,
+ 0x1115000011174,
+ 0x1117600011177,
+ 0x11180000111C5,
+ 0x111C9000111CD,
+ 0x111CE000111DB,
+ 0x111DC000111DD,
+ 0x1120000011212,
+ 0x1121300011238,
+ 0x1123E00011242,
+ 0x1128000011287,
+ 0x1128800011289,
+ 0x1128A0001128E,
+ 0x1128F0001129E,
+ 0x1129F000112A9,
+ 0x112B0000112EB,
+ 0x112F0000112FA,
+ 0x1130000011304,
+ 0x113050001130D,
+ 0x1130F00011311,
+ 0x1131300011329,
+ 0x1132A00011331,
+ 0x1133200011334,
+ 0x113350001133A,
+ 0x1133B00011345,
+ 0x1134700011349,
+ 0x1134B0001134E,
+ 0x1135000011351,
+ 0x1135700011358,
+ 0x1135D00011364,
+ 0x113660001136D,
+ 0x1137000011375,
+ 0x114000001144B,
+ 0x114500001145A,
+ 0x1145E00011462,
+ 0x11480000114C6,
+ 0x114C7000114C8,
+ 0x114D0000114DA,
+ 0x11580000115B6,
+ 0x115B8000115C1,
+ 0x115D8000115DE,
+ 0x1160000011641,
+ 0x1164400011645,
+ 0x116500001165A,
+ 0x11680000116B9,
+ 0x116C0000116CA,
+ 0x117000001171B,
+ 0x1171D0001172C,
+ 0x117300001173A,
+ 0x1174000011747,
+ 0x118000001183B,
+ 0x118C0000118EA,
+ 0x118FF00011907,
+ 0x119090001190A,
+ 0x1190C00011914,
+ 0x1191500011917,
+ 0x1191800011936,
+ 0x1193700011939,
+ 0x1193B00011944,
+ 0x119500001195A,
+ 0x119A0000119A8,
+ 0x119AA000119D8,
+ 0x119DA000119E2,
+ 0x119E3000119E5,
+ 0x11A0000011A3F,
+ 0x11A4700011A48,
+ 0x11A5000011A9A,
+ 0x11A9D00011A9E,
+ 0x11AB000011AF9,
+ 0x11C0000011C09,
+ 0x11C0A00011C37,
+ 0x11C3800011C41,
+ 0x11C5000011C5A,
+ 0x11C7200011C90,
+ 0x11C9200011CA8,
+ 0x11CA900011CB7,
+ 0x11D0000011D07,
+ 0x11D0800011D0A,
+ 0x11D0B00011D37,
+ 0x11D3A00011D3B,
+ 0x11D3C00011D3E,
+ 0x11D3F00011D48,
+ 0x11D5000011D5A,
+ 0x11D6000011D66,
+ 0x11D6700011D69,
+ 0x11D6A00011D8F,
+ 0x11D9000011D92,
+ 0x11D9300011D99,
+ 0x11DA000011DAA,
+ 0x11EE000011EF7,
+ 0x11F0000011F11,
+ 0x11F1200011F3B,
+ 0x11F3E00011F43,
+ 0x11F5000011F5A,
+ 0x11FB000011FB1,
+ 0x120000001239A,
+ 0x1248000012544,
+ 0x12F9000012FF1,
+ 0x1300000013430,
+ 0x1344000013456,
+ 0x1440000014647,
+ 0x1680000016A39,
+ 0x16A4000016A5F,
+ 0x16A6000016A6A,
+ 0x16A7000016ABF,
+ 0x16AC000016ACA,
+ 0x16AD000016AEE,
+ 0x16AF000016AF5,
+ 0x16B0000016B37,
+ 0x16B4000016B44,
+ 0x16B5000016B5A,
+ 0x16B6300016B78,
+ 0x16B7D00016B90,
+ 0x16E6000016E80,
+ 0x16F0000016F4B,
+ 0x16F4F00016F88,
+ 0x16F8F00016FA0,
+ 0x16FE000016FE2,
+ 0x16FE300016FE5,
+ 0x16FF000016FF2,
+ 0x17000000187F8,
+ 0x1880000018CD6,
+ 0x18D0000018D09,
+ 0x1AFF00001AFF4,
+ 0x1AFF50001AFFC,
+ 0x1AFFD0001AFFF,
+ 0x1B0000001B123,
+ 0x1B1320001B133,
+ 0x1B1500001B153,
+ 0x1B1550001B156,
+ 0x1B1640001B168,
+ 0x1B1700001B2FC,
+ 0x1BC000001BC6B,
+ 0x1BC700001BC7D,
+ 0x1BC800001BC89,
+ 0x1BC900001BC9A,
+ 0x1BC9D0001BC9F,
+ 0x1CF000001CF2E,
+ 0x1CF300001CF47,
+ 0x1DA000001DA37,
+ 0x1DA3B0001DA6D,
+ 0x1DA750001DA76,
+ 0x1DA840001DA85,
+ 0x1DA9B0001DAA0,
+ 0x1DAA10001DAB0,
+ 0x1DF000001DF1F,
+ 0x1DF250001DF2B,
+ 0x1E0000001E007,
+ 0x1E0080001E019,
+ 0x1E01B0001E022,
+ 0x1E0230001E025,
+ 0x1E0260001E02B,
+ 0x1E08F0001E090,
+ 0x1E1000001E12D,
+ 0x1E1300001E13E,
+ 0x1E1400001E14A,
+ 0x1E14E0001E14F,
+ 0x1E2900001E2AF,
+ 0x1E2C00001E2FA,
+ 0x1E4D00001E4FA,
+ 0x1E7E00001E7E7,
+ 0x1E7E80001E7EC,
+ 0x1E7ED0001E7EF,
+ 0x1E7F00001E7FF,
+ 0x1E8000001E8C5,
+ 0x1E8D00001E8D7,
+ 0x1E9220001E94C,
+ 0x1E9500001E95A,
+ 0x200000002A6E0,
+ 0x2A7000002B73A,
+ 0x2B7400002B81E,
+ 0x2B8200002CEA2,
+ 0x2CEB00002EBE1,
+ 0x2EBF00002EE5E,
+ 0x300000003134B,
+ 0x31350000323B0,
+ ),
+ "CONTEXTJ": (0x200C0000200E,),
+ "CONTEXTO": (
+ 0xB7000000B8,
+ 0x37500000376,
+ 0x5F3000005F5,
+ 0x6600000066A,
+ 0x6F0000006FA,
+ 0x30FB000030FC,
+ ),
+}
diff --git a/testcline/lib/python3.12/site-packages/idna/intranges.py b/testcline/lib/python3.12/site-packages/idna/intranges.py
new file mode 100644
index 0000000..7bfaa8d
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna/intranges.py
@@ -0,0 +1,57 @@
+"""
+Given a list of integers, made up of (hopefully) a small number of long runs
+of consecutive integers, compute a representation of the form
+((start1, end1), (start2, end2) ...). Then answer the question "was x present
+in the original list?" in time O(log(# runs)).
+"""
+
+import bisect
+from typing import List, Tuple
+
+
+def intranges_from_list(list_: List[int]) -> Tuple[int, ...]:
+ """Represent a list of integers as a sequence of ranges:
+ ((start_0, end_0), (start_1, end_1), ...), such that the original
+ integers are exactly those x such that start_i <= x < end_i for some i.
+
+ Ranges are encoded as single integers (start << 32 | end), not as tuples.
+ """
+
+ sorted_list = sorted(list_)
+ ranges = []
+ last_write = -1
+ for i in range(len(sorted_list)):
+ if i + 1 < len(sorted_list):
+ if sorted_list[i] == sorted_list[i + 1] - 1:
+ continue
+ current_range = sorted_list[last_write + 1 : i + 1]
+ ranges.append(_encode_range(current_range[0], current_range[-1] + 1))
+ last_write = i
+
+ return tuple(ranges)
+
+
+def _encode_range(start: int, end: int) -> int:
+ return (start << 32) | end
+
+
+def _decode_range(r: int) -> Tuple[int, int]:
+ return (r >> 32), (r & ((1 << 32) - 1))
+
+
+def intranges_contain(int_: int, ranges: Tuple[int, ...]) -> bool:
+ """Determine if `int_` falls into one of the ranges in `ranges`."""
+ tuple_ = _encode_range(int_, 0)
+ pos = bisect.bisect_left(ranges, tuple_)
+ # we could be immediately ahead of a tuple (start, end)
+ # with start < int_ <= end
+ if pos > 0:
+ left, right = _decode_range(ranges[pos - 1])
+ if left <= int_ < right:
+ return True
+ # or we could be immediately behind a tuple (int_, end)
+ if pos < len(ranges):
+ left, _ = _decode_range(ranges[pos])
+ if left == int_:
+ return True
+ return False
diff --git a/testcline/lib/python3.12/site-packages/idna/package_data.py b/testcline/lib/python3.12/site-packages/idna/package_data.py
new file mode 100644
index 0000000..514ff7e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna/package_data.py
@@ -0,0 +1 @@
+__version__ = "3.10"
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/__init__.py b/testcline/lib/python3.12/site-packages/idna/py.typed
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/__init__.py
rename to testcline/lib/python3.12/site-packages/idna/py.typed
diff --git a/testcline/lib/python3.12/site-packages/idna/uts46data.py b/testcline/lib/python3.12/site-packages/idna/uts46data.py
new file mode 100644
index 0000000..eb89432
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/idna/uts46data.py
@@ -0,0 +1,8681 @@
+# This file is automatically generated by tools/idna-data
+# vim: set fileencoding=utf-8 :
+
+from typing import List, Tuple, Union
+
+"""IDNA Mapping Table from UTS46."""
+
+
+__version__ = "15.1.0"
+
+
+def _seg_0() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x0, "3"),
+ (0x1, "3"),
+ (0x2, "3"),
+ (0x3, "3"),
+ (0x4, "3"),
+ (0x5, "3"),
+ (0x6, "3"),
+ (0x7, "3"),
+ (0x8, "3"),
+ (0x9, "3"),
+ (0xA, "3"),
+ (0xB, "3"),
+ (0xC, "3"),
+ (0xD, "3"),
+ (0xE, "3"),
+ (0xF, "3"),
+ (0x10, "3"),
+ (0x11, "3"),
+ (0x12, "3"),
+ (0x13, "3"),
+ (0x14, "3"),
+ (0x15, "3"),
+ (0x16, "3"),
+ (0x17, "3"),
+ (0x18, "3"),
+ (0x19, "3"),
+ (0x1A, "3"),
+ (0x1B, "3"),
+ (0x1C, "3"),
+ (0x1D, "3"),
+ (0x1E, "3"),
+ (0x1F, "3"),
+ (0x20, "3"),
+ (0x21, "3"),
+ (0x22, "3"),
+ (0x23, "3"),
+ (0x24, "3"),
+ (0x25, "3"),
+ (0x26, "3"),
+ (0x27, "3"),
+ (0x28, "3"),
+ (0x29, "3"),
+ (0x2A, "3"),
+ (0x2B, "3"),
+ (0x2C, "3"),
+ (0x2D, "V"),
+ (0x2E, "V"),
+ (0x2F, "3"),
+ (0x30, "V"),
+ (0x31, "V"),
+ (0x32, "V"),
+ (0x33, "V"),
+ (0x34, "V"),
+ (0x35, "V"),
+ (0x36, "V"),
+ (0x37, "V"),
+ (0x38, "V"),
+ (0x39, "V"),
+ (0x3A, "3"),
+ (0x3B, "3"),
+ (0x3C, "3"),
+ (0x3D, "3"),
+ (0x3E, "3"),
+ (0x3F, "3"),
+ (0x40, "3"),
+ (0x41, "M", "a"),
+ (0x42, "M", "b"),
+ (0x43, "M", "c"),
+ (0x44, "M", "d"),
+ (0x45, "M", "e"),
+ (0x46, "M", "f"),
+ (0x47, "M", "g"),
+ (0x48, "M", "h"),
+ (0x49, "M", "i"),
+ (0x4A, "M", "j"),
+ (0x4B, "M", "k"),
+ (0x4C, "M", "l"),
+ (0x4D, "M", "m"),
+ (0x4E, "M", "n"),
+ (0x4F, "M", "o"),
+ (0x50, "M", "p"),
+ (0x51, "M", "q"),
+ (0x52, "M", "r"),
+ (0x53, "M", "s"),
+ (0x54, "M", "t"),
+ (0x55, "M", "u"),
+ (0x56, "M", "v"),
+ (0x57, "M", "w"),
+ (0x58, "M", "x"),
+ (0x59, "M", "y"),
+ (0x5A, "M", "z"),
+ (0x5B, "3"),
+ (0x5C, "3"),
+ (0x5D, "3"),
+ (0x5E, "3"),
+ (0x5F, "3"),
+ (0x60, "3"),
+ (0x61, "V"),
+ (0x62, "V"),
+ (0x63, "V"),
+ ]
+
+
+def _seg_1() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x64, "V"),
+ (0x65, "V"),
+ (0x66, "V"),
+ (0x67, "V"),
+ (0x68, "V"),
+ (0x69, "V"),
+ (0x6A, "V"),
+ (0x6B, "V"),
+ (0x6C, "V"),
+ (0x6D, "V"),
+ (0x6E, "V"),
+ (0x6F, "V"),
+ (0x70, "V"),
+ (0x71, "V"),
+ (0x72, "V"),
+ (0x73, "V"),
+ (0x74, "V"),
+ (0x75, "V"),
+ (0x76, "V"),
+ (0x77, "V"),
+ (0x78, "V"),
+ (0x79, "V"),
+ (0x7A, "V"),
+ (0x7B, "3"),
+ (0x7C, "3"),
+ (0x7D, "3"),
+ (0x7E, "3"),
+ (0x7F, "3"),
+ (0x80, "X"),
+ (0x81, "X"),
+ (0x82, "X"),
+ (0x83, "X"),
+ (0x84, "X"),
+ (0x85, "X"),
+ (0x86, "X"),
+ (0x87, "X"),
+ (0x88, "X"),
+ (0x89, "X"),
+ (0x8A, "X"),
+ (0x8B, "X"),
+ (0x8C, "X"),
+ (0x8D, "X"),
+ (0x8E, "X"),
+ (0x8F, "X"),
+ (0x90, "X"),
+ (0x91, "X"),
+ (0x92, "X"),
+ (0x93, "X"),
+ (0x94, "X"),
+ (0x95, "X"),
+ (0x96, "X"),
+ (0x97, "X"),
+ (0x98, "X"),
+ (0x99, "X"),
+ (0x9A, "X"),
+ (0x9B, "X"),
+ (0x9C, "X"),
+ (0x9D, "X"),
+ (0x9E, "X"),
+ (0x9F, "X"),
+ (0xA0, "3", " "),
+ (0xA1, "V"),
+ (0xA2, "V"),
+ (0xA3, "V"),
+ (0xA4, "V"),
+ (0xA5, "V"),
+ (0xA6, "V"),
+ (0xA7, "V"),
+ (0xA8, "3", " ̈"),
+ (0xA9, "V"),
+ (0xAA, "M", "a"),
+ (0xAB, "V"),
+ (0xAC, "V"),
+ (0xAD, "I"),
+ (0xAE, "V"),
+ (0xAF, "3", " ̄"),
+ (0xB0, "V"),
+ (0xB1, "V"),
+ (0xB2, "M", "2"),
+ (0xB3, "M", "3"),
+ (0xB4, "3", " ́"),
+ (0xB5, "M", "μ"),
+ (0xB6, "V"),
+ (0xB7, "V"),
+ (0xB8, "3", " ̧"),
+ (0xB9, "M", "1"),
+ (0xBA, "M", "o"),
+ (0xBB, "V"),
+ (0xBC, "M", "1⁄4"),
+ (0xBD, "M", "1⁄2"),
+ (0xBE, "M", "3⁄4"),
+ (0xBF, "V"),
+ (0xC0, "M", "à"),
+ (0xC1, "M", "á"),
+ (0xC2, "M", "â"),
+ (0xC3, "M", "ã"),
+ (0xC4, "M", "ä"),
+ (0xC5, "M", "å"),
+ (0xC6, "M", "æ"),
+ (0xC7, "M", "ç"),
+ ]
+
+
+def _seg_2() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xC8, "M", "è"),
+ (0xC9, "M", "é"),
+ (0xCA, "M", "ê"),
+ (0xCB, "M", "ë"),
+ (0xCC, "M", "ì"),
+ (0xCD, "M", "í"),
+ (0xCE, "M", "î"),
+ (0xCF, "M", "ï"),
+ (0xD0, "M", "ð"),
+ (0xD1, "M", "ñ"),
+ (0xD2, "M", "ò"),
+ (0xD3, "M", "ó"),
+ (0xD4, "M", "ô"),
+ (0xD5, "M", "õ"),
+ (0xD6, "M", "ö"),
+ (0xD7, "V"),
+ (0xD8, "M", "ø"),
+ (0xD9, "M", "ù"),
+ (0xDA, "M", "ú"),
+ (0xDB, "M", "û"),
+ (0xDC, "M", "ü"),
+ (0xDD, "M", "ý"),
+ (0xDE, "M", "þ"),
+ (0xDF, "D", "ss"),
+ (0xE0, "V"),
+ (0xE1, "V"),
+ (0xE2, "V"),
+ (0xE3, "V"),
+ (0xE4, "V"),
+ (0xE5, "V"),
+ (0xE6, "V"),
+ (0xE7, "V"),
+ (0xE8, "V"),
+ (0xE9, "V"),
+ (0xEA, "V"),
+ (0xEB, "V"),
+ (0xEC, "V"),
+ (0xED, "V"),
+ (0xEE, "V"),
+ (0xEF, "V"),
+ (0xF0, "V"),
+ (0xF1, "V"),
+ (0xF2, "V"),
+ (0xF3, "V"),
+ (0xF4, "V"),
+ (0xF5, "V"),
+ (0xF6, "V"),
+ (0xF7, "V"),
+ (0xF8, "V"),
+ (0xF9, "V"),
+ (0xFA, "V"),
+ (0xFB, "V"),
+ (0xFC, "V"),
+ (0xFD, "V"),
+ (0xFE, "V"),
+ (0xFF, "V"),
+ (0x100, "M", "ā"),
+ (0x101, "V"),
+ (0x102, "M", "ă"),
+ (0x103, "V"),
+ (0x104, "M", "ą"),
+ (0x105, "V"),
+ (0x106, "M", "ć"),
+ (0x107, "V"),
+ (0x108, "M", "ĉ"),
+ (0x109, "V"),
+ (0x10A, "M", "ċ"),
+ (0x10B, "V"),
+ (0x10C, "M", "č"),
+ (0x10D, "V"),
+ (0x10E, "M", "ď"),
+ (0x10F, "V"),
+ (0x110, "M", "đ"),
+ (0x111, "V"),
+ (0x112, "M", "ē"),
+ (0x113, "V"),
+ (0x114, "M", "ĕ"),
+ (0x115, "V"),
+ (0x116, "M", "ė"),
+ (0x117, "V"),
+ (0x118, "M", "ę"),
+ (0x119, "V"),
+ (0x11A, "M", "ě"),
+ (0x11B, "V"),
+ (0x11C, "M", "ĝ"),
+ (0x11D, "V"),
+ (0x11E, "M", "ğ"),
+ (0x11F, "V"),
+ (0x120, "M", "ġ"),
+ (0x121, "V"),
+ (0x122, "M", "ģ"),
+ (0x123, "V"),
+ (0x124, "M", "ĥ"),
+ (0x125, "V"),
+ (0x126, "M", "ħ"),
+ (0x127, "V"),
+ (0x128, "M", "ĩ"),
+ (0x129, "V"),
+ (0x12A, "M", "ī"),
+ (0x12B, "V"),
+ ]
+
+
+def _seg_3() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x12C, "M", "ĭ"),
+ (0x12D, "V"),
+ (0x12E, "M", "į"),
+ (0x12F, "V"),
+ (0x130, "M", "i̇"),
+ (0x131, "V"),
+ (0x132, "M", "ij"),
+ (0x134, "M", "ĵ"),
+ (0x135, "V"),
+ (0x136, "M", "ķ"),
+ (0x137, "V"),
+ (0x139, "M", "ĺ"),
+ (0x13A, "V"),
+ (0x13B, "M", "ļ"),
+ (0x13C, "V"),
+ (0x13D, "M", "ľ"),
+ (0x13E, "V"),
+ (0x13F, "M", "l·"),
+ (0x141, "M", "ł"),
+ (0x142, "V"),
+ (0x143, "M", "ń"),
+ (0x144, "V"),
+ (0x145, "M", "ņ"),
+ (0x146, "V"),
+ (0x147, "M", "ň"),
+ (0x148, "V"),
+ (0x149, "M", "ʼn"),
+ (0x14A, "M", "ŋ"),
+ (0x14B, "V"),
+ (0x14C, "M", "ō"),
+ (0x14D, "V"),
+ (0x14E, "M", "ŏ"),
+ (0x14F, "V"),
+ (0x150, "M", "ő"),
+ (0x151, "V"),
+ (0x152, "M", "œ"),
+ (0x153, "V"),
+ (0x154, "M", "ŕ"),
+ (0x155, "V"),
+ (0x156, "M", "ŗ"),
+ (0x157, "V"),
+ (0x158, "M", "ř"),
+ (0x159, "V"),
+ (0x15A, "M", "ś"),
+ (0x15B, "V"),
+ (0x15C, "M", "ŝ"),
+ (0x15D, "V"),
+ (0x15E, "M", "ş"),
+ (0x15F, "V"),
+ (0x160, "M", "š"),
+ (0x161, "V"),
+ (0x162, "M", "ţ"),
+ (0x163, "V"),
+ (0x164, "M", "ť"),
+ (0x165, "V"),
+ (0x166, "M", "ŧ"),
+ (0x167, "V"),
+ (0x168, "M", "ũ"),
+ (0x169, "V"),
+ (0x16A, "M", "ū"),
+ (0x16B, "V"),
+ (0x16C, "M", "ŭ"),
+ (0x16D, "V"),
+ (0x16E, "M", "ů"),
+ (0x16F, "V"),
+ (0x170, "M", "ű"),
+ (0x171, "V"),
+ (0x172, "M", "ų"),
+ (0x173, "V"),
+ (0x174, "M", "ŵ"),
+ (0x175, "V"),
+ (0x176, "M", "ŷ"),
+ (0x177, "V"),
+ (0x178, "M", "ÿ"),
+ (0x179, "M", "ź"),
+ (0x17A, "V"),
+ (0x17B, "M", "ż"),
+ (0x17C, "V"),
+ (0x17D, "M", "ž"),
+ (0x17E, "V"),
+ (0x17F, "M", "s"),
+ (0x180, "V"),
+ (0x181, "M", "ɓ"),
+ (0x182, "M", "ƃ"),
+ (0x183, "V"),
+ (0x184, "M", "ƅ"),
+ (0x185, "V"),
+ (0x186, "M", "ɔ"),
+ (0x187, "M", "ƈ"),
+ (0x188, "V"),
+ (0x189, "M", "ɖ"),
+ (0x18A, "M", "ɗ"),
+ (0x18B, "M", "ƌ"),
+ (0x18C, "V"),
+ (0x18E, "M", "ǝ"),
+ (0x18F, "M", "ə"),
+ (0x190, "M", "ɛ"),
+ (0x191, "M", "ƒ"),
+ (0x192, "V"),
+ (0x193, "M", "ɠ"),
+ ]
+
+
+def _seg_4() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x194, "M", "ɣ"),
+ (0x195, "V"),
+ (0x196, "M", "ɩ"),
+ (0x197, "M", "ɨ"),
+ (0x198, "M", "ƙ"),
+ (0x199, "V"),
+ (0x19C, "M", "ɯ"),
+ (0x19D, "M", "ɲ"),
+ (0x19E, "V"),
+ (0x19F, "M", "ɵ"),
+ (0x1A0, "M", "ơ"),
+ (0x1A1, "V"),
+ (0x1A2, "M", "ƣ"),
+ (0x1A3, "V"),
+ (0x1A4, "M", "ƥ"),
+ (0x1A5, "V"),
+ (0x1A6, "M", "ʀ"),
+ (0x1A7, "M", "ƨ"),
+ (0x1A8, "V"),
+ (0x1A9, "M", "ʃ"),
+ (0x1AA, "V"),
+ (0x1AC, "M", "ƭ"),
+ (0x1AD, "V"),
+ (0x1AE, "M", "ʈ"),
+ (0x1AF, "M", "ư"),
+ (0x1B0, "V"),
+ (0x1B1, "M", "ʊ"),
+ (0x1B2, "M", "ʋ"),
+ (0x1B3, "M", "ƴ"),
+ (0x1B4, "V"),
+ (0x1B5, "M", "ƶ"),
+ (0x1B6, "V"),
+ (0x1B7, "M", "ʒ"),
+ (0x1B8, "M", "ƹ"),
+ (0x1B9, "V"),
+ (0x1BC, "M", "ƽ"),
+ (0x1BD, "V"),
+ (0x1C4, "M", "dž"),
+ (0x1C7, "M", "lj"),
+ (0x1CA, "M", "nj"),
+ (0x1CD, "M", "ǎ"),
+ (0x1CE, "V"),
+ (0x1CF, "M", "ǐ"),
+ (0x1D0, "V"),
+ (0x1D1, "M", "ǒ"),
+ (0x1D2, "V"),
+ (0x1D3, "M", "ǔ"),
+ (0x1D4, "V"),
+ (0x1D5, "M", "ǖ"),
+ (0x1D6, "V"),
+ (0x1D7, "M", "ǘ"),
+ (0x1D8, "V"),
+ (0x1D9, "M", "ǚ"),
+ (0x1DA, "V"),
+ (0x1DB, "M", "ǜ"),
+ (0x1DC, "V"),
+ (0x1DE, "M", "ǟ"),
+ (0x1DF, "V"),
+ (0x1E0, "M", "ǡ"),
+ (0x1E1, "V"),
+ (0x1E2, "M", "ǣ"),
+ (0x1E3, "V"),
+ (0x1E4, "M", "ǥ"),
+ (0x1E5, "V"),
+ (0x1E6, "M", "ǧ"),
+ (0x1E7, "V"),
+ (0x1E8, "M", "ǩ"),
+ (0x1E9, "V"),
+ (0x1EA, "M", "ǫ"),
+ (0x1EB, "V"),
+ (0x1EC, "M", "ǭ"),
+ (0x1ED, "V"),
+ (0x1EE, "M", "ǯ"),
+ (0x1EF, "V"),
+ (0x1F1, "M", "dz"),
+ (0x1F4, "M", "ǵ"),
+ (0x1F5, "V"),
+ (0x1F6, "M", "ƕ"),
+ (0x1F7, "M", "ƿ"),
+ (0x1F8, "M", "ǹ"),
+ (0x1F9, "V"),
+ (0x1FA, "M", "ǻ"),
+ (0x1FB, "V"),
+ (0x1FC, "M", "ǽ"),
+ (0x1FD, "V"),
+ (0x1FE, "M", "ǿ"),
+ (0x1FF, "V"),
+ (0x200, "M", "ȁ"),
+ (0x201, "V"),
+ (0x202, "M", "ȃ"),
+ (0x203, "V"),
+ (0x204, "M", "ȅ"),
+ (0x205, "V"),
+ (0x206, "M", "ȇ"),
+ (0x207, "V"),
+ (0x208, "M", "ȉ"),
+ (0x209, "V"),
+ (0x20A, "M", "ȋ"),
+ (0x20B, "V"),
+ (0x20C, "M", "ȍ"),
+ ]
+
+
+def _seg_5() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x20D, "V"),
+ (0x20E, "M", "ȏ"),
+ (0x20F, "V"),
+ (0x210, "M", "ȑ"),
+ (0x211, "V"),
+ (0x212, "M", "ȓ"),
+ (0x213, "V"),
+ (0x214, "M", "ȕ"),
+ (0x215, "V"),
+ (0x216, "M", "ȗ"),
+ (0x217, "V"),
+ (0x218, "M", "ș"),
+ (0x219, "V"),
+ (0x21A, "M", "ț"),
+ (0x21B, "V"),
+ (0x21C, "M", "ȝ"),
+ (0x21D, "V"),
+ (0x21E, "M", "ȟ"),
+ (0x21F, "V"),
+ (0x220, "M", "ƞ"),
+ (0x221, "V"),
+ (0x222, "M", "ȣ"),
+ (0x223, "V"),
+ (0x224, "M", "ȥ"),
+ (0x225, "V"),
+ (0x226, "M", "ȧ"),
+ (0x227, "V"),
+ (0x228, "M", "ȩ"),
+ (0x229, "V"),
+ (0x22A, "M", "ȫ"),
+ (0x22B, "V"),
+ (0x22C, "M", "ȭ"),
+ (0x22D, "V"),
+ (0x22E, "M", "ȯ"),
+ (0x22F, "V"),
+ (0x230, "M", "ȱ"),
+ (0x231, "V"),
+ (0x232, "M", "ȳ"),
+ (0x233, "V"),
+ (0x23A, "M", "ⱥ"),
+ (0x23B, "M", "ȼ"),
+ (0x23C, "V"),
+ (0x23D, "M", "ƚ"),
+ (0x23E, "M", "ⱦ"),
+ (0x23F, "V"),
+ (0x241, "M", "ɂ"),
+ (0x242, "V"),
+ (0x243, "M", "ƀ"),
+ (0x244, "M", "ʉ"),
+ (0x245, "M", "ʌ"),
+ (0x246, "M", "ɇ"),
+ (0x247, "V"),
+ (0x248, "M", "ɉ"),
+ (0x249, "V"),
+ (0x24A, "M", "ɋ"),
+ (0x24B, "V"),
+ (0x24C, "M", "ɍ"),
+ (0x24D, "V"),
+ (0x24E, "M", "ɏ"),
+ (0x24F, "V"),
+ (0x2B0, "M", "h"),
+ (0x2B1, "M", "ɦ"),
+ (0x2B2, "M", "j"),
+ (0x2B3, "M", "r"),
+ (0x2B4, "M", "ɹ"),
+ (0x2B5, "M", "ɻ"),
+ (0x2B6, "M", "ʁ"),
+ (0x2B7, "M", "w"),
+ (0x2B8, "M", "y"),
+ (0x2B9, "V"),
+ (0x2D8, "3", " ̆"),
+ (0x2D9, "3", " ̇"),
+ (0x2DA, "3", " ̊"),
+ (0x2DB, "3", " ̨"),
+ (0x2DC, "3", " ̃"),
+ (0x2DD, "3", " ̋"),
+ (0x2DE, "V"),
+ (0x2E0, "M", "ɣ"),
+ (0x2E1, "M", "l"),
+ (0x2E2, "M", "s"),
+ (0x2E3, "M", "x"),
+ (0x2E4, "M", "ʕ"),
+ (0x2E5, "V"),
+ (0x340, "M", "̀"),
+ (0x341, "M", "́"),
+ (0x342, "V"),
+ (0x343, "M", "̓"),
+ (0x344, "M", "̈́"),
+ (0x345, "M", "ι"),
+ (0x346, "V"),
+ (0x34F, "I"),
+ (0x350, "V"),
+ (0x370, "M", "ͱ"),
+ (0x371, "V"),
+ (0x372, "M", "ͳ"),
+ (0x373, "V"),
+ (0x374, "M", "ʹ"),
+ (0x375, "V"),
+ (0x376, "M", "ͷ"),
+ (0x377, "V"),
+ ]
+
+
+def _seg_6() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x378, "X"),
+ (0x37A, "3", " ι"),
+ (0x37B, "V"),
+ (0x37E, "3", ";"),
+ (0x37F, "M", "ϳ"),
+ (0x380, "X"),
+ (0x384, "3", " ́"),
+ (0x385, "3", " ̈́"),
+ (0x386, "M", "ά"),
+ (0x387, "M", "·"),
+ (0x388, "M", "έ"),
+ (0x389, "M", "ή"),
+ (0x38A, "M", "ί"),
+ (0x38B, "X"),
+ (0x38C, "M", "ό"),
+ (0x38D, "X"),
+ (0x38E, "M", "ύ"),
+ (0x38F, "M", "ώ"),
+ (0x390, "V"),
+ (0x391, "M", "α"),
+ (0x392, "M", "β"),
+ (0x393, "M", "γ"),
+ (0x394, "M", "δ"),
+ (0x395, "M", "ε"),
+ (0x396, "M", "ζ"),
+ (0x397, "M", "η"),
+ (0x398, "M", "θ"),
+ (0x399, "M", "ι"),
+ (0x39A, "M", "κ"),
+ (0x39B, "M", "λ"),
+ (0x39C, "M", "μ"),
+ (0x39D, "M", "ν"),
+ (0x39E, "M", "ξ"),
+ (0x39F, "M", "ο"),
+ (0x3A0, "M", "π"),
+ (0x3A1, "M", "ρ"),
+ (0x3A2, "X"),
+ (0x3A3, "M", "σ"),
+ (0x3A4, "M", "τ"),
+ (0x3A5, "M", "υ"),
+ (0x3A6, "M", "φ"),
+ (0x3A7, "M", "χ"),
+ (0x3A8, "M", "ψ"),
+ (0x3A9, "M", "ω"),
+ (0x3AA, "M", "ϊ"),
+ (0x3AB, "M", "ϋ"),
+ (0x3AC, "V"),
+ (0x3C2, "D", "σ"),
+ (0x3C3, "V"),
+ (0x3CF, "M", "ϗ"),
+ (0x3D0, "M", "β"),
+ (0x3D1, "M", "θ"),
+ (0x3D2, "M", "υ"),
+ (0x3D3, "M", "ύ"),
+ (0x3D4, "M", "ϋ"),
+ (0x3D5, "M", "φ"),
+ (0x3D6, "M", "π"),
+ (0x3D7, "V"),
+ (0x3D8, "M", "ϙ"),
+ (0x3D9, "V"),
+ (0x3DA, "M", "ϛ"),
+ (0x3DB, "V"),
+ (0x3DC, "M", "ϝ"),
+ (0x3DD, "V"),
+ (0x3DE, "M", "ϟ"),
+ (0x3DF, "V"),
+ (0x3E0, "M", "ϡ"),
+ (0x3E1, "V"),
+ (0x3E2, "M", "ϣ"),
+ (0x3E3, "V"),
+ (0x3E4, "M", "ϥ"),
+ (0x3E5, "V"),
+ (0x3E6, "M", "ϧ"),
+ (0x3E7, "V"),
+ (0x3E8, "M", "ϩ"),
+ (0x3E9, "V"),
+ (0x3EA, "M", "ϫ"),
+ (0x3EB, "V"),
+ (0x3EC, "M", "ϭ"),
+ (0x3ED, "V"),
+ (0x3EE, "M", "ϯ"),
+ (0x3EF, "V"),
+ (0x3F0, "M", "κ"),
+ (0x3F1, "M", "ρ"),
+ (0x3F2, "M", "σ"),
+ (0x3F3, "V"),
+ (0x3F4, "M", "θ"),
+ (0x3F5, "M", "ε"),
+ (0x3F6, "V"),
+ (0x3F7, "M", "ϸ"),
+ (0x3F8, "V"),
+ (0x3F9, "M", "σ"),
+ (0x3FA, "M", "ϻ"),
+ (0x3FB, "V"),
+ (0x3FD, "M", "ͻ"),
+ (0x3FE, "M", "ͼ"),
+ (0x3FF, "M", "ͽ"),
+ (0x400, "M", "ѐ"),
+ (0x401, "M", "ё"),
+ (0x402, "M", "ђ"),
+ ]
+
+
+def _seg_7() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x403, "M", "ѓ"),
+ (0x404, "M", "є"),
+ (0x405, "M", "ѕ"),
+ (0x406, "M", "і"),
+ (0x407, "M", "ї"),
+ (0x408, "M", "ј"),
+ (0x409, "M", "љ"),
+ (0x40A, "M", "њ"),
+ (0x40B, "M", "ћ"),
+ (0x40C, "M", "ќ"),
+ (0x40D, "M", "ѝ"),
+ (0x40E, "M", "ў"),
+ (0x40F, "M", "џ"),
+ (0x410, "M", "а"),
+ (0x411, "M", "б"),
+ (0x412, "M", "в"),
+ (0x413, "M", "г"),
+ (0x414, "M", "д"),
+ (0x415, "M", "е"),
+ (0x416, "M", "ж"),
+ (0x417, "M", "з"),
+ (0x418, "M", "и"),
+ (0x419, "M", "й"),
+ (0x41A, "M", "к"),
+ (0x41B, "M", "л"),
+ (0x41C, "M", "м"),
+ (0x41D, "M", "н"),
+ (0x41E, "M", "о"),
+ (0x41F, "M", "п"),
+ (0x420, "M", "р"),
+ (0x421, "M", "с"),
+ (0x422, "M", "т"),
+ (0x423, "M", "у"),
+ (0x424, "M", "ф"),
+ (0x425, "M", "х"),
+ (0x426, "M", "ц"),
+ (0x427, "M", "ч"),
+ (0x428, "M", "ш"),
+ (0x429, "M", "щ"),
+ (0x42A, "M", "ъ"),
+ (0x42B, "M", "ы"),
+ (0x42C, "M", "ь"),
+ (0x42D, "M", "э"),
+ (0x42E, "M", "ю"),
+ (0x42F, "M", "я"),
+ (0x430, "V"),
+ (0x460, "M", "ѡ"),
+ (0x461, "V"),
+ (0x462, "M", "ѣ"),
+ (0x463, "V"),
+ (0x464, "M", "ѥ"),
+ (0x465, "V"),
+ (0x466, "M", "ѧ"),
+ (0x467, "V"),
+ (0x468, "M", "ѩ"),
+ (0x469, "V"),
+ (0x46A, "M", "ѫ"),
+ (0x46B, "V"),
+ (0x46C, "M", "ѭ"),
+ (0x46D, "V"),
+ (0x46E, "M", "ѯ"),
+ (0x46F, "V"),
+ (0x470, "M", "ѱ"),
+ (0x471, "V"),
+ (0x472, "M", "ѳ"),
+ (0x473, "V"),
+ (0x474, "M", "ѵ"),
+ (0x475, "V"),
+ (0x476, "M", "ѷ"),
+ (0x477, "V"),
+ (0x478, "M", "ѹ"),
+ (0x479, "V"),
+ (0x47A, "M", "ѻ"),
+ (0x47B, "V"),
+ (0x47C, "M", "ѽ"),
+ (0x47D, "V"),
+ (0x47E, "M", "ѿ"),
+ (0x47F, "V"),
+ (0x480, "M", "ҁ"),
+ (0x481, "V"),
+ (0x48A, "M", "ҋ"),
+ (0x48B, "V"),
+ (0x48C, "M", "ҍ"),
+ (0x48D, "V"),
+ (0x48E, "M", "ҏ"),
+ (0x48F, "V"),
+ (0x490, "M", "ґ"),
+ (0x491, "V"),
+ (0x492, "M", "ғ"),
+ (0x493, "V"),
+ (0x494, "M", "ҕ"),
+ (0x495, "V"),
+ (0x496, "M", "җ"),
+ (0x497, "V"),
+ (0x498, "M", "ҙ"),
+ (0x499, "V"),
+ (0x49A, "M", "қ"),
+ (0x49B, "V"),
+ (0x49C, "M", "ҝ"),
+ (0x49D, "V"),
+ ]
+
+
+def _seg_8() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x49E, "M", "ҟ"),
+ (0x49F, "V"),
+ (0x4A0, "M", "ҡ"),
+ (0x4A1, "V"),
+ (0x4A2, "M", "ң"),
+ (0x4A3, "V"),
+ (0x4A4, "M", "ҥ"),
+ (0x4A5, "V"),
+ (0x4A6, "M", "ҧ"),
+ (0x4A7, "V"),
+ (0x4A8, "M", "ҩ"),
+ (0x4A9, "V"),
+ (0x4AA, "M", "ҫ"),
+ (0x4AB, "V"),
+ (0x4AC, "M", "ҭ"),
+ (0x4AD, "V"),
+ (0x4AE, "M", "ү"),
+ (0x4AF, "V"),
+ (0x4B0, "M", "ұ"),
+ (0x4B1, "V"),
+ (0x4B2, "M", "ҳ"),
+ (0x4B3, "V"),
+ (0x4B4, "M", "ҵ"),
+ (0x4B5, "V"),
+ (0x4B6, "M", "ҷ"),
+ (0x4B7, "V"),
+ (0x4B8, "M", "ҹ"),
+ (0x4B9, "V"),
+ (0x4BA, "M", "һ"),
+ (0x4BB, "V"),
+ (0x4BC, "M", "ҽ"),
+ (0x4BD, "V"),
+ (0x4BE, "M", "ҿ"),
+ (0x4BF, "V"),
+ (0x4C0, "X"),
+ (0x4C1, "M", "ӂ"),
+ (0x4C2, "V"),
+ (0x4C3, "M", "ӄ"),
+ (0x4C4, "V"),
+ (0x4C5, "M", "ӆ"),
+ (0x4C6, "V"),
+ (0x4C7, "M", "ӈ"),
+ (0x4C8, "V"),
+ (0x4C9, "M", "ӊ"),
+ (0x4CA, "V"),
+ (0x4CB, "M", "ӌ"),
+ (0x4CC, "V"),
+ (0x4CD, "M", "ӎ"),
+ (0x4CE, "V"),
+ (0x4D0, "M", "ӑ"),
+ (0x4D1, "V"),
+ (0x4D2, "M", "ӓ"),
+ (0x4D3, "V"),
+ (0x4D4, "M", "ӕ"),
+ (0x4D5, "V"),
+ (0x4D6, "M", "ӗ"),
+ (0x4D7, "V"),
+ (0x4D8, "M", "ә"),
+ (0x4D9, "V"),
+ (0x4DA, "M", "ӛ"),
+ (0x4DB, "V"),
+ (0x4DC, "M", "ӝ"),
+ (0x4DD, "V"),
+ (0x4DE, "M", "ӟ"),
+ (0x4DF, "V"),
+ (0x4E0, "M", "ӡ"),
+ (0x4E1, "V"),
+ (0x4E2, "M", "ӣ"),
+ (0x4E3, "V"),
+ (0x4E4, "M", "ӥ"),
+ (0x4E5, "V"),
+ (0x4E6, "M", "ӧ"),
+ (0x4E7, "V"),
+ (0x4E8, "M", "ө"),
+ (0x4E9, "V"),
+ (0x4EA, "M", "ӫ"),
+ (0x4EB, "V"),
+ (0x4EC, "M", "ӭ"),
+ (0x4ED, "V"),
+ (0x4EE, "M", "ӯ"),
+ (0x4EF, "V"),
+ (0x4F0, "M", "ӱ"),
+ (0x4F1, "V"),
+ (0x4F2, "M", "ӳ"),
+ (0x4F3, "V"),
+ (0x4F4, "M", "ӵ"),
+ (0x4F5, "V"),
+ (0x4F6, "M", "ӷ"),
+ (0x4F7, "V"),
+ (0x4F8, "M", "ӹ"),
+ (0x4F9, "V"),
+ (0x4FA, "M", "ӻ"),
+ (0x4FB, "V"),
+ (0x4FC, "M", "ӽ"),
+ (0x4FD, "V"),
+ (0x4FE, "M", "ӿ"),
+ (0x4FF, "V"),
+ (0x500, "M", "ԁ"),
+ (0x501, "V"),
+ (0x502, "M", "ԃ"),
+ ]
+
+
+def _seg_9() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x503, "V"),
+ (0x504, "M", "ԅ"),
+ (0x505, "V"),
+ (0x506, "M", "ԇ"),
+ (0x507, "V"),
+ (0x508, "M", "ԉ"),
+ (0x509, "V"),
+ (0x50A, "M", "ԋ"),
+ (0x50B, "V"),
+ (0x50C, "M", "ԍ"),
+ (0x50D, "V"),
+ (0x50E, "M", "ԏ"),
+ (0x50F, "V"),
+ (0x510, "M", "ԑ"),
+ (0x511, "V"),
+ (0x512, "M", "ԓ"),
+ (0x513, "V"),
+ (0x514, "M", "ԕ"),
+ (0x515, "V"),
+ (0x516, "M", "ԗ"),
+ (0x517, "V"),
+ (0x518, "M", "ԙ"),
+ (0x519, "V"),
+ (0x51A, "M", "ԛ"),
+ (0x51B, "V"),
+ (0x51C, "M", "ԝ"),
+ (0x51D, "V"),
+ (0x51E, "M", "ԟ"),
+ (0x51F, "V"),
+ (0x520, "M", "ԡ"),
+ (0x521, "V"),
+ (0x522, "M", "ԣ"),
+ (0x523, "V"),
+ (0x524, "M", "ԥ"),
+ (0x525, "V"),
+ (0x526, "M", "ԧ"),
+ (0x527, "V"),
+ (0x528, "M", "ԩ"),
+ (0x529, "V"),
+ (0x52A, "M", "ԫ"),
+ (0x52B, "V"),
+ (0x52C, "M", "ԭ"),
+ (0x52D, "V"),
+ (0x52E, "M", "ԯ"),
+ (0x52F, "V"),
+ (0x530, "X"),
+ (0x531, "M", "ա"),
+ (0x532, "M", "բ"),
+ (0x533, "M", "գ"),
+ (0x534, "M", "դ"),
+ (0x535, "M", "ե"),
+ (0x536, "M", "զ"),
+ (0x537, "M", "է"),
+ (0x538, "M", "ը"),
+ (0x539, "M", "թ"),
+ (0x53A, "M", "ժ"),
+ (0x53B, "M", "ի"),
+ (0x53C, "M", "լ"),
+ (0x53D, "M", "խ"),
+ (0x53E, "M", "ծ"),
+ (0x53F, "M", "կ"),
+ (0x540, "M", "հ"),
+ (0x541, "M", "ձ"),
+ (0x542, "M", "ղ"),
+ (0x543, "M", "ճ"),
+ (0x544, "M", "մ"),
+ (0x545, "M", "յ"),
+ (0x546, "M", "ն"),
+ (0x547, "M", "շ"),
+ (0x548, "M", "ո"),
+ (0x549, "M", "չ"),
+ (0x54A, "M", "պ"),
+ (0x54B, "M", "ջ"),
+ (0x54C, "M", "ռ"),
+ (0x54D, "M", "ս"),
+ (0x54E, "M", "վ"),
+ (0x54F, "M", "տ"),
+ (0x550, "M", "ր"),
+ (0x551, "M", "ց"),
+ (0x552, "M", "ւ"),
+ (0x553, "M", "փ"),
+ (0x554, "M", "ք"),
+ (0x555, "M", "օ"),
+ (0x556, "M", "ֆ"),
+ (0x557, "X"),
+ (0x559, "V"),
+ (0x587, "M", "եւ"),
+ (0x588, "V"),
+ (0x58B, "X"),
+ (0x58D, "V"),
+ (0x590, "X"),
+ (0x591, "V"),
+ (0x5C8, "X"),
+ (0x5D0, "V"),
+ (0x5EB, "X"),
+ (0x5EF, "V"),
+ (0x5F5, "X"),
+ (0x606, "V"),
+ (0x61C, "X"),
+ (0x61D, "V"),
+ ]
+
+
+def _seg_10() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x675, "M", "اٴ"),
+ (0x676, "M", "وٴ"),
+ (0x677, "M", "ۇٴ"),
+ (0x678, "M", "يٴ"),
+ (0x679, "V"),
+ (0x6DD, "X"),
+ (0x6DE, "V"),
+ (0x70E, "X"),
+ (0x710, "V"),
+ (0x74B, "X"),
+ (0x74D, "V"),
+ (0x7B2, "X"),
+ (0x7C0, "V"),
+ (0x7FB, "X"),
+ (0x7FD, "V"),
+ (0x82E, "X"),
+ (0x830, "V"),
+ (0x83F, "X"),
+ (0x840, "V"),
+ (0x85C, "X"),
+ (0x85E, "V"),
+ (0x85F, "X"),
+ (0x860, "V"),
+ (0x86B, "X"),
+ (0x870, "V"),
+ (0x88F, "X"),
+ (0x898, "V"),
+ (0x8E2, "X"),
+ (0x8E3, "V"),
+ (0x958, "M", "क़"),
+ (0x959, "M", "ख़"),
+ (0x95A, "M", "ग़"),
+ (0x95B, "M", "ज़"),
+ (0x95C, "M", "ड़"),
+ (0x95D, "M", "ढ़"),
+ (0x95E, "M", "फ़"),
+ (0x95F, "M", "य़"),
+ (0x960, "V"),
+ (0x984, "X"),
+ (0x985, "V"),
+ (0x98D, "X"),
+ (0x98F, "V"),
+ (0x991, "X"),
+ (0x993, "V"),
+ (0x9A9, "X"),
+ (0x9AA, "V"),
+ (0x9B1, "X"),
+ (0x9B2, "V"),
+ (0x9B3, "X"),
+ (0x9B6, "V"),
+ (0x9BA, "X"),
+ (0x9BC, "V"),
+ (0x9C5, "X"),
+ (0x9C7, "V"),
+ (0x9C9, "X"),
+ (0x9CB, "V"),
+ (0x9CF, "X"),
+ (0x9D7, "V"),
+ (0x9D8, "X"),
+ (0x9DC, "M", "ড়"),
+ (0x9DD, "M", "ঢ়"),
+ (0x9DE, "X"),
+ (0x9DF, "M", "য়"),
+ (0x9E0, "V"),
+ (0x9E4, "X"),
+ (0x9E6, "V"),
+ (0x9FF, "X"),
+ (0xA01, "V"),
+ (0xA04, "X"),
+ (0xA05, "V"),
+ (0xA0B, "X"),
+ (0xA0F, "V"),
+ (0xA11, "X"),
+ (0xA13, "V"),
+ (0xA29, "X"),
+ (0xA2A, "V"),
+ (0xA31, "X"),
+ (0xA32, "V"),
+ (0xA33, "M", "ਲ਼"),
+ (0xA34, "X"),
+ (0xA35, "V"),
+ (0xA36, "M", "ਸ਼"),
+ (0xA37, "X"),
+ (0xA38, "V"),
+ (0xA3A, "X"),
+ (0xA3C, "V"),
+ (0xA3D, "X"),
+ (0xA3E, "V"),
+ (0xA43, "X"),
+ (0xA47, "V"),
+ (0xA49, "X"),
+ (0xA4B, "V"),
+ (0xA4E, "X"),
+ (0xA51, "V"),
+ (0xA52, "X"),
+ (0xA59, "M", "ਖ਼"),
+ (0xA5A, "M", "ਗ਼"),
+ (0xA5B, "M", "ਜ਼"),
+ (0xA5C, "V"),
+ (0xA5D, "X"),
+ ]
+
+
+def _seg_11() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xA5E, "M", "ਫ਼"),
+ (0xA5F, "X"),
+ (0xA66, "V"),
+ (0xA77, "X"),
+ (0xA81, "V"),
+ (0xA84, "X"),
+ (0xA85, "V"),
+ (0xA8E, "X"),
+ (0xA8F, "V"),
+ (0xA92, "X"),
+ (0xA93, "V"),
+ (0xAA9, "X"),
+ (0xAAA, "V"),
+ (0xAB1, "X"),
+ (0xAB2, "V"),
+ (0xAB4, "X"),
+ (0xAB5, "V"),
+ (0xABA, "X"),
+ (0xABC, "V"),
+ (0xAC6, "X"),
+ (0xAC7, "V"),
+ (0xACA, "X"),
+ (0xACB, "V"),
+ (0xACE, "X"),
+ (0xAD0, "V"),
+ (0xAD1, "X"),
+ (0xAE0, "V"),
+ (0xAE4, "X"),
+ (0xAE6, "V"),
+ (0xAF2, "X"),
+ (0xAF9, "V"),
+ (0xB00, "X"),
+ (0xB01, "V"),
+ (0xB04, "X"),
+ (0xB05, "V"),
+ (0xB0D, "X"),
+ (0xB0F, "V"),
+ (0xB11, "X"),
+ (0xB13, "V"),
+ (0xB29, "X"),
+ (0xB2A, "V"),
+ (0xB31, "X"),
+ (0xB32, "V"),
+ (0xB34, "X"),
+ (0xB35, "V"),
+ (0xB3A, "X"),
+ (0xB3C, "V"),
+ (0xB45, "X"),
+ (0xB47, "V"),
+ (0xB49, "X"),
+ (0xB4B, "V"),
+ (0xB4E, "X"),
+ (0xB55, "V"),
+ (0xB58, "X"),
+ (0xB5C, "M", "ଡ଼"),
+ (0xB5D, "M", "ଢ଼"),
+ (0xB5E, "X"),
+ (0xB5F, "V"),
+ (0xB64, "X"),
+ (0xB66, "V"),
+ (0xB78, "X"),
+ (0xB82, "V"),
+ (0xB84, "X"),
+ (0xB85, "V"),
+ (0xB8B, "X"),
+ (0xB8E, "V"),
+ (0xB91, "X"),
+ (0xB92, "V"),
+ (0xB96, "X"),
+ (0xB99, "V"),
+ (0xB9B, "X"),
+ (0xB9C, "V"),
+ (0xB9D, "X"),
+ (0xB9E, "V"),
+ (0xBA0, "X"),
+ (0xBA3, "V"),
+ (0xBA5, "X"),
+ (0xBA8, "V"),
+ (0xBAB, "X"),
+ (0xBAE, "V"),
+ (0xBBA, "X"),
+ (0xBBE, "V"),
+ (0xBC3, "X"),
+ (0xBC6, "V"),
+ (0xBC9, "X"),
+ (0xBCA, "V"),
+ (0xBCE, "X"),
+ (0xBD0, "V"),
+ (0xBD1, "X"),
+ (0xBD7, "V"),
+ (0xBD8, "X"),
+ (0xBE6, "V"),
+ (0xBFB, "X"),
+ (0xC00, "V"),
+ (0xC0D, "X"),
+ (0xC0E, "V"),
+ (0xC11, "X"),
+ (0xC12, "V"),
+ (0xC29, "X"),
+ (0xC2A, "V"),
+ ]
+
+
+def _seg_12() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xC3A, "X"),
+ (0xC3C, "V"),
+ (0xC45, "X"),
+ (0xC46, "V"),
+ (0xC49, "X"),
+ (0xC4A, "V"),
+ (0xC4E, "X"),
+ (0xC55, "V"),
+ (0xC57, "X"),
+ (0xC58, "V"),
+ (0xC5B, "X"),
+ (0xC5D, "V"),
+ (0xC5E, "X"),
+ (0xC60, "V"),
+ (0xC64, "X"),
+ (0xC66, "V"),
+ (0xC70, "X"),
+ (0xC77, "V"),
+ (0xC8D, "X"),
+ (0xC8E, "V"),
+ (0xC91, "X"),
+ (0xC92, "V"),
+ (0xCA9, "X"),
+ (0xCAA, "V"),
+ (0xCB4, "X"),
+ (0xCB5, "V"),
+ (0xCBA, "X"),
+ (0xCBC, "V"),
+ (0xCC5, "X"),
+ (0xCC6, "V"),
+ (0xCC9, "X"),
+ (0xCCA, "V"),
+ (0xCCE, "X"),
+ (0xCD5, "V"),
+ (0xCD7, "X"),
+ (0xCDD, "V"),
+ (0xCDF, "X"),
+ (0xCE0, "V"),
+ (0xCE4, "X"),
+ (0xCE6, "V"),
+ (0xCF0, "X"),
+ (0xCF1, "V"),
+ (0xCF4, "X"),
+ (0xD00, "V"),
+ (0xD0D, "X"),
+ (0xD0E, "V"),
+ (0xD11, "X"),
+ (0xD12, "V"),
+ (0xD45, "X"),
+ (0xD46, "V"),
+ (0xD49, "X"),
+ (0xD4A, "V"),
+ (0xD50, "X"),
+ (0xD54, "V"),
+ (0xD64, "X"),
+ (0xD66, "V"),
+ (0xD80, "X"),
+ (0xD81, "V"),
+ (0xD84, "X"),
+ (0xD85, "V"),
+ (0xD97, "X"),
+ (0xD9A, "V"),
+ (0xDB2, "X"),
+ (0xDB3, "V"),
+ (0xDBC, "X"),
+ (0xDBD, "V"),
+ (0xDBE, "X"),
+ (0xDC0, "V"),
+ (0xDC7, "X"),
+ (0xDCA, "V"),
+ (0xDCB, "X"),
+ (0xDCF, "V"),
+ (0xDD5, "X"),
+ (0xDD6, "V"),
+ (0xDD7, "X"),
+ (0xDD8, "V"),
+ (0xDE0, "X"),
+ (0xDE6, "V"),
+ (0xDF0, "X"),
+ (0xDF2, "V"),
+ (0xDF5, "X"),
+ (0xE01, "V"),
+ (0xE33, "M", "ํา"),
+ (0xE34, "V"),
+ (0xE3B, "X"),
+ (0xE3F, "V"),
+ (0xE5C, "X"),
+ (0xE81, "V"),
+ (0xE83, "X"),
+ (0xE84, "V"),
+ (0xE85, "X"),
+ (0xE86, "V"),
+ (0xE8B, "X"),
+ (0xE8C, "V"),
+ (0xEA4, "X"),
+ (0xEA5, "V"),
+ (0xEA6, "X"),
+ (0xEA7, "V"),
+ (0xEB3, "M", "ໍາ"),
+ (0xEB4, "V"),
+ ]
+
+
+def _seg_13() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xEBE, "X"),
+ (0xEC0, "V"),
+ (0xEC5, "X"),
+ (0xEC6, "V"),
+ (0xEC7, "X"),
+ (0xEC8, "V"),
+ (0xECF, "X"),
+ (0xED0, "V"),
+ (0xEDA, "X"),
+ (0xEDC, "M", "ຫນ"),
+ (0xEDD, "M", "ຫມ"),
+ (0xEDE, "V"),
+ (0xEE0, "X"),
+ (0xF00, "V"),
+ (0xF0C, "M", "་"),
+ (0xF0D, "V"),
+ (0xF43, "M", "གྷ"),
+ (0xF44, "V"),
+ (0xF48, "X"),
+ (0xF49, "V"),
+ (0xF4D, "M", "ཌྷ"),
+ (0xF4E, "V"),
+ (0xF52, "M", "དྷ"),
+ (0xF53, "V"),
+ (0xF57, "M", "བྷ"),
+ (0xF58, "V"),
+ (0xF5C, "M", "ཛྷ"),
+ (0xF5D, "V"),
+ (0xF69, "M", "ཀྵ"),
+ (0xF6A, "V"),
+ (0xF6D, "X"),
+ (0xF71, "V"),
+ (0xF73, "M", "ཱི"),
+ (0xF74, "V"),
+ (0xF75, "M", "ཱུ"),
+ (0xF76, "M", "ྲྀ"),
+ (0xF77, "M", "ྲཱྀ"),
+ (0xF78, "M", "ླྀ"),
+ (0xF79, "M", "ླཱྀ"),
+ (0xF7A, "V"),
+ (0xF81, "M", "ཱྀ"),
+ (0xF82, "V"),
+ (0xF93, "M", "ྒྷ"),
+ (0xF94, "V"),
+ (0xF98, "X"),
+ (0xF99, "V"),
+ (0xF9D, "M", "ྜྷ"),
+ (0xF9E, "V"),
+ (0xFA2, "M", "ྡྷ"),
+ (0xFA3, "V"),
+ (0xFA7, "M", "ྦྷ"),
+ (0xFA8, "V"),
+ (0xFAC, "M", "ྫྷ"),
+ (0xFAD, "V"),
+ (0xFB9, "M", "ྐྵ"),
+ (0xFBA, "V"),
+ (0xFBD, "X"),
+ (0xFBE, "V"),
+ (0xFCD, "X"),
+ (0xFCE, "V"),
+ (0xFDB, "X"),
+ (0x1000, "V"),
+ (0x10A0, "X"),
+ (0x10C7, "M", "ⴧ"),
+ (0x10C8, "X"),
+ (0x10CD, "M", "ⴭ"),
+ (0x10CE, "X"),
+ (0x10D0, "V"),
+ (0x10FC, "M", "ნ"),
+ (0x10FD, "V"),
+ (0x115F, "X"),
+ (0x1161, "V"),
+ (0x1249, "X"),
+ (0x124A, "V"),
+ (0x124E, "X"),
+ (0x1250, "V"),
+ (0x1257, "X"),
+ (0x1258, "V"),
+ (0x1259, "X"),
+ (0x125A, "V"),
+ (0x125E, "X"),
+ (0x1260, "V"),
+ (0x1289, "X"),
+ (0x128A, "V"),
+ (0x128E, "X"),
+ (0x1290, "V"),
+ (0x12B1, "X"),
+ (0x12B2, "V"),
+ (0x12B6, "X"),
+ (0x12B8, "V"),
+ (0x12BF, "X"),
+ (0x12C0, "V"),
+ (0x12C1, "X"),
+ (0x12C2, "V"),
+ (0x12C6, "X"),
+ (0x12C8, "V"),
+ (0x12D7, "X"),
+ (0x12D8, "V"),
+ (0x1311, "X"),
+ (0x1312, "V"),
+ ]
+
+
+def _seg_14() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1316, "X"),
+ (0x1318, "V"),
+ (0x135B, "X"),
+ (0x135D, "V"),
+ (0x137D, "X"),
+ (0x1380, "V"),
+ (0x139A, "X"),
+ (0x13A0, "V"),
+ (0x13F6, "X"),
+ (0x13F8, "M", "Ᏸ"),
+ (0x13F9, "M", "Ᏹ"),
+ (0x13FA, "M", "Ᏺ"),
+ (0x13FB, "M", "Ᏻ"),
+ (0x13FC, "M", "Ᏼ"),
+ (0x13FD, "M", "Ᏽ"),
+ (0x13FE, "X"),
+ (0x1400, "V"),
+ (0x1680, "X"),
+ (0x1681, "V"),
+ (0x169D, "X"),
+ (0x16A0, "V"),
+ (0x16F9, "X"),
+ (0x1700, "V"),
+ (0x1716, "X"),
+ (0x171F, "V"),
+ (0x1737, "X"),
+ (0x1740, "V"),
+ (0x1754, "X"),
+ (0x1760, "V"),
+ (0x176D, "X"),
+ (0x176E, "V"),
+ (0x1771, "X"),
+ (0x1772, "V"),
+ (0x1774, "X"),
+ (0x1780, "V"),
+ (0x17B4, "X"),
+ (0x17B6, "V"),
+ (0x17DE, "X"),
+ (0x17E0, "V"),
+ (0x17EA, "X"),
+ (0x17F0, "V"),
+ (0x17FA, "X"),
+ (0x1800, "V"),
+ (0x1806, "X"),
+ (0x1807, "V"),
+ (0x180B, "I"),
+ (0x180E, "X"),
+ (0x180F, "I"),
+ (0x1810, "V"),
+ (0x181A, "X"),
+ (0x1820, "V"),
+ (0x1879, "X"),
+ (0x1880, "V"),
+ (0x18AB, "X"),
+ (0x18B0, "V"),
+ (0x18F6, "X"),
+ (0x1900, "V"),
+ (0x191F, "X"),
+ (0x1920, "V"),
+ (0x192C, "X"),
+ (0x1930, "V"),
+ (0x193C, "X"),
+ (0x1940, "V"),
+ (0x1941, "X"),
+ (0x1944, "V"),
+ (0x196E, "X"),
+ (0x1970, "V"),
+ (0x1975, "X"),
+ (0x1980, "V"),
+ (0x19AC, "X"),
+ (0x19B0, "V"),
+ (0x19CA, "X"),
+ (0x19D0, "V"),
+ (0x19DB, "X"),
+ (0x19DE, "V"),
+ (0x1A1C, "X"),
+ (0x1A1E, "V"),
+ (0x1A5F, "X"),
+ (0x1A60, "V"),
+ (0x1A7D, "X"),
+ (0x1A7F, "V"),
+ (0x1A8A, "X"),
+ (0x1A90, "V"),
+ (0x1A9A, "X"),
+ (0x1AA0, "V"),
+ (0x1AAE, "X"),
+ (0x1AB0, "V"),
+ (0x1ACF, "X"),
+ (0x1B00, "V"),
+ (0x1B4D, "X"),
+ (0x1B50, "V"),
+ (0x1B7F, "X"),
+ (0x1B80, "V"),
+ (0x1BF4, "X"),
+ (0x1BFC, "V"),
+ (0x1C38, "X"),
+ (0x1C3B, "V"),
+ (0x1C4A, "X"),
+ (0x1C4D, "V"),
+ (0x1C80, "M", "в"),
+ ]
+
+
+def _seg_15() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1C81, "M", "д"),
+ (0x1C82, "M", "о"),
+ (0x1C83, "M", "с"),
+ (0x1C84, "M", "т"),
+ (0x1C86, "M", "ъ"),
+ (0x1C87, "M", "ѣ"),
+ (0x1C88, "M", "ꙋ"),
+ (0x1C89, "X"),
+ (0x1C90, "M", "ა"),
+ (0x1C91, "M", "ბ"),
+ (0x1C92, "M", "გ"),
+ (0x1C93, "M", "დ"),
+ (0x1C94, "M", "ე"),
+ (0x1C95, "M", "ვ"),
+ (0x1C96, "M", "ზ"),
+ (0x1C97, "M", "თ"),
+ (0x1C98, "M", "ი"),
+ (0x1C99, "M", "კ"),
+ (0x1C9A, "M", "ლ"),
+ (0x1C9B, "M", "მ"),
+ (0x1C9C, "M", "ნ"),
+ (0x1C9D, "M", "ო"),
+ (0x1C9E, "M", "პ"),
+ (0x1C9F, "M", "ჟ"),
+ (0x1CA0, "M", "რ"),
+ (0x1CA1, "M", "ს"),
+ (0x1CA2, "M", "ტ"),
+ (0x1CA3, "M", "უ"),
+ (0x1CA4, "M", "ფ"),
+ (0x1CA5, "M", "ქ"),
+ (0x1CA6, "M", "ღ"),
+ (0x1CA7, "M", "ყ"),
+ (0x1CA8, "M", "შ"),
+ (0x1CA9, "M", "ჩ"),
+ (0x1CAA, "M", "ც"),
+ (0x1CAB, "M", "ძ"),
+ (0x1CAC, "M", "წ"),
+ (0x1CAD, "M", "ჭ"),
+ (0x1CAE, "M", "ხ"),
+ (0x1CAF, "M", "ჯ"),
+ (0x1CB0, "M", "ჰ"),
+ (0x1CB1, "M", "ჱ"),
+ (0x1CB2, "M", "ჲ"),
+ (0x1CB3, "M", "ჳ"),
+ (0x1CB4, "M", "ჴ"),
+ (0x1CB5, "M", "ჵ"),
+ (0x1CB6, "M", "ჶ"),
+ (0x1CB7, "M", "ჷ"),
+ (0x1CB8, "M", "ჸ"),
+ (0x1CB9, "M", "ჹ"),
+ (0x1CBA, "M", "ჺ"),
+ (0x1CBB, "X"),
+ (0x1CBD, "M", "ჽ"),
+ (0x1CBE, "M", "ჾ"),
+ (0x1CBF, "M", "ჿ"),
+ (0x1CC0, "V"),
+ (0x1CC8, "X"),
+ (0x1CD0, "V"),
+ (0x1CFB, "X"),
+ (0x1D00, "V"),
+ (0x1D2C, "M", "a"),
+ (0x1D2D, "M", "æ"),
+ (0x1D2E, "M", "b"),
+ (0x1D2F, "V"),
+ (0x1D30, "M", "d"),
+ (0x1D31, "M", "e"),
+ (0x1D32, "M", "ǝ"),
+ (0x1D33, "M", "g"),
+ (0x1D34, "M", "h"),
+ (0x1D35, "M", "i"),
+ (0x1D36, "M", "j"),
+ (0x1D37, "M", "k"),
+ (0x1D38, "M", "l"),
+ (0x1D39, "M", "m"),
+ (0x1D3A, "M", "n"),
+ (0x1D3B, "V"),
+ (0x1D3C, "M", "o"),
+ (0x1D3D, "M", "ȣ"),
+ (0x1D3E, "M", "p"),
+ (0x1D3F, "M", "r"),
+ (0x1D40, "M", "t"),
+ (0x1D41, "M", "u"),
+ (0x1D42, "M", "w"),
+ (0x1D43, "M", "a"),
+ (0x1D44, "M", "ɐ"),
+ (0x1D45, "M", "ɑ"),
+ (0x1D46, "M", "ᴂ"),
+ (0x1D47, "M", "b"),
+ (0x1D48, "M", "d"),
+ (0x1D49, "M", "e"),
+ (0x1D4A, "M", "ə"),
+ (0x1D4B, "M", "ɛ"),
+ (0x1D4C, "M", "ɜ"),
+ (0x1D4D, "M", "g"),
+ (0x1D4E, "V"),
+ (0x1D4F, "M", "k"),
+ (0x1D50, "M", "m"),
+ (0x1D51, "M", "ŋ"),
+ (0x1D52, "M", "o"),
+ (0x1D53, "M", "ɔ"),
+ ]
+
+
+def _seg_16() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1D54, "M", "ᴖ"),
+ (0x1D55, "M", "ᴗ"),
+ (0x1D56, "M", "p"),
+ (0x1D57, "M", "t"),
+ (0x1D58, "M", "u"),
+ (0x1D59, "M", "ᴝ"),
+ (0x1D5A, "M", "ɯ"),
+ (0x1D5B, "M", "v"),
+ (0x1D5C, "M", "ᴥ"),
+ (0x1D5D, "M", "β"),
+ (0x1D5E, "M", "γ"),
+ (0x1D5F, "M", "δ"),
+ (0x1D60, "M", "φ"),
+ (0x1D61, "M", "χ"),
+ (0x1D62, "M", "i"),
+ (0x1D63, "M", "r"),
+ (0x1D64, "M", "u"),
+ (0x1D65, "M", "v"),
+ (0x1D66, "M", "β"),
+ (0x1D67, "M", "γ"),
+ (0x1D68, "M", "ρ"),
+ (0x1D69, "M", "φ"),
+ (0x1D6A, "M", "χ"),
+ (0x1D6B, "V"),
+ (0x1D78, "M", "н"),
+ (0x1D79, "V"),
+ (0x1D9B, "M", "ɒ"),
+ (0x1D9C, "M", "c"),
+ (0x1D9D, "M", "ɕ"),
+ (0x1D9E, "M", "ð"),
+ (0x1D9F, "M", "ɜ"),
+ (0x1DA0, "M", "f"),
+ (0x1DA1, "M", "ɟ"),
+ (0x1DA2, "M", "ɡ"),
+ (0x1DA3, "M", "ɥ"),
+ (0x1DA4, "M", "ɨ"),
+ (0x1DA5, "M", "ɩ"),
+ (0x1DA6, "M", "ɪ"),
+ (0x1DA7, "M", "ᵻ"),
+ (0x1DA8, "M", "ʝ"),
+ (0x1DA9, "M", "ɭ"),
+ (0x1DAA, "M", "ᶅ"),
+ (0x1DAB, "M", "ʟ"),
+ (0x1DAC, "M", "ɱ"),
+ (0x1DAD, "M", "ɰ"),
+ (0x1DAE, "M", "ɲ"),
+ (0x1DAF, "M", "ɳ"),
+ (0x1DB0, "M", "ɴ"),
+ (0x1DB1, "M", "ɵ"),
+ (0x1DB2, "M", "ɸ"),
+ (0x1DB3, "M", "ʂ"),
+ (0x1DB4, "M", "ʃ"),
+ (0x1DB5, "M", "ƫ"),
+ (0x1DB6, "M", "ʉ"),
+ (0x1DB7, "M", "ʊ"),
+ (0x1DB8, "M", "ᴜ"),
+ (0x1DB9, "M", "ʋ"),
+ (0x1DBA, "M", "ʌ"),
+ (0x1DBB, "M", "z"),
+ (0x1DBC, "M", "ʐ"),
+ (0x1DBD, "M", "ʑ"),
+ (0x1DBE, "M", "ʒ"),
+ (0x1DBF, "M", "θ"),
+ (0x1DC0, "V"),
+ (0x1E00, "M", "ḁ"),
+ (0x1E01, "V"),
+ (0x1E02, "M", "ḃ"),
+ (0x1E03, "V"),
+ (0x1E04, "M", "ḅ"),
+ (0x1E05, "V"),
+ (0x1E06, "M", "ḇ"),
+ (0x1E07, "V"),
+ (0x1E08, "M", "ḉ"),
+ (0x1E09, "V"),
+ (0x1E0A, "M", "ḋ"),
+ (0x1E0B, "V"),
+ (0x1E0C, "M", "ḍ"),
+ (0x1E0D, "V"),
+ (0x1E0E, "M", "ḏ"),
+ (0x1E0F, "V"),
+ (0x1E10, "M", "ḑ"),
+ (0x1E11, "V"),
+ (0x1E12, "M", "ḓ"),
+ (0x1E13, "V"),
+ (0x1E14, "M", "ḕ"),
+ (0x1E15, "V"),
+ (0x1E16, "M", "ḗ"),
+ (0x1E17, "V"),
+ (0x1E18, "M", "ḙ"),
+ (0x1E19, "V"),
+ (0x1E1A, "M", "ḛ"),
+ (0x1E1B, "V"),
+ (0x1E1C, "M", "ḝ"),
+ (0x1E1D, "V"),
+ (0x1E1E, "M", "ḟ"),
+ (0x1E1F, "V"),
+ (0x1E20, "M", "ḡ"),
+ (0x1E21, "V"),
+ (0x1E22, "M", "ḣ"),
+ (0x1E23, "V"),
+ ]
+
+
+def _seg_17() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1E24, "M", "ḥ"),
+ (0x1E25, "V"),
+ (0x1E26, "M", "ḧ"),
+ (0x1E27, "V"),
+ (0x1E28, "M", "ḩ"),
+ (0x1E29, "V"),
+ (0x1E2A, "M", "ḫ"),
+ (0x1E2B, "V"),
+ (0x1E2C, "M", "ḭ"),
+ (0x1E2D, "V"),
+ (0x1E2E, "M", "ḯ"),
+ (0x1E2F, "V"),
+ (0x1E30, "M", "ḱ"),
+ (0x1E31, "V"),
+ (0x1E32, "M", "ḳ"),
+ (0x1E33, "V"),
+ (0x1E34, "M", "ḵ"),
+ (0x1E35, "V"),
+ (0x1E36, "M", "ḷ"),
+ (0x1E37, "V"),
+ (0x1E38, "M", "ḹ"),
+ (0x1E39, "V"),
+ (0x1E3A, "M", "ḻ"),
+ (0x1E3B, "V"),
+ (0x1E3C, "M", "ḽ"),
+ (0x1E3D, "V"),
+ (0x1E3E, "M", "ḿ"),
+ (0x1E3F, "V"),
+ (0x1E40, "M", "ṁ"),
+ (0x1E41, "V"),
+ (0x1E42, "M", "ṃ"),
+ (0x1E43, "V"),
+ (0x1E44, "M", "ṅ"),
+ (0x1E45, "V"),
+ (0x1E46, "M", "ṇ"),
+ (0x1E47, "V"),
+ (0x1E48, "M", "ṉ"),
+ (0x1E49, "V"),
+ (0x1E4A, "M", "ṋ"),
+ (0x1E4B, "V"),
+ (0x1E4C, "M", "ṍ"),
+ (0x1E4D, "V"),
+ (0x1E4E, "M", "ṏ"),
+ (0x1E4F, "V"),
+ (0x1E50, "M", "ṑ"),
+ (0x1E51, "V"),
+ (0x1E52, "M", "ṓ"),
+ (0x1E53, "V"),
+ (0x1E54, "M", "ṕ"),
+ (0x1E55, "V"),
+ (0x1E56, "M", "ṗ"),
+ (0x1E57, "V"),
+ (0x1E58, "M", "ṙ"),
+ (0x1E59, "V"),
+ (0x1E5A, "M", "ṛ"),
+ (0x1E5B, "V"),
+ (0x1E5C, "M", "ṝ"),
+ (0x1E5D, "V"),
+ (0x1E5E, "M", "ṟ"),
+ (0x1E5F, "V"),
+ (0x1E60, "M", "ṡ"),
+ (0x1E61, "V"),
+ (0x1E62, "M", "ṣ"),
+ (0x1E63, "V"),
+ (0x1E64, "M", "ṥ"),
+ (0x1E65, "V"),
+ (0x1E66, "M", "ṧ"),
+ (0x1E67, "V"),
+ (0x1E68, "M", "ṩ"),
+ (0x1E69, "V"),
+ (0x1E6A, "M", "ṫ"),
+ (0x1E6B, "V"),
+ (0x1E6C, "M", "ṭ"),
+ (0x1E6D, "V"),
+ (0x1E6E, "M", "ṯ"),
+ (0x1E6F, "V"),
+ (0x1E70, "M", "ṱ"),
+ (0x1E71, "V"),
+ (0x1E72, "M", "ṳ"),
+ (0x1E73, "V"),
+ (0x1E74, "M", "ṵ"),
+ (0x1E75, "V"),
+ (0x1E76, "M", "ṷ"),
+ (0x1E77, "V"),
+ (0x1E78, "M", "ṹ"),
+ (0x1E79, "V"),
+ (0x1E7A, "M", "ṻ"),
+ (0x1E7B, "V"),
+ (0x1E7C, "M", "ṽ"),
+ (0x1E7D, "V"),
+ (0x1E7E, "M", "ṿ"),
+ (0x1E7F, "V"),
+ (0x1E80, "M", "ẁ"),
+ (0x1E81, "V"),
+ (0x1E82, "M", "ẃ"),
+ (0x1E83, "V"),
+ (0x1E84, "M", "ẅ"),
+ (0x1E85, "V"),
+ (0x1E86, "M", "ẇ"),
+ (0x1E87, "V"),
+ ]
+
+
+def _seg_18() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1E88, "M", "ẉ"),
+ (0x1E89, "V"),
+ (0x1E8A, "M", "ẋ"),
+ (0x1E8B, "V"),
+ (0x1E8C, "M", "ẍ"),
+ (0x1E8D, "V"),
+ (0x1E8E, "M", "ẏ"),
+ (0x1E8F, "V"),
+ (0x1E90, "M", "ẑ"),
+ (0x1E91, "V"),
+ (0x1E92, "M", "ẓ"),
+ (0x1E93, "V"),
+ (0x1E94, "M", "ẕ"),
+ (0x1E95, "V"),
+ (0x1E9A, "M", "aʾ"),
+ (0x1E9B, "M", "ṡ"),
+ (0x1E9C, "V"),
+ (0x1E9E, "M", "ß"),
+ (0x1E9F, "V"),
+ (0x1EA0, "M", "ạ"),
+ (0x1EA1, "V"),
+ (0x1EA2, "M", "ả"),
+ (0x1EA3, "V"),
+ (0x1EA4, "M", "ấ"),
+ (0x1EA5, "V"),
+ (0x1EA6, "M", "ầ"),
+ (0x1EA7, "V"),
+ (0x1EA8, "M", "ẩ"),
+ (0x1EA9, "V"),
+ (0x1EAA, "M", "ẫ"),
+ (0x1EAB, "V"),
+ (0x1EAC, "M", "ậ"),
+ (0x1EAD, "V"),
+ (0x1EAE, "M", "ắ"),
+ (0x1EAF, "V"),
+ (0x1EB0, "M", "ằ"),
+ (0x1EB1, "V"),
+ (0x1EB2, "M", "ẳ"),
+ (0x1EB3, "V"),
+ (0x1EB4, "M", "ẵ"),
+ (0x1EB5, "V"),
+ (0x1EB6, "M", "ặ"),
+ (0x1EB7, "V"),
+ (0x1EB8, "M", "ẹ"),
+ (0x1EB9, "V"),
+ (0x1EBA, "M", "ẻ"),
+ (0x1EBB, "V"),
+ (0x1EBC, "M", "ẽ"),
+ (0x1EBD, "V"),
+ (0x1EBE, "M", "ế"),
+ (0x1EBF, "V"),
+ (0x1EC0, "M", "ề"),
+ (0x1EC1, "V"),
+ (0x1EC2, "M", "ể"),
+ (0x1EC3, "V"),
+ (0x1EC4, "M", "ễ"),
+ (0x1EC5, "V"),
+ (0x1EC6, "M", "ệ"),
+ (0x1EC7, "V"),
+ (0x1EC8, "M", "ỉ"),
+ (0x1EC9, "V"),
+ (0x1ECA, "M", "ị"),
+ (0x1ECB, "V"),
+ (0x1ECC, "M", "ọ"),
+ (0x1ECD, "V"),
+ (0x1ECE, "M", "ỏ"),
+ (0x1ECF, "V"),
+ (0x1ED0, "M", "ố"),
+ (0x1ED1, "V"),
+ (0x1ED2, "M", "ồ"),
+ (0x1ED3, "V"),
+ (0x1ED4, "M", "ổ"),
+ (0x1ED5, "V"),
+ (0x1ED6, "M", "ỗ"),
+ (0x1ED7, "V"),
+ (0x1ED8, "M", "ộ"),
+ (0x1ED9, "V"),
+ (0x1EDA, "M", "ớ"),
+ (0x1EDB, "V"),
+ (0x1EDC, "M", "ờ"),
+ (0x1EDD, "V"),
+ (0x1EDE, "M", "ở"),
+ (0x1EDF, "V"),
+ (0x1EE0, "M", "ỡ"),
+ (0x1EE1, "V"),
+ (0x1EE2, "M", "ợ"),
+ (0x1EE3, "V"),
+ (0x1EE4, "M", "ụ"),
+ (0x1EE5, "V"),
+ (0x1EE6, "M", "ủ"),
+ (0x1EE7, "V"),
+ (0x1EE8, "M", "ứ"),
+ (0x1EE9, "V"),
+ (0x1EEA, "M", "ừ"),
+ (0x1EEB, "V"),
+ (0x1EEC, "M", "ử"),
+ (0x1EED, "V"),
+ (0x1EEE, "M", "ữ"),
+ (0x1EEF, "V"),
+ (0x1EF0, "M", "ự"),
+ ]
+
+
+def _seg_19() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1EF1, "V"),
+ (0x1EF2, "M", "ỳ"),
+ (0x1EF3, "V"),
+ (0x1EF4, "M", "ỵ"),
+ (0x1EF5, "V"),
+ (0x1EF6, "M", "ỷ"),
+ (0x1EF7, "V"),
+ (0x1EF8, "M", "ỹ"),
+ (0x1EF9, "V"),
+ (0x1EFA, "M", "ỻ"),
+ (0x1EFB, "V"),
+ (0x1EFC, "M", "ỽ"),
+ (0x1EFD, "V"),
+ (0x1EFE, "M", "ỿ"),
+ (0x1EFF, "V"),
+ (0x1F08, "M", "ἀ"),
+ (0x1F09, "M", "ἁ"),
+ (0x1F0A, "M", "ἂ"),
+ (0x1F0B, "M", "ἃ"),
+ (0x1F0C, "M", "ἄ"),
+ (0x1F0D, "M", "ἅ"),
+ (0x1F0E, "M", "ἆ"),
+ (0x1F0F, "M", "ἇ"),
+ (0x1F10, "V"),
+ (0x1F16, "X"),
+ (0x1F18, "M", "ἐ"),
+ (0x1F19, "M", "ἑ"),
+ (0x1F1A, "M", "ἒ"),
+ (0x1F1B, "M", "ἓ"),
+ (0x1F1C, "M", "ἔ"),
+ (0x1F1D, "M", "ἕ"),
+ (0x1F1E, "X"),
+ (0x1F20, "V"),
+ (0x1F28, "M", "ἠ"),
+ (0x1F29, "M", "ἡ"),
+ (0x1F2A, "M", "ἢ"),
+ (0x1F2B, "M", "ἣ"),
+ (0x1F2C, "M", "ἤ"),
+ (0x1F2D, "M", "ἥ"),
+ (0x1F2E, "M", "ἦ"),
+ (0x1F2F, "M", "ἧ"),
+ (0x1F30, "V"),
+ (0x1F38, "M", "ἰ"),
+ (0x1F39, "M", "ἱ"),
+ (0x1F3A, "M", "ἲ"),
+ (0x1F3B, "M", "ἳ"),
+ (0x1F3C, "M", "ἴ"),
+ (0x1F3D, "M", "ἵ"),
+ (0x1F3E, "M", "ἶ"),
+ (0x1F3F, "M", "ἷ"),
+ (0x1F40, "V"),
+ (0x1F46, "X"),
+ (0x1F48, "M", "ὀ"),
+ (0x1F49, "M", "ὁ"),
+ (0x1F4A, "M", "ὂ"),
+ (0x1F4B, "M", "ὃ"),
+ (0x1F4C, "M", "ὄ"),
+ (0x1F4D, "M", "ὅ"),
+ (0x1F4E, "X"),
+ (0x1F50, "V"),
+ (0x1F58, "X"),
+ (0x1F59, "M", "ὑ"),
+ (0x1F5A, "X"),
+ (0x1F5B, "M", "ὓ"),
+ (0x1F5C, "X"),
+ (0x1F5D, "M", "ὕ"),
+ (0x1F5E, "X"),
+ (0x1F5F, "M", "ὗ"),
+ (0x1F60, "V"),
+ (0x1F68, "M", "ὠ"),
+ (0x1F69, "M", "ὡ"),
+ (0x1F6A, "M", "ὢ"),
+ (0x1F6B, "M", "ὣ"),
+ (0x1F6C, "M", "ὤ"),
+ (0x1F6D, "M", "ὥ"),
+ (0x1F6E, "M", "ὦ"),
+ (0x1F6F, "M", "ὧ"),
+ (0x1F70, "V"),
+ (0x1F71, "M", "ά"),
+ (0x1F72, "V"),
+ (0x1F73, "M", "έ"),
+ (0x1F74, "V"),
+ (0x1F75, "M", "ή"),
+ (0x1F76, "V"),
+ (0x1F77, "M", "ί"),
+ (0x1F78, "V"),
+ (0x1F79, "M", "ό"),
+ (0x1F7A, "V"),
+ (0x1F7B, "M", "ύ"),
+ (0x1F7C, "V"),
+ (0x1F7D, "M", "ώ"),
+ (0x1F7E, "X"),
+ (0x1F80, "M", "ἀι"),
+ (0x1F81, "M", "ἁι"),
+ (0x1F82, "M", "ἂι"),
+ (0x1F83, "M", "ἃι"),
+ (0x1F84, "M", "ἄι"),
+ (0x1F85, "M", "ἅι"),
+ (0x1F86, "M", "ἆι"),
+ (0x1F87, "M", "ἇι"),
+ ]
+
+
+def _seg_20() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1F88, "M", "ἀι"),
+ (0x1F89, "M", "ἁι"),
+ (0x1F8A, "M", "ἂι"),
+ (0x1F8B, "M", "ἃι"),
+ (0x1F8C, "M", "ἄι"),
+ (0x1F8D, "M", "ἅι"),
+ (0x1F8E, "M", "ἆι"),
+ (0x1F8F, "M", "ἇι"),
+ (0x1F90, "M", "ἠι"),
+ (0x1F91, "M", "ἡι"),
+ (0x1F92, "M", "ἢι"),
+ (0x1F93, "M", "ἣι"),
+ (0x1F94, "M", "ἤι"),
+ (0x1F95, "M", "ἥι"),
+ (0x1F96, "M", "ἦι"),
+ (0x1F97, "M", "ἧι"),
+ (0x1F98, "M", "ἠι"),
+ (0x1F99, "M", "ἡι"),
+ (0x1F9A, "M", "ἢι"),
+ (0x1F9B, "M", "ἣι"),
+ (0x1F9C, "M", "ἤι"),
+ (0x1F9D, "M", "ἥι"),
+ (0x1F9E, "M", "ἦι"),
+ (0x1F9F, "M", "ἧι"),
+ (0x1FA0, "M", "ὠι"),
+ (0x1FA1, "M", "ὡι"),
+ (0x1FA2, "M", "ὢι"),
+ (0x1FA3, "M", "ὣι"),
+ (0x1FA4, "M", "ὤι"),
+ (0x1FA5, "M", "ὥι"),
+ (0x1FA6, "M", "ὦι"),
+ (0x1FA7, "M", "ὧι"),
+ (0x1FA8, "M", "ὠι"),
+ (0x1FA9, "M", "ὡι"),
+ (0x1FAA, "M", "ὢι"),
+ (0x1FAB, "M", "ὣι"),
+ (0x1FAC, "M", "ὤι"),
+ (0x1FAD, "M", "ὥι"),
+ (0x1FAE, "M", "ὦι"),
+ (0x1FAF, "M", "ὧι"),
+ (0x1FB0, "V"),
+ (0x1FB2, "M", "ὰι"),
+ (0x1FB3, "M", "αι"),
+ (0x1FB4, "M", "άι"),
+ (0x1FB5, "X"),
+ (0x1FB6, "V"),
+ (0x1FB7, "M", "ᾶι"),
+ (0x1FB8, "M", "ᾰ"),
+ (0x1FB9, "M", "ᾱ"),
+ (0x1FBA, "M", "ὰ"),
+ (0x1FBB, "M", "ά"),
+ (0x1FBC, "M", "αι"),
+ (0x1FBD, "3", " ̓"),
+ (0x1FBE, "M", "ι"),
+ (0x1FBF, "3", " ̓"),
+ (0x1FC0, "3", " ͂"),
+ (0x1FC1, "3", " ̈͂"),
+ (0x1FC2, "M", "ὴι"),
+ (0x1FC3, "M", "ηι"),
+ (0x1FC4, "M", "ήι"),
+ (0x1FC5, "X"),
+ (0x1FC6, "V"),
+ (0x1FC7, "M", "ῆι"),
+ (0x1FC8, "M", "ὲ"),
+ (0x1FC9, "M", "έ"),
+ (0x1FCA, "M", "ὴ"),
+ (0x1FCB, "M", "ή"),
+ (0x1FCC, "M", "ηι"),
+ (0x1FCD, "3", " ̓̀"),
+ (0x1FCE, "3", " ̓́"),
+ (0x1FCF, "3", " ̓͂"),
+ (0x1FD0, "V"),
+ (0x1FD3, "M", "ΐ"),
+ (0x1FD4, "X"),
+ (0x1FD6, "V"),
+ (0x1FD8, "M", "ῐ"),
+ (0x1FD9, "M", "ῑ"),
+ (0x1FDA, "M", "ὶ"),
+ (0x1FDB, "M", "ί"),
+ (0x1FDC, "X"),
+ (0x1FDD, "3", " ̔̀"),
+ (0x1FDE, "3", " ̔́"),
+ (0x1FDF, "3", " ̔͂"),
+ (0x1FE0, "V"),
+ (0x1FE3, "M", "ΰ"),
+ (0x1FE4, "V"),
+ (0x1FE8, "M", "ῠ"),
+ (0x1FE9, "M", "ῡ"),
+ (0x1FEA, "M", "ὺ"),
+ (0x1FEB, "M", "ύ"),
+ (0x1FEC, "M", "ῥ"),
+ (0x1FED, "3", " ̈̀"),
+ (0x1FEE, "3", " ̈́"),
+ (0x1FEF, "3", "`"),
+ (0x1FF0, "X"),
+ (0x1FF2, "M", "ὼι"),
+ (0x1FF3, "M", "ωι"),
+ (0x1FF4, "M", "ώι"),
+ (0x1FF5, "X"),
+ (0x1FF6, "V"),
+ ]
+
+
+def _seg_21() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1FF7, "M", "ῶι"),
+ (0x1FF8, "M", "ὸ"),
+ (0x1FF9, "M", "ό"),
+ (0x1FFA, "M", "ὼ"),
+ (0x1FFB, "M", "ώ"),
+ (0x1FFC, "M", "ωι"),
+ (0x1FFD, "3", " ́"),
+ (0x1FFE, "3", " ̔"),
+ (0x1FFF, "X"),
+ (0x2000, "3", " "),
+ (0x200B, "I"),
+ (0x200C, "D", ""),
+ (0x200E, "X"),
+ (0x2010, "V"),
+ (0x2011, "M", "‐"),
+ (0x2012, "V"),
+ (0x2017, "3", " ̳"),
+ (0x2018, "V"),
+ (0x2024, "X"),
+ (0x2027, "V"),
+ (0x2028, "X"),
+ (0x202F, "3", " "),
+ (0x2030, "V"),
+ (0x2033, "M", "′′"),
+ (0x2034, "M", "′′′"),
+ (0x2035, "V"),
+ (0x2036, "M", "‵‵"),
+ (0x2037, "M", "‵‵‵"),
+ (0x2038, "V"),
+ (0x203C, "3", "!!"),
+ (0x203D, "V"),
+ (0x203E, "3", " ̅"),
+ (0x203F, "V"),
+ (0x2047, "3", "??"),
+ (0x2048, "3", "?!"),
+ (0x2049, "3", "!?"),
+ (0x204A, "V"),
+ (0x2057, "M", "′′′′"),
+ (0x2058, "V"),
+ (0x205F, "3", " "),
+ (0x2060, "I"),
+ (0x2061, "X"),
+ (0x2064, "I"),
+ (0x2065, "X"),
+ (0x2070, "M", "0"),
+ (0x2071, "M", "i"),
+ (0x2072, "X"),
+ (0x2074, "M", "4"),
+ (0x2075, "M", "5"),
+ (0x2076, "M", "6"),
+ (0x2077, "M", "7"),
+ (0x2078, "M", "8"),
+ (0x2079, "M", "9"),
+ (0x207A, "3", "+"),
+ (0x207B, "M", "−"),
+ (0x207C, "3", "="),
+ (0x207D, "3", "("),
+ (0x207E, "3", ")"),
+ (0x207F, "M", "n"),
+ (0x2080, "M", "0"),
+ (0x2081, "M", "1"),
+ (0x2082, "M", "2"),
+ (0x2083, "M", "3"),
+ (0x2084, "M", "4"),
+ (0x2085, "M", "5"),
+ (0x2086, "M", "6"),
+ (0x2087, "M", "7"),
+ (0x2088, "M", "8"),
+ (0x2089, "M", "9"),
+ (0x208A, "3", "+"),
+ (0x208B, "M", "−"),
+ (0x208C, "3", "="),
+ (0x208D, "3", "("),
+ (0x208E, "3", ")"),
+ (0x208F, "X"),
+ (0x2090, "M", "a"),
+ (0x2091, "M", "e"),
+ (0x2092, "M", "o"),
+ (0x2093, "M", "x"),
+ (0x2094, "M", "ə"),
+ (0x2095, "M", "h"),
+ (0x2096, "M", "k"),
+ (0x2097, "M", "l"),
+ (0x2098, "M", "m"),
+ (0x2099, "M", "n"),
+ (0x209A, "M", "p"),
+ (0x209B, "M", "s"),
+ (0x209C, "M", "t"),
+ (0x209D, "X"),
+ (0x20A0, "V"),
+ (0x20A8, "M", "rs"),
+ (0x20A9, "V"),
+ (0x20C1, "X"),
+ (0x20D0, "V"),
+ (0x20F1, "X"),
+ (0x2100, "3", "a/c"),
+ (0x2101, "3", "a/s"),
+ (0x2102, "M", "c"),
+ (0x2103, "M", "°c"),
+ (0x2104, "V"),
+ ]
+
+
+def _seg_22() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x2105, "3", "c/o"),
+ (0x2106, "3", "c/u"),
+ (0x2107, "M", "ɛ"),
+ (0x2108, "V"),
+ (0x2109, "M", "°f"),
+ (0x210A, "M", "g"),
+ (0x210B, "M", "h"),
+ (0x210F, "M", "ħ"),
+ (0x2110, "M", "i"),
+ (0x2112, "M", "l"),
+ (0x2114, "V"),
+ (0x2115, "M", "n"),
+ (0x2116, "M", "no"),
+ (0x2117, "V"),
+ (0x2119, "M", "p"),
+ (0x211A, "M", "q"),
+ (0x211B, "M", "r"),
+ (0x211E, "V"),
+ (0x2120, "M", "sm"),
+ (0x2121, "M", "tel"),
+ (0x2122, "M", "tm"),
+ (0x2123, "V"),
+ (0x2124, "M", "z"),
+ (0x2125, "V"),
+ (0x2126, "M", "ω"),
+ (0x2127, "V"),
+ (0x2128, "M", "z"),
+ (0x2129, "V"),
+ (0x212A, "M", "k"),
+ (0x212B, "M", "å"),
+ (0x212C, "M", "b"),
+ (0x212D, "M", "c"),
+ (0x212E, "V"),
+ (0x212F, "M", "e"),
+ (0x2131, "M", "f"),
+ (0x2132, "X"),
+ (0x2133, "M", "m"),
+ (0x2134, "M", "o"),
+ (0x2135, "M", "א"),
+ (0x2136, "M", "ב"),
+ (0x2137, "M", "ג"),
+ (0x2138, "M", "ד"),
+ (0x2139, "M", "i"),
+ (0x213A, "V"),
+ (0x213B, "M", "fax"),
+ (0x213C, "M", "π"),
+ (0x213D, "M", "γ"),
+ (0x213F, "M", "π"),
+ (0x2140, "M", "∑"),
+ (0x2141, "V"),
+ (0x2145, "M", "d"),
+ (0x2147, "M", "e"),
+ (0x2148, "M", "i"),
+ (0x2149, "M", "j"),
+ (0x214A, "V"),
+ (0x2150, "M", "1⁄7"),
+ (0x2151, "M", "1⁄9"),
+ (0x2152, "M", "1⁄10"),
+ (0x2153, "M", "1⁄3"),
+ (0x2154, "M", "2⁄3"),
+ (0x2155, "M", "1⁄5"),
+ (0x2156, "M", "2⁄5"),
+ (0x2157, "M", "3⁄5"),
+ (0x2158, "M", "4⁄5"),
+ (0x2159, "M", "1⁄6"),
+ (0x215A, "M", "5⁄6"),
+ (0x215B, "M", "1⁄8"),
+ (0x215C, "M", "3⁄8"),
+ (0x215D, "M", "5⁄8"),
+ (0x215E, "M", "7⁄8"),
+ (0x215F, "M", "1⁄"),
+ (0x2160, "M", "i"),
+ (0x2161, "M", "ii"),
+ (0x2162, "M", "iii"),
+ (0x2163, "M", "iv"),
+ (0x2164, "M", "v"),
+ (0x2165, "M", "vi"),
+ (0x2166, "M", "vii"),
+ (0x2167, "M", "viii"),
+ (0x2168, "M", "ix"),
+ (0x2169, "M", "x"),
+ (0x216A, "M", "xi"),
+ (0x216B, "M", "xii"),
+ (0x216C, "M", "l"),
+ (0x216D, "M", "c"),
+ (0x216E, "M", "d"),
+ (0x216F, "M", "m"),
+ (0x2170, "M", "i"),
+ (0x2171, "M", "ii"),
+ (0x2172, "M", "iii"),
+ (0x2173, "M", "iv"),
+ (0x2174, "M", "v"),
+ (0x2175, "M", "vi"),
+ (0x2176, "M", "vii"),
+ (0x2177, "M", "viii"),
+ (0x2178, "M", "ix"),
+ (0x2179, "M", "x"),
+ (0x217A, "M", "xi"),
+ (0x217B, "M", "xii"),
+ (0x217C, "M", "l"),
+ ]
+
+
+def _seg_23() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x217D, "M", "c"),
+ (0x217E, "M", "d"),
+ (0x217F, "M", "m"),
+ (0x2180, "V"),
+ (0x2183, "X"),
+ (0x2184, "V"),
+ (0x2189, "M", "0⁄3"),
+ (0x218A, "V"),
+ (0x218C, "X"),
+ (0x2190, "V"),
+ (0x222C, "M", "∫∫"),
+ (0x222D, "M", "∫∫∫"),
+ (0x222E, "V"),
+ (0x222F, "M", "∮∮"),
+ (0x2230, "M", "∮∮∮"),
+ (0x2231, "V"),
+ (0x2329, "M", "〈"),
+ (0x232A, "M", "〉"),
+ (0x232B, "V"),
+ (0x2427, "X"),
+ (0x2440, "V"),
+ (0x244B, "X"),
+ (0x2460, "M", "1"),
+ (0x2461, "M", "2"),
+ (0x2462, "M", "3"),
+ (0x2463, "M", "4"),
+ (0x2464, "M", "5"),
+ (0x2465, "M", "6"),
+ (0x2466, "M", "7"),
+ (0x2467, "M", "8"),
+ (0x2468, "M", "9"),
+ (0x2469, "M", "10"),
+ (0x246A, "M", "11"),
+ (0x246B, "M", "12"),
+ (0x246C, "M", "13"),
+ (0x246D, "M", "14"),
+ (0x246E, "M", "15"),
+ (0x246F, "M", "16"),
+ (0x2470, "M", "17"),
+ (0x2471, "M", "18"),
+ (0x2472, "M", "19"),
+ (0x2473, "M", "20"),
+ (0x2474, "3", "(1)"),
+ (0x2475, "3", "(2)"),
+ (0x2476, "3", "(3)"),
+ (0x2477, "3", "(4)"),
+ (0x2478, "3", "(5)"),
+ (0x2479, "3", "(6)"),
+ (0x247A, "3", "(7)"),
+ (0x247B, "3", "(8)"),
+ (0x247C, "3", "(9)"),
+ (0x247D, "3", "(10)"),
+ (0x247E, "3", "(11)"),
+ (0x247F, "3", "(12)"),
+ (0x2480, "3", "(13)"),
+ (0x2481, "3", "(14)"),
+ (0x2482, "3", "(15)"),
+ (0x2483, "3", "(16)"),
+ (0x2484, "3", "(17)"),
+ (0x2485, "3", "(18)"),
+ (0x2486, "3", "(19)"),
+ (0x2487, "3", "(20)"),
+ (0x2488, "X"),
+ (0x249C, "3", "(a)"),
+ (0x249D, "3", "(b)"),
+ (0x249E, "3", "(c)"),
+ (0x249F, "3", "(d)"),
+ (0x24A0, "3", "(e)"),
+ (0x24A1, "3", "(f)"),
+ (0x24A2, "3", "(g)"),
+ (0x24A3, "3", "(h)"),
+ (0x24A4, "3", "(i)"),
+ (0x24A5, "3", "(j)"),
+ (0x24A6, "3", "(k)"),
+ (0x24A7, "3", "(l)"),
+ (0x24A8, "3", "(m)"),
+ (0x24A9, "3", "(n)"),
+ (0x24AA, "3", "(o)"),
+ (0x24AB, "3", "(p)"),
+ (0x24AC, "3", "(q)"),
+ (0x24AD, "3", "(r)"),
+ (0x24AE, "3", "(s)"),
+ (0x24AF, "3", "(t)"),
+ (0x24B0, "3", "(u)"),
+ (0x24B1, "3", "(v)"),
+ (0x24B2, "3", "(w)"),
+ (0x24B3, "3", "(x)"),
+ (0x24B4, "3", "(y)"),
+ (0x24B5, "3", "(z)"),
+ (0x24B6, "M", "a"),
+ (0x24B7, "M", "b"),
+ (0x24B8, "M", "c"),
+ (0x24B9, "M", "d"),
+ (0x24BA, "M", "e"),
+ (0x24BB, "M", "f"),
+ (0x24BC, "M", "g"),
+ (0x24BD, "M", "h"),
+ (0x24BE, "M", "i"),
+ (0x24BF, "M", "j"),
+ (0x24C0, "M", "k"),
+ ]
+
+
+def _seg_24() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x24C1, "M", "l"),
+ (0x24C2, "M", "m"),
+ (0x24C3, "M", "n"),
+ (0x24C4, "M", "o"),
+ (0x24C5, "M", "p"),
+ (0x24C6, "M", "q"),
+ (0x24C7, "M", "r"),
+ (0x24C8, "M", "s"),
+ (0x24C9, "M", "t"),
+ (0x24CA, "M", "u"),
+ (0x24CB, "M", "v"),
+ (0x24CC, "M", "w"),
+ (0x24CD, "M", "x"),
+ (0x24CE, "M", "y"),
+ (0x24CF, "M", "z"),
+ (0x24D0, "M", "a"),
+ (0x24D1, "M", "b"),
+ (0x24D2, "M", "c"),
+ (0x24D3, "M", "d"),
+ (0x24D4, "M", "e"),
+ (0x24D5, "M", "f"),
+ (0x24D6, "M", "g"),
+ (0x24D7, "M", "h"),
+ (0x24D8, "M", "i"),
+ (0x24D9, "M", "j"),
+ (0x24DA, "M", "k"),
+ (0x24DB, "M", "l"),
+ (0x24DC, "M", "m"),
+ (0x24DD, "M", "n"),
+ (0x24DE, "M", "o"),
+ (0x24DF, "M", "p"),
+ (0x24E0, "M", "q"),
+ (0x24E1, "M", "r"),
+ (0x24E2, "M", "s"),
+ (0x24E3, "M", "t"),
+ (0x24E4, "M", "u"),
+ (0x24E5, "M", "v"),
+ (0x24E6, "M", "w"),
+ (0x24E7, "M", "x"),
+ (0x24E8, "M", "y"),
+ (0x24E9, "M", "z"),
+ (0x24EA, "M", "0"),
+ (0x24EB, "V"),
+ (0x2A0C, "M", "∫∫∫∫"),
+ (0x2A0D, "V"),
+ (0x2A74, "3", "::="),
+ (0x2A75, "3", "=="),
+ (0x2A76, "3", "==="),
+ (0x2A77, "V"),
+ (0x2ADC, "M", "⫝̸"),
+ (0x2ADD, "V"),
+ (0x2B74, "X"),
+ (0x2B76, "V"),
+ (0x2B96, "X"),
+ (0x2B97, "V"),
+ (0x2C00, "M", "ⰰ"),
+ (0x2C01, "M", "ⰱ"),
+ (0x2C02, "M", "ⰲ"),
+ (0x2C03, "M", "ⰳ"),
+ (0x2C04, "M", "ⰴ"),
+ (0x2C05, "M", "ⰵ"),
+ (0x2C06, "M", "ⰶ"),
+ (0x2C07, "M", "ⰷ"),
+ (0x2C08, "M", "ⰸ"),
+ (0x2C09, "M", "ⰹ"),
+ (0x2C0A, "M", "ⰺ"),
+ (0x2C0B, "M", "ⰻ"),
+ (0x2C0C, "M", "ⰼ"),
+ (0x2C0D, "M", "ⰽ"),
+ (0x2C0E, "M", "ⰾ"),
+ (0x2C0F, "M", "ⰿ"),
+ (0x2C10, "M", "ⱀ"),
+ (0x2C11, "M", "ⱁ"),
+ (0x2C12, "M", "ⱂ"),
+ (0x2C13, "M", "ⱃ"),
+ (0x2C14, "M", "ⱄ"),
+ (0x2C15, "M", "ⱅ"),
+ (0x2C16, "M", "ⱆ"),
+ (0x2C17, "M", "ⱇ"),
+ (0x2C18, "M", "ⱈ"),
+ (0x2C19, "M", "ⱉ"),
+ (0x2C1A, "M", "ⱊ"),
+ (0x2C1B, "M", "ⱋ"),
+ (0x2C1C, "M", "ⱌ"),
+ (0x2C1D, "M", "ⱍ"),
+ (0x2C1E, "M", "ⱎ"),
+ (0x2C1F, "M", "ⱏ"),
+ (0x2C20, "M", "ⱐ"),
+ (0x2C21, "M", "ⱑ"),
+ (0x2C22, "M", "ⱒ"),
+ (0x2C23, "M", "ⱓ"),
+ (0x2C24, "M", "ⱔ"),
+ (0x2C25, "M", "ⱕ"),
+ (0x2C26, "M", "ⱖ"),
+ (0x2C27, "M", "ⱗ"),
+ (0x2C28, "M", "ⱘ"),
+ (0x2C29, "M", "ⱙ"),
+ (0x2C2A, "M", "ⱚ"),
+ (0x2C2B, "M", "ⱛ"),
+ (0x2C2C, "M", "ⱜ"),
+ ]
+
+
+def _seg_25() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x2C2D, "M", "ⱝ"),
+ (0x2C2E, "M", "ⱞ"),
+ (0x2C2F, "M", "ⱟ"),
+ (0x2C30, "V"),
+ (0x2C60, "M", "ⱡ"),
+ (0x2C61, "V"),
+ (0x2C62, "M", "ɫ"),
+ (0x2C63, "M", "ᵽ"),
+ (0x2C64, "M", "ɽ"),
+ (0x2C65, "V"),
+ (0x2C67, "M", "ⱨ"),
+ (0x2C68, "V"),
+ (0x2C69, "M", "ⱪ"),
+ (0x2C6A, "V"),
+ (0x2C6B, "M", "ⱬ"),
+ (0x2C6C, "V"),
+ (0x2C6D, "M", "ɑ"),
+ (0x2C6E, "M", "ɱ"),
+ (0x2C6F, "M", "ɐ"),
+ (0x2C70, "M", "ɒ"),
+ (0x2C71, "V"),
+ (0x2C72, "M", "ⱳ"),
+ (0x2C73, "V"),
+ (0x2C75, "M", "ⱶ"),
+ (0x2C76, "V"),
+ (0x2C7C, "M", "j"),
+ (0x2C7D, "M", "v"),
+ (0x2C7E, "M", "ȿ"),
+ (0x2C7F, "M", "ɀ"),
+ (0x2C80, "M", "ⲁ"),
+ (0x2C81, "V"),
+ (0x2C82, "M", "ⲃ"),
+ (0x2C83, "V"),
+ (0x2C84, "M", "ⲅ"),
+ (0x2C85, "V"),
+ (0x2C86, "M", "ⲇ"),
+ (0x2C87, "V"),
+ (0x2C88, "M", "ⲉ"),
+ (0x2C89, "V"),
+ (0x2C8A, "M", "ⲋ"),
+ (0x2C8B, "V"),
+ (0x2C8C, "M", "ⲍ"),
+ (0x2C8D, "V"),
+ (0x2C8E, "M", "ⲏ"),
+ (0x2C8F, "V"),
+ (0x2C90, "M", "ⲑ"),
+ (0x2C91, "V"),
+ (0x2C92, "M", "ⲓ"),
+ (0x2C93, "V"),
+ (0x2C94, "M", "ⲕ"),
+ (0x2C95, "V"),
+ (0x2C96, "M", "ⲗ"),
+ (0x2C97, "V"),
+ (0x2C98, "M", "ⲙ"),
+ (0x2C99, "V"),
+ (0x2C9A, "M", "ⲛ"),
+ (0x2C9B, "V"),
+ (0x2C9C, "M", "ⲝ"),
+ (0x2C9D, "V"),
+ (0x2C9E, "M", "ⲟ"),
+ (0x2C9F, "V"),
+ (0x2CA0, "M", "ⲡ"),
+ (0x2CA1, "V"),
+ (0x2CA2, "M", "ⲣ"),
+ (0x2CA3, "V"),
+ (0x2CA4, "M", "ⲥ"),
+ (0x2CA5, "V"),
+ (0x2CA6, "M", "ⲧ"),
+ (0x2CA7, "V"),
+ (0x2CA8, "M", "ⲩ"),
+ (0x2CA9, "V"),
+ (0x2CAA, "M", "ⲫ"),
+ (0x2CAB, "V"),
+ (0x2CAC, "M", "ⲭ"),
+ (0x2CAD, "V"),
+ (0x2CAE, "M", "ⲯ"),
+ (0x2CAF, "V"),
+ (0x2CB0, "M", "ⲱ"),
+ (0x2CB1, "V"),
+ (0x2CB2, "M", "ⲳ"),
+ (0x2CB3, "V"),
+ (0x2CB4, "M", "ⲵ"),
+ (0x2CB5, "V"),
+ (0x2CB6, "M", "ⲷ"),
+ (0x2CB7, "V"),
+ (0x2CB8, "M", "ⲹ"),
+ (0x2CB9, "V"),
+ (0x2CBA, "M", "ⲻ"),
+ (0x2CBB, "V"),
+ (0x2CBC, "M", "ⲽ"),
+ (0x2CBD, "V"),
+ (0x2CBE, "M", "ⲿ"),
+ (0x2CBF, "V"),
+ (0x2CC0, "M", "ⳁ"),
+ (0x2CC1, "V"),
+ (0x2CC2, "M", "ⳃ"),
+ (0x2CC3, "V"),
+ (0x2CC4, "M", "ⳅ"),
+ (0x2CC5, "V"),
+ (0x2CC6, "M", "ⳇ"),
+ ]
+
+
+def _seg_26() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x2CC7, "V"),
+ (0x2CC8, "M", "ⳉ"),
+ (0x2CC9, "V"),
+ (0x2CCA, "M", "ⳋ"),
+ (0x2CCB, "V"),
+ (0x2CCC, "M", "ⳍ"),
+ (0x2CCD, "V"),
+ (0x2CCE, "M", "ⳏ"),
+ (0x2CCF, "V"),
+ (0x2CD0, "M", "ⳑ"),
+ (0x2CD1, "V"),
+ (0x2CD2, "M", "ⳓ"),
+ (0x2CD3, "V"),
+ (0x2CD4, "M", "ⳕ"),
+ (0x2CD5, "V"),
+ (0x2CD6, "M", "ⳗ"),
+ (0x2CD7, "V"),
+ (0x2CD8, "M", "ⳙ"),
+ (0x2CD9, "V"),
+ (0x2CDA, "M", "ⳛ"),
+ (0x2CDB, "V"),
+ (0x2CDC, "M", "ⳝ"),
+ (0x2CDD, "V"),
+ (0x2CDE, "M", "ⳟ"),
+ (0x2CDF, "V"),
+ (0x2CE0, "M", "ⳡ"),
+ (0x2CE1, "V"),
+ (0x2CE2, "M", "ⳣ"),
+ (0x2CE3, "V"),
+ (0x2CEB, "M", "ⳬ"),
+ (0x2CEC, "V"),
+ (0x2CED, "M", "ⳮ"),
+ (0x2CEE, "V"),
+ (0x2CF2, "M", "ⳳ"),
+ (0x2CF3, "V"),
+ (0x2CF4, "X"),
+ (0x2CF9, "V"),
+ (0x2D26, "X"),
+ (0x2D27, "V"),
+ (0x2D28, "X"),
+ (0x2D2D, "V"),
+ (0x2D2E, "X"),
+ (0x2D30, "V"),
+ (0x2D68, "X"),
+ (0x2D6F, "M", "ⵡ"),
+ (0x2D70, "V"),
+ (0x2D71, "X"),
+ (0x2D7F, "V"),
+ (0x2D97, "X"),
+ (0x2DA0, "V"),
+ (0x2DA7, "X"),
+ (0x2DA8, "V"),
+ (0x2DAF, "X"),
+ (0x2DB0, "V"),
+ (0x2DB7, "X"),
+ (0x2DB8, "V"),
+ (0x2DBF, "X"),
+ (0x2DC0, "V"),
+ (0x2DC7, "X"),
+ (0x2DC8, "V"),
+ (0x2DCF, "X"),
+ (0x2DD0, "V"),
+ (0x2DD7, "X"),
+ (0x2DD8, "V"),
+ (0x2DDF, "X"),
+ (0x2DE0, "V"),
+ (0x2E5E, "X"),
+ (0x2E80, "V"),
+ (0x2E9A, "X"),
+ (0x2E9B, "V"),
+ (0x2E9F, "M", "母"),
+ (0x2EA0, "V"),
+ (0x2EF3, "M", "龟"),
+ (0x2EF4, "X"),
+ (0x2F00, "M", "一"),
+ (0x2F01, "M", "丨"),
+ (0x2F02, "M", "丶"),
+ (0x2F03, "M", "丿"),
+ (0x2F04, "M", "乙"),
+ (0x2F05, "M", "亅"),
+ (0x2F06, "M", "二"),
+ (0x2F07, "M", "亠"),
+ (0x2F08, "M", "人"),
+ (0x2F09, "M", "儿"),
+ (0x2F0A, "M", "入"),
+ (0x2F0B, "M", "八"),
+ (0x2F0C, "M", "冂"),
+ (0x2F0D, "M", "冖"),
+ (0x2F0E, "M", "冫"),
+ (0x2F0F, "M", "几"),
+ (0x2F10, "M", "凵"),
+ (0x2F11, "M", "刀"),
+ (0x2F12, "M", "力"),
+ (0x2F13, "M", "勹"),
+ (0x2F14, "M", "匕"),
+ (0x2F15, "M", "匚"),
+ (0x2F16, "M", "匸"),
+ (0x2F17, "M", "十"),
+ (0x2F18, "M", "卜"),
+ (0x2F19, "M", "卩"),
+ ]
+
+
+def _seg_27() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x2F1A, "M", "厂"),
+ (0x2F1B, "M", "厶"),
+ (0x2F1C, "M", "又"),
+ (0x2F1D, "M", "口"),
+ (0x2F1E, "M", "囗"),
+ (0x2F1F, "M", "土"),
+ (0x2F20, "M", "士"),
+ (0x2F21, "M", "夂"),
+ (0x2F22, "M", "夊"),
+ (0x2F23, "M", "夕"),
+ (0x2F24, "M", "大"),
+ (0x2F25, "M", "女"),
+ (0x2F26, "M", "子"),
+ (0x2F27, "M", "宀"),
+ (0x2F28, "M", "寸"),
+ (0x2F29, "M", "小"),
+ (0x2F2A, "M", "尢"),
+ (0x2F2B, "M", "尸"),
+ (0x2F2C, "M", "屮"),
+ (0x2F2D, "M", "山"),
+ (0x2F2E, "M", "巛"),
+ (0x2F2F, "M", "工"),
+ (0x2F30, "M", "己"),
+ (0x2F31, "M", "巾"),
+ (0x2F32, "M", "干"),
+ (0x2F33, "M", "幺"),
+ (0x2F34, "M", "广"),
+ (0x2F35, "M", "廴"),
+ (0x2F36, "M", "廾"),
+ (0x2F37, "M", "弋"),
+ (0x2F38, "M", "弓"),
+ (0x2F39, "M", "彐"),
+ (0x2F3A, "M", "彡"),
+ (0x2F3B, "M", "彳"),
+ (0x2F3C, "M", "心"),
+ (0x2F3D, "M", "戈"),
+ (0x2F3E, "M", "戶"),
+ (0x2F3F, "M", "手"),
+ (0x2F40, "M", "支"),
+ (0x2F41, "M", "攴"),
+ (0x2F42, "M", "文"),
+ (0x2F43, "M", "斗"),
+ (0x2F44, "M", "斤"),
+ (0x2F45, "M", "方"),
+ (0x2F46, "M", "无"),
+ (0x2F47, "M", "日"),
+ (0x2F48, "M", "曰"),
+ (0x2F49, "M", "月"),
+ (0x2F4A, "M", "木"),
+ (0x2F4B, "M", "欠"),
+ (0x2F4C, "M", "止"),
+ (0x2F4D, "M", "歹"),
+ (0x2F4E, "M", "殳"),
+ (0x2F4F, "M", "毋"),
+ (0x2F50, "M", "比"),
+ (0x2F51, "M", "毛"),
+ (0x2F52, "M", "氏"),
+ (0x2F53, "M", "气"),
+ (0x2F54, "M", "水"),
+ (0x2F55, "M", "火"),
+ (0x2F56, "M", "爪"),
+ (0x2F57, "M", "父"),
+ (0x2F58, "M", "爻"),
+ (0x2F59, "M", "爿"),
+ (0x2F5A, "M", "片"),
+ (0x2F5B, "M", "牙"),
+ (0x2F5C, "M", "牛"),
+ (0x2F5D, "M", "犬"),
+ (0x2F5E, "M", "玄"),
+ (0x2F5F, "M", "玉"),
+ (0x2F60, "M", "瓜"),
+ (0x2F61, "M", "瓦"),
+ (0x2F62, "M", "甘"),
+ (0x2F63, "M", "生"),
+ (0x2F64, "M", "用"),
+ (0x2F65, "M", "田"),
+ (0x2F66, "M", "疋"),
+ (0x2F67, "M", "疒"),
+ (0x2F68, "M", "癶"),
+ (0x2F69, "M", "白"),
+ (0x2F6A, "M", "皮"),
+ (0x2F6B, "M", "皿"),
+ (0x2F6C, "M", "目"),
+ (0x2F6D, "M", "矛"),
+ (0x2F6E, "M", "矢"),
+ (0x2F6F, "M", "石"),
+ (0x2F70, "M", "示"),
+ (0x2F71, "M", "禸"),
+ (0x2F72, "M", "禾"),
+ (0x2F73, "M", "穴"),
+ (0x2F74, "M", "立"),
+ (0x2F75, "M", "竹"),
+ (0x2F76, "M", "米"),
+ (0x2F77, "M", "糸"),
+ (0x2F78, "M", "缶"),
+ (0x2F79, "M", "网"),
+ (0x2F7A, "M", "羊"),
+ (0x2F7B, "M", "羽"),
+ (0x2F7C, "M", "老"),
+ (0x2F7D, "M", "而"),
+ ]
+
+
+def _seg_28() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x2F7E, "M", "耒"),
+ (0x2F7F, "M", "耳"),
+ (0x2F80, "M", "聿"),
+ (0x2F81, "M", "肉"),
+ (0x2F82, "M", "臣"),
+ (0x2F83, "M", "自"),
+ (0x2F84, "M", "至"),
+ (0x2F85, "M", "臼"),
+ (0x2F86, "M", "舌"),
+ (0x2F87, "M", "舛"),
+ (0x2F88, "M", "舟"),
+ (0x2F89, "M", "艮"),
+ (0x2F8A, "M", "色"),
+ (0x2F8B, "M", "艸"),
+ (0x2F8C, "M", "虍"),
+ (0x2F8D, "M", "虫"),
+ (0x2F8E, "M", "血"),
+ (0x2F8F, "M", "行"),
+ (0x2F90, "M", "衣"),
+ (0x2F91, "M", "襾"),
+ (0x2F92, "M", "見"),
+ (0x2F93, "M", "角"),
+ (0x2F94, "M", "言"),
+ (0x2F95, "M", "谷"),
+ (0x2F96, "M", "豆"),
+ (0x2F97, "M", "豕"),
+ (0x2F98, "M", "豸"),
+ (0x2F99, "M", "貝"),
+ (0x2F9A, "M", "赤"),
+ (0x2F9B, "M", "走"),
+ (0x2F9C, "M", "足"),
+ (0x2F9D, "M", "身"),
+ (0x2F9E, "M", "車"),
+ (0x2F9F, "M", "辛"),
+ (0x2FA0, "M", "辰"),
+ (0x2FA1, "M", "辵"),
+ (0x2FA2, "M", "邑"),
+ (0x2FA3, "M", "酉"),
+ (0x2FA4, "M", "釆"),
+ (0x2FA5, "M", "里"),
+ (0x2FA6, "M", "金"),
+ (0x2FA7, "M", "長"),
+ (0x2FA8, "M", "門"),
+ (0x2FA9, "M", "阜"),
+ (0x2FAA, "M", "隶"),
+ (0x2FAB, "M", "隹"),
+ (0x2FAC, "M", "雨"),
+ (0x2FAD, "M", "靑"),
+ (0x2FAE, "M", "非"),
+ (0x2FAF, "M", "面"),
+ (0x2FB0, "M", "革"),
+ (0x2FB1, "M", "韋"),
+ (0x2FB2, "M", "韭"),
+ (0x2FB3, "M", "音"),
+ (0x2FB4, "M", "頁"),
+ (0x2FB5, "M", "風"),
+ (0x2FB6, "M", "飛"),
+ (0x2FB7, "M", "食"),
+ (0x2FB8, "M", "首"),
+ (0x2FB9, "M", "香"),
+ (0x2FBA, "M", "馬"),
+ (0x2FBB, "M", "骨"),
+ (0x2FBC, "M", "高"),
+ (0x2FBD, "M", "髟"),
+ (0x2FBE, "M", "鬥"),
+ (0x2FBF, "M", "鬯"),
+ (0x2FC0, "M", "鬲"),
+ (0x2FC1, "M", "鬼"),
+ (0x2FC2, "M", "魚"),
+ (0x2FC3, "M", "鳥"),
+ (0x2FC4, "M", "鹵"),
+ (0x2FC5, "M", "鹿"),
+ (0x2FC6, "M", "麥"),
+ (0x2FC7, "M", "麻"),
+ (0x2FC8, "M", "黃"),
+ (0x2FC9, "M", "黍"),
+ (0x2FCA, "M", "黑"),
+ (0x2FCB, "M", "黹"),
+ (0x2FCC, "M", "黽"),
+ (0x2FCD, "M", "鼎"),
+ (0x2FCE, "M", "鼓"),
+ (0x2FCF, "M", "鼠"),
+ (0x2FD0, "M", "鼻"),
+ (0x2FD1, "M", "齊"),
+ (0x2FD2, "M", "齒"),
+ (0x2FD3, "M", "龍"),
+ (0x2FD4, "M", "龜"),
+ (0x2FD5, "M", "龠"),
+ (0x2FD6, "X"),
+ (0x3000, "3", " "),
+ (0x3001, "V"),
+ (0x3002, "M", "."),
+ (0x3003, "V"),
+ (0x3036, "M", "〒"),
+ (0x3037, "V"),
+ (0x3038, "M", "十"),
+ (0x3039, "M", "卄"),
+ (0x303A, "M", "卅"),
+ (0x303B, "V"),
+ (0x3040, "X"),
+ ]
+
+
+def _seg_29() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x3041, "V"),
+ (0x3097, "X"),
+ (0x3099, "V"),
+ (0x309B, "3", " ゙"),
+ (0x309C, "3", " ゚"),
+ (0x309D, "V"),
+ (0x309F, "M", "より"),
+ (0x30A0, "V"),
+ (0x30FF, "M", "コト"),
+ (0x3100, "X"),
+ (0x3105, "V"),
+ (0x3130, "X"),
+ (0x3131, "M", "ᄀ"),
+ (0x3132, "M", "ᄁ"),
+ (0x3133, "M", "ᆪ"),
+ (0x3134, "M", "ᄂ"),
+ (0x3135, "M", "ᆬ"),
+ (0x3136, "M", "ᆭ"),
+ (0x3137, "M", "ᄃ"),
+ (0x3138, "M", "ᄄ"),
+ (0x3139, "M", "ᄅ"),
+ (0x313A, "M", "ᆰ"),
+ (0x313B, "M", "ᆱ"),
+ (0x313C, "M", "ᆲ"),
+ (0x313D, "M", "ᆳ"),
+ (0x313E, "M", "ᆴ"),
+ (0x313F, "M", "ᆵ"),
+ (0x3140, "M", "ᄚ"),
+ (0x3141, "M", "ᄆ"),
+ (0x3142, "M", "ᄇ"),
+ (0x3143, "M", "ᄈ"),
+ (0x3144, "M", "ᄡ"),
+ (0x3145, "M", "ᄉ"),
+ (0x3146, "M", "ᄊ"),
+ (0x3147, "M", "ᄋ"),
+ (0x3148, "M", "ᄌ"),
+ (0x3149, "M", "ᄍ"),
+ (0x314A, "M", "ᄎ"),
+ (0x314B, "M", "ᄏ"),
+ (0x314C, "M", "ᄐ"),
+ (0x314D, "M", "ᄑ"),
+ (0x314E, "M", "ᄒ"),
+ (0x314F, "M", "ᅡ"),
+ (0x3150, "M", "ᅢ"),
+ (0x3151, "M", "ᅣ"),
+ (0x3152, "M", "ᅤ"),
+ (0x3153, "M", "ᅥ"),
+ (0x3154, "M", "ᅦ"),
+ (0x3155, "M", "ᅧ"),
+ (0x3156, "M", "ᅨ"),
+ (0x3157, "M", "ᅩ"),
+ (0x3158, "M", "ᅪ"),
+ (0x3159, "M", "ᅫ"),
+ (0x315A, "M", "ᅬ"),
+ (0x315B, "M", "ᅭ"),
+ (0x315C, "M", "ᅮ"),
+ (0x315D, "M", "ᅯ"),
+ (0x315E, "M", "ᅰ"),
+ (0x315F, "M", "ᅱ"),
+ (0x3160, "M", "ᅲ"),
+ (0x3161, "M", "ᅳ"),
+ (0x3162, "M", "ᅴ"),
+ (0x3163, "M", "ᅵ"),
+ (0x3164, "X"),
+ (0x3165, "M", "ᄔ"),
+ (0x3166, "M", "ᄕ"),
+ (0x3167, "M", "ᇇ"),
+ (0x3168, "M", "ᇈ"),
+ (0x3169, "M", "ᇌ"),
+ (0x316A, "M", "ᇎ"),
+ (0x316B, "M", "ᇓ"),
+ (0x316C, "M", "ᇗ"),
+ (0x316D, "M", "ᇙ"),
+ (0x316E, "M", "ᄜ"),
+ (0x316F, "M", "ᇝ"),
+ (0x3170, "M", "ᇟ"),
+ (0x3171, "M", "ᄝ"),
+ (0x3172, "M", "ᄞ"),
+ (0x3173, "M", "ᄠ"),
+ (0x3174, "M", "ᄢ"),
+ (0x3175, "M", "ᄣ"),
+ (0x3176, "M", "ᄧ"),
+ (0x3177, "M", "ᄩ"),
+ (0x3178, "M", "ᄫ"),
+ (0x3179, "M", "ᄬ"),
+ (0x317A, "M", "ᄭ"),
+ (0x317B, "M", "ᄮ"),
+ (0x317C, "M", "ᄯ"),
+ (0x317D, "M", "ᄲ"),
+ (0x317E, "M", "ᄶ"),
+ (0x317F, "M", "ᅀ"),
+ (0x3180, "M", "ᅇ"),
+ (0x3181, "M", "ᅌ"),
+ (0x3182, "M", "ᇱ"),
+ (0x3183, "M", "ᇲ"),
+ (0x3184, "M", "ᅗ"),
+ (0x3185, "M", "ᅘ"),
+ (0x3186, "M", "ᅙ"),
+ (0x3187, "M", "ᆄ"),
+ (0x3188, "M", "ᆅ"),
+ ]
+
+
+def _seg_30() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x3189, "M", "ᆈ"),
+ (0x318A, "M", "ᆑ"),
+ (0x318B, "M", "ᆒ"),
+ (0x318C, "M", "ᆔ"),
+ (0x318D, "M", "ᆞ"),
+ (0x318E, "M", "ᆡ"),
+ (0x318F, "X"),
+ (0x3190, "V"),
+ (0x3192, "M", "一"),
+ (0x3193, "M", "二"),
+ (0x3194, "M", "三"),
+ (0x3195, "M", "四"),
+ (0x3196, "M", "上"),
+ (0x3197, "M", "中"),
+ (0x3198, "M", "下"),
+ (0x3199, "M", "甲"),
+ (0x319A, "M", "乙"),
+ (0x319B, "M", "丙"),
+ (0x319C, "M", "丁"),
+ (0x319D, "M", "天"),
+ (0x319E, "M", "地"),
+ (0x319F, "M", "人"),
+ (0x31A0, "V"),
+ (0x31E4, "X"),
+ (0x31F0, "V"),
+ (0x3200, "3", "(ᄀ)"),
+ (0x3201, "3", "(ᄂ)"),
+ (0x3202, "3", "(ᄃ)"),
+ (0x3203, "3", "(ᄅ)"),
+ (0x3204, "3", "(ᄆ)"),
+ (0x3205, "3", "(ᄇ)"),
+ (0x3206, "3", "(ᄉ)"),
+ (0x3207, "3", "(ᄋ)"),
+ (0x3208, "3", "(ᄌ)"),
+ (0x3209, "3", "(ᄎ)"),
+ (0x320A, "3", "(ᄏ)"),
+ (0x320B, "3", "(ᄐ)"),
+ (0x320C, "3", "(ᄑ)"),
+ (0x320D, "3", "(ᄒ)"),
+ (0x320E, "3", "(가)"),
+ (0x320F, "3", "(나)"),
+ (0x3210, "3", "(다)"),
+ (0x3211, "3", "(라)"),
+ (0x3212, "3", "(마)"),
+ (0x3213, "3", "(바)"),
+ (0x3214, "3", "(사)"),
+ (0x3215, "3", "(아)"),
+ (0x3216, "3", "(자)"),
+ (0x3217, "3", "(차)"),
+ (0x3218, "3", "(카)"),
+ (0x3219, "3", "(타)"),
+ (0x321A, "3", "(파)"),
+ (0x321B, "3", "(하)"),
+ (0x321C, "3", "(주)"),
+ (0x321D, "3", "(오전)"),
+ (0x321E, "3", "(오후)"),
+ (0x321F, "X"),
+ (0x3220, "3", "(一)"),
+ (0x3221, "3", "(二)"),
+ (0x3222, "3", "(三)"),
+ (0x3223, "3", "(四)"),
+ (0x3224, "3", "(五)"),
+ (0x3225, "3", "(六)"),
+ (0x3226, "3", "(七)"),
+ (0x3227, "3", "(八)"),
+ (0x3228, "3", "(九)"),
+ (0x3229, "3", "(十)"),
+ (0x322A, "3", "(月)"),
+ (0x322B, "3", "(火)"),
+ (0x322C, "3", "(水)"),
+ (0x322D, "3", "(木)"),
+ (0x322E, "3", "(金)"),
+ (0x322F, "3", "(土)"),
+ (0x3230, "3", "(日)"),
+ (0x3231, "3", "(株)"),
+ (0x3232, "3", "(有)"),
+ (0x3233, "3", "(社)"),
+ (0x3234, "3", "(名)"),
+ (0x3235, "3", "(特)"),
+ (0x3236, "3", "(財)"),
+ (0x3237, "3", "(祝)"),
+ (0x3238, "3", "(労)"),
+ (0x3239, "3", "(代)"),
+ (0x323A, "3", "(呼)"),
+ (0x323B, "3", "(学)"),
+ (0x323C, "3", "(監)"),
+ (0x323D, "3", "(企)"),
+ (0x323E, "3", "(資)"),
+ (0x323F, "3", "(協)"),
+ (0x3240, "3", "(祭)"),
+ (0x3241, "3", "(休)"),
+ (0x3242, "3", "(自)"),
+ (0x3243, "3", "(至)"),
+ (0x3244, "M", "問"),
+ (0x3245, "M", "幼"),
+ (0x3246, "M", "文"),
+ (0x3247, "M", "箏"),
+ (0x3248, "V"),
+ (0x3250, "M", "pte"),
+ (0x3251, "M", "21"),
+ ]
+
+
+def _seg_31() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x3252, "M", "22"),
+ (0x3253, "M", "23"),
+ (0x3254, "M", "24"),
+ (0x3255, "M", "25"),
+ (0x3256, "M", "26"),
+ (0x3257, "M", "27"),
+ (0x3258, "M", "28"),
+ (0x3259, "M", "29"),
+ (0x325A, "M", "30"),
+ (0x325B, "M", "31"),
+ (0x325C, "M", "32"),
+ (0x325D, "M", "33"),
+ (0x325E, "M", "34"),
+ (0x325F, "M", "35"),
+ (0x3260, "M", "ᄀ"),
+ (0x3261, "M", "ᄂ"),
+ (0x3262, "M", "ᄃ"),
+ (0x3263, "M", "ᄅ"),
+ (0x3264, "M", "ᄆ"),
+ (0x3265, "M", "ᄇ"),
+ (0x3266, "M", "ᄉ"),
+ (0x3267, "M", "ᄋ"),
+ (0x3268, "M", "ᄌ"),
+ (0x3269, "M", "ᄎ"),
+ (0x326A, "M", "ᄏ"),
+ (0x326B, "M", "ᄐ"),
+ (0x326C, "M", "ᄑ"),
+ (0x326D, "M", "ᄒ"),
+ (0x326E, "M", "가"),
+ (0x326F, "M", "나"),
+ (0x3270, "M", "다"),
+ (0x3271, "M", "라"),
+ (0x3272, "M", "마"),
+ (0x3273, "M", "바"),
+ (0x3274, "M", "사"),
+ (0x3275, "M", "아"),
+ (0x3276, "M", "자"),
+ (0x3277, "M", "차"),
+ (0x3278, "M", "카"),
+ (0x3279, "M", "타"),
+ (0x327A, "M", "파"),
+ (0x327B, "M", "하"),
+ (0x327C, "M", "참고"),
+ (0x327D, "M", "주의"),
+ (0x327E, "M", "우"),
+ (0x327F, "V"),
+ (0x3280, "M", "一"),
+ (0x3281, "M", "二"),
+ (0x3282, "M", "三"),
+ (0x3283, "M", "四"),
+ (0x3284, "M", "五"),
+ (0x3285, "M", "六"),
+ (0x3286, "M", "七"),
+ (0x3287, "M", "八"),
+ (0x3288, "M", "九"),
+ (0x3289, "M", "十"),
+ (0x328A, "M", "月"),
+ (0x328B, "M", "火"),
+ (0x328C, "M", "水"),
+ (0x328D, "M", "木"),
+ (0x328E, "M", "金"),
+ (0x328F, "M", "土"),
+ (0x3290, "M", "日"),
+ (0x3291, "M", "株"),
+ (0x3292, "M", "有"),
+ (0x3293, "M", "社"),
+ (0x3294, "M", "名"),
+ (0x3295, "M", "特"),
+ (0x3296, "M", "財"),
+ (0x3297, "M", "祝"),
+ (0x3298, "M", "労"),
+ (0x3299, "M", "秘"),
+ (0x329A, "M", "男"),
+ (0x329B, "M", "女"),
+ (0x329C, "M", "適"),
+ (0x329D, "M", "優"),
+ (0x329E, "M", "印"),
+ (0x329F, "M", "注"),
+ (0x32A0, "M", "項"),
+ (0x32A1, "M", "休"),
+ (0x32A2, "M", "写"),
+ (0x32A3, "M", "正"),
+ (0x32A4, "M", "上"),
+ (0x32A5, "M", "中"),
+ (0x32A6, "M", "下"),
+ (0x32A7, "M", "左"),
+ (0x32A8, "M", "右"),
+ (0x32A9, "M", "医"),
+ (0x32AA, "M", "宗"),
+ (0x32AB, "M", "学"),
+ (0x32AC, "M", "監"),
+ (0x32AD, "M", "企"),
+ (0x32AE, "M", "資"),
+ (0x32AF, "M", "協"),
+ (0x32B0, "M", "夜"),
+ (0x32B1, "M", "36"),
+ (0x32B2, "M", "37"),
+ (0x32B3, "M", "38"),
+ (0x32B4, "M", "39"),
+ (0x32B5, "M", "40"),
+ ]
+
+
+def _seg_32() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x32B6, "M", "41"),
+ (0x32B7, "M", "42"),
+ (0x32B8, "M", "43"),
+ (0x32B9, "M", "44"),
+ (0x32BA, "M", "45"),
+ (0x32BB, "M", "46"),
+ (0x32BC, "M", "47"),
+ (0x32BD, "M", "48"),
+ (0x32BE, "M", "49"),
+ (0x32BF, "M", "50"),
+ (0x32C0, "M", "1月"),
+ (0x32C1, "M", "2月"),
+ (0x32C2, "M", "3月"),
+ (0x32C3, "M", "4月"),
+ (0x32C4, "M", "5月"),
+ (0x32C5, "M", "6月"),
+ (0x32C6, "M", "7月"),
+ (0x32C7, "M", "8月"),
+ (0x32C8, "M", "9月"),
+ (0x32C9, "M", "10月"),
+ (0x32CA, "M", "11月"),
+ (0x32CB, "M", "12月"),
+ (0x32CC, "M", "hg"),
+ (0x32CD, "M", "erg"),
+ (0x32CE, "M", "ev"),
+ (0x32CF, "M", "ltd"),
+ (0x32D0, "M", "ア"),
+ (0x32D1, "M", "イ"),
+ (0x32D2, "M", "ウ"),
+ (0x32D3, "M", "エ"),
+ (0x32D4, "M", "オ"),
+ (0x32D5, "M", "カ"),
+ (0x32D6, "M", "キ"),
+ (0x32D7, "M", "ク"),
+ (0x32D8, "M", "ケ"),
+ (0x32D9, "M", "コ"),
+ (0x32DA, "M", "サ"),
+ (0x32DB, "M", "シ"),
+ (0x32DC, "M", "ス"),
+ (0x32DD, "M", "セ"),
+ (0x32DE, "M", "ソ"),
+ (0x32DF, "M", "タ"),
+ (0x32E0, "M", "チ"),
+ (0x32E1, "M", "ツ"),
+ (0x32E2, "M", "テ"),
+ (0x32E3, "M", "ト"),
+ (0x32E4, "M", "ナ"),
+ (0x32E5, "M", "ニ"),
+ (0x32E6, "M", "ヌ"),
+ (0x32E7, "M", "ネ"),
+ (0x32E8, "M", "ノ"),
+ (0x32E9, "M", "ハ"),
+ (0x32EA, "M", "ヒ"),
+ (0x32EB, "M", "フ"),
+ (0x32EC, "M", "ヘ"),
+ (0x32ED, "M", "ホ"),
+ (0x32EE, "M", "マ"),
+ (0x32EF, "M", "ミ"),
+ (0x32F0, "M", "ム"),
+ (0x32F1, "M", "メ"),
+ (0x32F2, "M", "モ"),
+ (0x32F3, "M", "ヤ"),
+ (0x32F4, "M", "ユ"),
+ (0x32F5, "M", "ヨ"),
+ (0x32F6, "M", "ラ"),
+ (0x32F7, "M", "リ"),
+ (0x32F8, "M", "ル"),
+ (0x32F9, "M", "レ"),
+ (0x32FA, "M", "ロ"),
+ (0x32FB, "M", "ワ"),
+ (0x32FC, "M", "ヰ"),
+ (0x32FD, "M", "ヱ"),
+ (0x32FE, "M", "ヲ"),
+ (0x32FF, "M", "令和"),
+ (0x3300, "M", "アパート"),
+ (0x3301, "M", "アルファ"),
+ (0x3302, "M", "アンペア"),
+ (0x3303, "M", "アール"),
+ (0x3304, "M", "イニング"),
+ (0x3305, "M", "インチ"),
+ (0x3306, "M", "ウォン"),
+ (0x3307, "M", "エスクード"),
+ (0x3308, "M", "エーカー"),
+ (0x3309, "M", "オンス"),
+ (0x330A, "M", "オーム"),
+ (0x330B, "M", "カイリ"),
+ (0x330C, "M", "カラット"),
+ (0x330D, "M", "カロリー"),
+ (0x330E, "M", "ガロン"),
+ (0x330F, "M", "ガンマ"),
+ (0x3310, "M", "ギガ"),
+ (0x3311, "M", "ギニー"),
+ (0x3312, "M", "キュリー"),
+ (0x3313, "M", "ギルダー"),
+ (0x3314, "M", "キロ"),
+ (0x3315, "M", "キログラム"),
+ (0x3316, "M", "キロメートル"),
+ (0x3317, "M", "キロワット"),
+ (0x3318, "M", "グラム"),
+ (0x3319, "M", "グラムトン"),
+ ]
+
+
+def _seg_33() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x331A, "M", "クルゼイロ"),
+ (0x331B, "M", "クローネ"),
+ (0x331C, "M", "ケース"),
+ (0x331D, "M", "コルナ"),
+ (0x331E, "M", "コーポ"),
+ (0x331F, "M", "サイクル"),
+ (0x3320, "M", "サンチーム"),
+ (0x3321, "M", "シリング"),
+ (0x3322, "M", "センチ"),
+ (0x3323, "M", "セント"),
+ (0x3324, "M", "ダース"),
+ (0x3325, "M", "デシ"),
+ (0x3326, "M", "ドル"),
+ (0x3327, "M", "トン"),
+ (0x3328, "M", "ナノ"),
+ (0x3329, "M", "ノット"),
+ (0x332A, "M", "ハイツ"),
+ (0x332B, "M", "パーセント"),
+ (0x332C, "M", "パーツ"),
+ (0x332D, "M", "バーレル"),
+ (0x332E, "M", "ピアストル"),
+ (0x332F, "M", "ピクル"),
+ (0x3330, "M", "ピコ"),
+ (0x3331, "M", "ビル"),
+ (0x3332, "M", "ファラッド"),
+ (0x3333, "M", "フィート"),
+ (0x3334, "M", "ブッシェル"),
+ (0x3335, "M", "フラン"),
+ (0x3336, "M", "ヘクタール"),
+ (0x3337, "M", "ペソ"),
+ (0x3338, "M", "ペニヒ"),
+ (0x3339, "M", "ヘルツ"),
+ (0x333A, "M", "ペンス"),
+ (0x333B, "M", "ページ"),
+ (0x333C, "M", "ベータ"),
+ (0x333D, "M", "ポイント"),
+ (0x333E, "M", "ボルト"),
+ (0x333F, "M", "ホン"),
+ (0x3340, "M", "ポンド"),
+ (0x3341, "M", "ホール"),
+ (0x3342, "M", "ホーン"),
+ (0x3343, "M", "マイクロ"),
+ (0x3344, "M", "マイル"),
+ (0x3345, "M", "マッハ"),
+ (0x3346, "M", "マルク"),
+ (0x3347, "M", "マンション"),
+ (0x3348, "M", "ミクロン"),
+ (0x3349, "M", "ミリ"),
+ (0x334A, "M", "ミリバール"),
+ (0x334B, "M", "メガ"),
+ (0x334C, "M", "メガトン"),
+ (0x334D, "M", "メートル"),
+ (0x334E, "M", "ヤード"),
+ (0x334F, "M", "ヤール"),
+ (0x3350, "M", "ユアン"),
+ (0x3351, "M", "リットル"),
+ (0x3352, "M", "リラ"),
+ (0x3353, "M", "ルピー"),
+ (0x3354, "M", "ルーブル"),
+ (0x3355, "M", "レム"),
+ (0x3356, "M", "レントゲン"),
+ (0x3357, "M", "ワット"),
+ (0x3358, "M", "0点"),
+ (0x3359, "M", "1点"),
+ (0x335A, "M", "2点"),
+ (0x335B, "M", "3点"),
+ (0x335C, "M", "4点"),
+ (0x335D, "M", "5点"),
+ (0x335E, "M", "6点"),
+ (0x335F, "M", "7点"),
+ (0x3360, "M", "8点"),
+ (0x3361, "M", "9点"),
+ (0x3362, "M", "10点"),
+ (0x3363, "M", "11点"),
+ (0x3364, "M", "12点"),
+ (0x3365, "M", "13点"),
+ (0x3366, "M", "14点"),
+ (0x3367, "M", "15点"),
+ (0x3368, "M", "16点"),
+ (0x3369, "M", "17点"),
+ (0x336A, "M", "18点"),
+ (0x336B, "M", "19点"),
+ (0x336C, "M", "20点"),
+ (0x336D, "M", "21点"),
+ (0x336E, "M", "22点"),
+ (0x336F, "M", "23点"),
+ (0x3370, "M", "24点"),
+ (0x3371, "M", "hpa"),
+ (0x3372, "M", "da"),
+ (0x3373, "M", "au"),
+ (0x3374, "M", "bar"),
+ (0x3375, "M", "ov"),
+ (0x3376, "M", "pc"),
+ (0x3377, "M", "dm"),
+ (0x3378, "M", "dm2"),
+ (0x3379, "M", "dm3"),
+ (0x337A, "M", "iu"),
+ (0x337B, "M", "平成"),
+ (0x337C, "M", "昭和"),
+ (0x337D, "M", "大正"),
+ ]
+
+
+def _seg_34() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x337E, "M", "明治"),
+ (0x337F, "M", "株式会社"),
+ (0x3380, "M", "pa"),
+ (0x3381, "M", "na"),
+ (0x3382, "M", "μa"),
+ (0x3383, "M", "ma"),
+ (0x3384, "M", "ka"),
+ (0x3385, "M", "kb"),
+ (0x3386, "M", "mb"),
+ (0x3387, "M", "gb"),
+ (0x3388, "M", "cal"),
+ (0x3389, "M", "kcal"),
+ (0x338A, "M", "pf"),
+ (0x338B, "M", "nf"),
+ (0x338C, "M", "μf"),
+ (0x338D, "M", "μg"),
+ (0x338E, "M", "mg"),
+ (0x338F, "M", "kg"),
+ (0x3390, "M", "hz"),
+ (0x3391, "M", "khz"),
+ (0x3392, "M", "mhz"),
+ (0x3393, "M", "ghz"),
+ (0x3394, "M", "thz"),
+ (0x3395, "M", "μl"),
+ (0x3396, "M", "ml"),
+ (0x3397, "M", "dl"),
+ (0x3398, "M", "kl"),
+ (0x3399, "M", "fm"),
+ (0x339A, "M", "nm"),
+ (0x339B, "M", "μm"),
+ (0x339C, "M", "mm"),
+ (0x339D, "M", "cm"),
+ (0x339E, "M", "km"),
+ (0x339F, "M", "mm2"),
+ (0x33A0, "M", "cm2"),
+ (0x33A1, "M", "m2"),
+ (0x33A2, "M", "km2"),
+ (0x33A3, "M", "mm3"),
+ (0x33A4, "M", "cm3"),
+ (0x33A5, "M", "m3"),
+ (0x33A6, "M", "km3"),
+ (0x33A7, "M", "m∕s"),
+ (0x33A8, "M", "m∕s2"),
+ (0x33A9, "M", "pa"),
+ (0x33AA, "M", "kpa"),
+ (0x33AB, "M", "mpa"),
+ (0x33AC, "M", "gpa"),
+ (0x33AD, "M", "rad"),
+ (0x33AE, "M", "rad∕s"),
+ (0x33AF, "M", "rad∕s2"),
+ (0x33B0, "M", "ps"),
+ (0x33B1, "M", "ns"),
+ (0x33B2, "M", "μs"),
+ (0x33B3, "M", "ms"),
+ (0x33B4, "M", "pv"),
+ (0x33B5, "M", "nv"),
+ (0x33B6, "M", "μv"),
+ (0x33B7, "M", "mv"),
+ (0x33B8, "M", "kv"),
+ (0x33B9, "M", "mv"),
+ (0x33BA, "M", "pw"),
+ (0x33BB, "M", "nw"),
+ (0x33BC, "M", "μw"),
+ (0x33BD, "M", "mw"),
+ (0x33BE, "M", "kw"),
+ (0x33BF, "M", "mw"),
+ (0x33C0, "M", "kω"),
+ (0x33C1, "M", "mω"),
+ (0x33C2, "X"),
+ (0x33C3, "M", "bq"),
+ (0x33C4, "M", "cc"),
+ (0x33C5, "M", "cd"),
+ (0x33C6, "M", "c∕kg"),
+ (0x33C7, "X"),
+ (0x33C8, "M", "db"),
+ (0x33C9, "M", "gy"),
+ (0x33CA, "M", "ha"),
+ (0x33CB, "M", "hp"),
+ (0x33CC, "M", "in"),
+ (0x33CD, "M", "kk"),
+ (0x33CE, "M", "km"),
+ (0x33CF, "M", "kt"),
+ (0x33D0, "M", "lm"),
+ (0x33D1, "M", "ln"),
+ (0x33D2, "M", "log"),
+ (0x33D3, "M", "lx"),
+ (0x33D4, "M", "mb"),
+ (0x33D5, "M", "mil"),
+ (0x33D6, "M", "mol"),
+ (0x33D7, "M", "ph"),
+ (0x33D8, "X"),
+ (0x33D9, "M", "ppm"),
+ (0x33DA, "M", "pr"),
+ (0x33DB, "M", "sr"),
+ (0x33DC, "M", "sv"),
+ (0x33DD, "M", "wb"),
+ (0x33DE, "M", "v∕m"),
+ (0x33DF, "M", "a∕m"),
+ (0x33E0, "M", "1日"),
+ (0x33E1, "M", "2日"),
+ ]
+
+
+def _seg_35() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x33E2, "M", "3日"),
+ (0x33E3, "M", "4日"),
+ (0x33E4, "M", "5日"),
+ (0x33E5, "M", "6日"),
+ (0x33E6, "M", "7日"),
+ (0x33E7, "M", "8日"),
+ (0x33E8, "M", "9日"),
+ (0x33E9, "M", "10日"),
+ (0x33EA, "M", "11日"),
+ (0x33EB, "M", "12日"),
+ (0x33EC, "M", "13日"),
+ (0x33ED, "M", "14日"),
+ (0x33EE, "M", "15日"),
+ (0x33EF, "M", "16日"),
+ (0x33F0, "M", "17日"),
+ (0x33F1, "M", "18日"),
+ (0x33F2, "M", "19日"),
+ (0x33F3, "M", "20日"),
+ (0x33F4, "M", "21日"),
+ (0x33F5, "M", "22日"),
+ (0x33F6, "M", "23日"),
+ (0x33F7, "M", "24日"),
+ (0x33F8, "M", "25日"),
+ (0x33F9, "M", "26日"),
+ (0x33FA, "M", "27日"),
+ (0x33FB, "M", "28日"),
+ (0x33FC, "M", "29日"),
+ (0x33FD, "M", "30日"),
+ (0x33FE, "M", "31日"),
+ (0x33FF, "M", "gal"),
+ (0x3400, "V"),
+ (0xA48D, "X"),
+ (0xA490, "V"),
+ (0xA4C7, "X"),
+ (0xA4D0, "V"),
+ (0xA62C, "X"),
+ (0xA640, "M", "ꙁ"),
+ (0xA641, "V"),
+ (0xA642, "M", "ꙃ"),
+ (0xA643, "V"),
+ (0xA644, "M", "ꙅ"),
+ (0xA645, "V"),
+ (0xA646, "M", "ꙇ"),
+ (0xA647, "V"),
+ (0xA648, "M", "ꙉ"),
+ (0xA649, "V"),
+ (0xA64A, "M", "ꙋ"),
+ (0xA64B, "V"),
+ (0xA64C, "M", "ꙍ"),
+ (0xA64D, "V"),
+ (0xA64E, "M", "ꙏ"),
+ (0xA64F, "V"),
+ (0xA650, "M", "ꙑ"),
+ (0xA651, "V"),
+ (0xA652, "M", "ꙓ"),
+ (0xA653, "V"),
+ (0xA654, "M", "ꙕ"),
+ (0xA655, "V"),
+ (0xA656, "M", "ꙗ"),
+ (0xA657, "V"),
+ (0xA658, "M", "ꙙ"),
+ (0xA659, "V"),
+ (0xA65A, "M", "ꙛ"),
+ (0xA65B, "V"),
+ (0xA65C, "M", "ꙝ"),
+ (0xA65D, "V"),
+ (0xA65E, "M", "ꙟ"),
+ (0xA65F, "V"),
+ (0xA660, "M", "ꙡ"),
+ (0xA661, "V"),
+ (0xA662, "M", "ꙣ"),
+ (0xA663, "V"),
+ (0xA664, "M", "ꙥ"),
+ (0xA665, "V"),
+ (0xA666, "M", "ꙧ"),
+ (0xA667, "V"),
+ (0xA668, "M", "ꙩ"),
+ (0xA669, "V"),
+ (0xA66A, "M", "ꙫ"),
+ (0xA66B, "V"),
+ (0xA66C, "M", "ꙭ"),
+ (0xA66D, "V"),
+ (0xA680, "M", "ꚁ"),
+ (0xA681, "V"),
+ (0xA682, "M", "ꚃ"),
+ (0xA683, "V"),
+ (0xA684, "M", "ꚅ"),
+ (0xA685, "V"),
+ (0xA686, "M", "ꚇ"),
+ (0xA687, "V"),
+ (0xA688, "M", "ꚉ"),
+ (0xA689, "V"),
+ (0xA68A, "M", "ꚋ"),
+ (0xA68B, "V"),
+ (0xA68C, "M", "ꚍ"),
+ (0xA68D, "V"),
+ (0xA68E, "M", "ꚏ"),
+ (0xA68F, "V"),
+ (0xA690, "M", "ꚑ"),
+ (0xA691, "V"),
+ ]
+
+
+def _seg_36() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xA692, "M", "ꚓ"),
+ (0xA693, "V"),
+ (0xA694, "M", "ꚕ"),
+ (0xA695, "V"),
+ (0xA696, "M", "ꚗ"),
+ (0xA697, "V"),
+ (0xA698, "M", "ꚙ"),
+ (0xA699, "V"),
+ (0xA69A, "M", "ꚛ"),
+ (0xA69B, "V"),
+ (0xA69C, "M", "ъ"),
+ (0xA69D, "M", "ь"),
+ (0xA69E, "V"),
+ (0xA6F8, "X"),
+ (0xA700, "V"),
+ (0xA722, "M", "ꜣ"),
+ (0xA723, "V"),
+ (0xA724, "M", "ꜥ"),
+ (0xA725, "V"),
+ (0xA726, "M", "ꜧ"),
+ (0xA727, "V"),
+ (0xA728, "M", "ꜩ"),
+ (0xA729, "V"),
+ (0xA72A, "M", "ꜫ"),
+ (0xA72B, "V"),
+ (0xA72C, "M", "ꜭ"),
+ (0xA72D, "V"),
+ (0xA72E, "M", "ꜯ"),
+ (0xA72F, "V"),
+ (0xA732, "M", "ꜳ"),
+ (0xA733, "V"),
+ (0xA734, "M", "ꜵ"),
+ (0xA735, "V"),
+ (0xA736, "M", "ꜷ"),
+ (0xA737, "V"),
+ (0xA738, "M", "ꜹ"),
+ (0xA739, "V"),
+ (0xA73A, "M", "ꜻ"),
+ (0xA73B, "V"),
+ (0xA73C, "M", "ꜽ"),
+ (0xA73D, "V"),
+ (0xA73E, "M", "ꜿ"),
+ (0xA73F, "V"),
+ (0xA740, "M", "ꝁ"),
+ (0xA741, "V"),
+ (0xA742, "M", "ꝃ"),
+ (0xA743, "V"),
+ (0xA744, "M", "ꝅ"),
+ (0xA745, "V"),
+ (0xA746, "M", "ꝇ"),
+ (0xA747, "V"),
+ (0xA748, "M", "ꝉ"),
+ (0xA749, "V"),
+ (0xA74A, "M", "ꝋ"),
+ (0xA74B, "V"),
+ (0xA74C, "M", "ꝍ"),
+ (0xA74D, "V"),
+ (0xA74E, "M", "ꝏ"),
+ (0xA74F, "V"),
+ (0xA750, "M", "ꝑ"),
+ (0xA751, "V"),
+ (0xA752, "M", "ꝓ"),
+ (0xA753, "V"),
+ (0xA754, "M", "ꝕ"),
+ (0xA755, "V"),
+ (0xA756, "M", "ꝗ"),
+ (0xA757, "V"),
+ (0xA758, "M", "ꝙ"),
+ (0xA759, "V"),
+ (0xA75A, "M", "ꝛ"),
+ (0xA75B, "V"),
+ (0xA75C, "M", "ꝝ"),
+ (0xA75D, "V"),
+ (0xA75E, "M", "ꝟ"),
+ (0xA75F, "V"),
+ (0xA760, "M", "ꝡ"),
+ (0xA761, "V"),
+ (0xA762, "M", "ꝣ"),
+ (0xA763, "V"),
+ (0xA764, "M", "ꝥ"),
+ (0xA765, "V"),
+ (0xA766, "M", "ꝧ"),
+ (0xA767, "V"),
+ (0xA768, "M", "ꝩ"),
+ (0xA769, "V"),
+ (0xA76A, "M", "ꝫ"),
+ (0xA76B, "V"),
+ (0xA76C, "M", "ꝭ"),
+ (0xA76D, "V"),
+ (0xA76E, "M", "ꝯ"),
+ (0xA76F, "V"),
+ (0xA770, "M", "ꝯ"),
+ (0xA771, "V"),
+ (0xA779, "M", "ꝺ"),
+ (0xA77A, "V"),
+ (0xA77B, "M", "ꝼ"),
+ (0xA77C, "V"),
+ (0xA77D, "M", "ᵹ"),
+ (0xA77E, "M", "ꝿ"),
+ (0xA77F, "V"),
+ ]
+
+
+def _seg_37() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xA780, "M", "ꞁ"),
+ (0xA781, "V"),
+ (0xA782, "M", "ꞃ"),
+ (0xA783, "V"),
+ (0xA784, "M", "ꞅ"),
+ (0xA785, "V"),
+ (0xA786, "M", "ꞇ"),
+ (0xA787, "V"),
+ (0xA78B, "M", "ꞌ"),
+ (0xA78C, "V"),
+ (0xA78D, "M", "ɥ"),
+ (0xA78E, "V"),
+ (0xA790, "M", "ꞑ"),
+ (0xA791, "V"),
+ (0xA792, "M", "ꞓ"),
+ (0xA793, "V"),
+ (0xA796, "M", "ꞗ"),
+ (0xA797, "V"),
+ (0xA798, "M", "ꞙ"),
+ (0xA799, "V"),
+ (0xA79A, "M", "ꞛ"),
+ (0xA79B, "V"),
+ (0xA79C, "M", "ꞝ"),
+ (0xA79D, "V"),
+ (0xA79E, "M", "ꞟ"),
+ (0xA79F, "V"),
+ (0xA7A0, "M", "ꞡ"),
+ (0xA7A1, "V"),
+ (0xA7A2, "M", "ꞣ"),
+ (0xA7A3, "V"),
+ (0xA7A4, "M", "ꞥ"),
+ (0xA7A5, "V"),
+ (0xA7A6, "M", "ꞧ"),
+ (0xA7A7, "V"),
+ (0xA7A8, "M", "ꞩ"),
+ (0xA7A9, "V"),
+ (0xA7AA, "M", "ɦ"),
+ (0xA7AB, "M", "ɜ"),
+ (0xA7AC, "M", "ɡ"),
+ (0xA7AD, "M", "ɬ"),
+ (0xA7AE, "M", "ɪ"),
+ (0xA7AF, "V"),
+ (0xA7B0, "M", "ʞ"),
+ (0xA7B1, "M", "ʇ"),
+ (0xA7B2, "M", "ʝ"),
+ (0xA7B3, "M", "ꭓ"),
+ (0xA7B4, "M", "ꞵ"),
+ (0xA7B5, "V"),
+ (0xA7B6, "M", "ꞷ"),
+ (0xA7B7, "V"),
+ (0xA7B8, "M", "ꞹ"),
+ (0xA7B9, "V"),
+ (0xA7BA, "M", "ꞻ"),
+ (0xA7BB, "V"),
+ (0xA7BC, "M", "ꞽ"),
+ (0xA7BD, "V"),
+ (0xA7BE, "M", "ꞿ"),
+ (0xA7BF, "V"),
+ (0xA7C0, "M", "ꟁ"),
+ (0xA7C1, "V"),
+ (0xA7C2, "M", "ꟃ"),
+ (0xA7C3, "V"),
+ (0xA7C4, "M", "ꞔ"),
+ (0xA7C5, "M", "ʂ"),
+ (0xA7C6, "M", "ᶎ"),
+ (0xA7C7, "M", "ꟈ"),
+ (0xA7C8, "V"),
+ (0xA7C9, "M", "ꟊ"),
+ (0xA7CA, "V"),
+ (0xA7CB, "X"),
+ (0xA7D0, "M", "ꟑ"),
+ (0xA7D1, "V"),
+ (0xA7D2, "X"),
+ (0xA7D3, "V"),
+ (0xA7D4, "X"),
+ (0xA7D5, "V"),
+ (0xA7D6, "M", "ꟗ"),
+ (0xA7D7, "V"),
+ (0xA7D8, "M", "ꟙ"),
+ (0xA7D9, "V"),
+ (0xA7DA, "X"),
+ (0xA7F2, "M", "c"),
+ (0xA7F3, "M", "f"),
+ (0xA7F4, "M", "q"),
+ (0xA7F5, "M", "ꟶ"),
+ (0xA7F6, "V"),
+ (0xA7F8, "M", "ħ"),
+ (0xA7F9, "M", "œ"),
+ (0xA7FA, "V"),
+ (0xA82D, "X"),
+ (0xA830, "V"),
+ (0xA83A, "X"),
+ (0xA840, "V"),
+ (0xA878, "X"),
+ (0xA880, "V"),
+ (0xA8C6, "X"),
+ (0xA8CE, "V"),
+ (0xA8DA, "X"),
+ (0xA8E0, "V"),
+ (0xA954, "X"),
+ ]
+
+
+def _seg_38() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xA95F, "V"),
+ (0xA97D, "X"),
+ (0xA980, "V"),
+ (0xA9CE, "X"),
+ (0xA9CF, "V"),
+ (0xA9DA, "X"),
+ (0xA9DE, "V"),
+ (0xA9FF, "X"),
+ (0xAA00, "V"),
+ (0xAA37, "X"),
+ (0xAA40, "V"),
+ (0xAA4E, "X"),
+ (0xAA50, "V"),
+ (0xAA5A, "X"),
+ (0xAA5C, "V"),
+ (0xAAC3, "X"),
+ (0xAADB, "V"),
+ (0xAAF7, "X"),
+ (0xAB01, "V"),
+ (0xAB07, "X"),
+ (0xAB09, "V"),
+ (0xAB0F, "X"),
+ (0xAB11, "V"),
+ (0xAB17, "X"),
+ (0xAB20, "V"),
+ (0xAB27, "X"),
+ (0xAB28, "V"),
+ (0xAB2F, "X"),
+ (0xAB30, "V"),
+ (0xAB5C, "M", "ꜧ"),
+ (0xAB5D, "M", "ꬷ"),
+ (0xAB5E, "M", "ɫ"),
+ (0xAB5F, "M", "ꭒ"),
+ (0xAB60, "V"),
+ (0xAB69, "M", "ʍ"),
+ (0xAB6A, "V"),
+ (0xAB6C, "X"),
+ (0xAB70, "M", "Ꭰ"),
+ (0xAB71, "M", "Ꭱ"),
+ (0xAB72, "M", "Ꭲ"),
+ (0xAB73, "M", "Ꭳ"),
+ (0xAB74, "M", "Ꭴ"),
+ (0xAB75, "M", "Ꭵ"),
+ (0xAB76, "M", "Ꭶ"),
+ (0xAB77, "M", "Ꭷ"),
+ (0xAB78, "M", "Ꭸ"),
+ (0xAB79, "M", "Ꭹ"),
+ (0xAB7A, "M", "Ꭺ"),
+ (0xAB7B, "M", "Ꭻ"),
+ (0xAB7C, "M", "Ꭼ"),
+ (0xAB7D, "M", "Ꭽ"),
+ (0xAB7E, "M", "Ꭾ"),
+ (0xAB7F, "M", "Ꭿ"),
+ (0xAB80, "M", "Ꮀ"),
+ (0xAB81, "M", "Ꮁ"),
+ (0xAB82, "M", "Ꮂ"),
+ (0xAB83, "M", "Ꮃ"),
+ (0xAB84, "M", "Ꮄ"),
+ (0xAB85, "M", "Ꮅ"),
+ (0xAB86, "M", "Ꮆ"),
+ (0xAB87, "M", "Ꮇ"),
+ (0xAB88, "M", "Ꮈ"),
+ (0xAB89, "M", "Ꮉ"),
+ (0xAB8A, "M", "Ꮊ"),
+ (0xAB8B, "M", "Ꮋ"),
+ (0xAB8C, "M", "Ꮌ"),
+ (0xAB8D, "M", "Ꮍ"),
+ (0xAB8E, "M", "Ꮎ"),
+ (0xAB8F, "M", "Ꮏ"),
+ (0xAB90, "M", "Ꮐ"),
+ (0xAB91, "M", "Ꮑ"),
+ (0xAB92, "M", "Ꮒ"),
+ (0xAB93, "M", "Ꮓ"),
+ (0xAB94, "M", "Ꮔ"),
+ (0xAB95, "M", "Ꮕ"),
+ (0xAB96, "M", "Ꮖ"),
+ (0xAB97, "M", "Ꮗ"),
+ (0xAB98, "M", "Ꮘ"),
+ (0xAB99, "M", "Ꮙ"),
+ (0xAB9A, "M", "Ꮚ"),
+ (0xAB9B, "M", "Ꮛ"),
+ (0xAB9C, "M", "Ꮜ"),
+ (0xAB9D, "M", "Ꮝ"),
+ (0xAB9E, "M", "Ꮞ"),
+ (0xAB9F, "M", "Ꮟ"),
+ (0xABA0, "M", "Ꮠ"),
+ (0xABA1, "M", "Ꮡ"),
+ (0xABA2, "M", "Ꮢ"),
+ (0xABA3, "M", "Ꮣ"),
+ (0xABA4, "M", "Ꮤ"),
+ (0xABA5, "M", "Ꮥ"),
+ (0xABA6, "M", "Ꮦ"),
+ (0xABA7, "M", "Ꮧ"),
+ (0xABA8, "M", "Ꮨ"),
+ (0xABA9, "M", "Ꮩ"),
+ (0xABAA, "M", "Ꮪ"),
+ (0xABAB, "M", "Ꮫ"),
+ (0xABAC, "M", "Ꮬ"),
+ (0xABAD, "M", "Ꮭ"),
+ (0xABAE, "M", "Ꮮ"),
+ ]
+
+
+def _seg_39() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xABAF, "M", "Ꮯ"),
+ (0xABB0, "M", "Ꮰ"),
+ (0xABB1, "M", "Ꮱ"),
+ (0xABB2, "M", "Ꮲ"),
+ (0xABB3, "M", "Ꮳ"),
+ (0xABB4, "M", "Ꮴ"),
+ (0xABB5, "M", "Ꮵ"),
+ (0xABB6, "M", "Ꮶ"),
+ (0xABB7, "M", "Ꮷ"),
+ (0xABB8, "M", "Ꮸ"),
+ (0xABB9, "M", "Ꮹ"),
+ (0xABBA, "M", "Ꮺ"),
+ (0xABBB, "M", "Ꮻ"),
+ (0xABBC, "M", "Ꮼ"),
+ (0xABBD, "M", "Ꮽ"),
+ (0xABBE, "M", "Ꮾ"),
+ (0xABBF, "M", "Ꮿ"),
+ (0xABC0, "V"),
+ (0xABEE, "X"),
+ (0xABF0, "V"),
+ (0xABFA, "X"),
+ (0xAC00, "V"),
+ (0xD7A4, "X"),
+ (0xD7B0, "V"),
+ (0xD7C7, "X"),
+ (0xD7CB, "V"),
+ (0xD7FC, "X"),
+ (0xF900, "M", "豈"),
+ (0xF901, "M", "更"),
+ (0xF902, "M", "車"),
+ (0xF903, "M", "賈"),
+ (0xF904, "M", "滑"),
+ (0xF905, "M", "串"),
+ (0xF906, "M", "句"),
+ (0xF907, "M", "龜"),
+ (0xF909, "M", "契"),
+ (0xF90A, "M", "金"),
+ (0xF90B, "M", "喇"),
+ (0xF90C, "M", "奈"),
+ (0xF90D, "M", "懶"),
+ (0xF90E, "M", "癩"),
+ (0xF90F, "M", "羅"),
+ (0xF910, "M", "蘿"),
+ (0xF911, "M", "螺"),
+ (0xF912, "M", "裸"),
+ (0xF913, "M", "邏"),
+ (0xF914, "M", "樂"),
+ (0xF915, "M", "洛"),
+ (0xF916, "M", "烙"),
+ (0xF917, "M", "珞"),
+ (0xF918, "M", "落"),
+ (0xF919, "M", "酪"),
+ (0xF91A, "M", "駱"),
+ (0xF91B, "M", "亂"),
+ (0xF91C, "M", "卵"),
+ (0xF91D, "M", "欄"),
+ (0xF91E, "M", "爛"),
+ (0xF91F, "M", "蘭"),
+ (0xF920, "M", "鸞"),
+ (0xF921, "M", "嵐"),
+ (0xF922, "M", "濫"),
+ (0xF923, "M", "藍"),
+ (0xF924, "M", "襤"),
+ (0xF925, "M", "拉"),
+ (0xF926, "M", "臘"),
+ (0xF927, "M", "蠟"),
+ (0xF928, "M", "廊"),
+ (0xF929, "M", "朗"),
+ (0xF92A, "M", "浪"),
+ (0xF92B, "M", "狼"),
+ (0xF92C, "M", "郎"),
+ (0xF92D, "M", "來"),
+ (0xF92E, "M", "冷"),
+ (0xF92F, "M", "勞"),
+ (0xF930, "M", "擄"),
+ (0xF931, "M", "櫓"),
+ (0xF932, "M", "爐"),
+ (0xF933, "M", "盧"),
+ (0xF934, "M", "老"),
+ (0xF935, "M", "蘆"),
+ (0xF936, "M", "虜"),
+ (0xF937, "M", "路"),
+ (0xF938, "M", "露"),
+ (0xF939, "M", "魯"),
+ (0xF93A, "M", "鷺"),
+ (0xF93B, "M", "碌"),
+ (0xF93C, "M", "祿"),
+ (0xF93D, "M", "綠"),
+ (0xF93E, "M", "菉"),
+ (0xF93F, "M", "錄"),
+ (0xF940, "M", "鹿"),
+ (0xF941, "M", "論"),
+ (0xF942, "M", "壟"),
+ (0xF943, "M", "弄"),
+ (0xF944, "M", "籠"),
+ (0xF945, "M", "聾"),
+ (0xF946, "M", "牢"),
+ (0xF947, "M", "磊"),
+ (0xF948, "M", "賂"),
+ (0xF949, "M", "雷"),
+ ]
+
+
+def _seg_40() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xF94A, "M", "壘"),
+ (0xF94B, "M", "屢"),
+ (0xF94C, "M", "樓"),
+ (0xF94D, "M", "淚"),
+ (0xF94E, "M", "漏"),
+ (0xF94F, "M", "累"),
+ (0xF950, "M", "縷"),
+ (0xF951, "M", "陋"),
+ (0xF952, "M", "勒"),
+ (0xF953, "M", "肋"),
+ (0xF954, "M", "凜"),
+ (0xF955, "M", "凌"),
+ (0xF956, "M", "稜"),
+ (0xF957, "M", "綾"),
+ (0xF958, "M", "菱"),
+ (0xF959, "M", "陵"),
+ (0xF95A, "M", "讀"),
+ (0xF95B, "M", "拏"),
+ (0xF95C, "M", "樂"),
+ (0xF95D, "M", "諾"),
+ (0xF95E, "M", "丹"),
+ (0xF95F, "M", "寧"),
+ (0xF960, "M", "怒"),
+ (0xF961, "M", "率"),
+ (0xF962, "M", "異"),
+ (0xF963, "M", "北"),
+ (0xF964, "M", "磻"),
+ (0xF965, "M", "便"),
+ (0xF966, "M", "復"),
+ (0xF967, "M", "不"),
+ (0xF968, "M", "泌"),
+ (0xF969, "M", "數"),
+ (0xF96A, "M", "索"),
+ (0xF96B, "M", "參"),
+ (0xF96C, "M", "塞"),
+ (0xF96D, "M", "省"),
+ (0xF96E, "M", "葉"),
+ (0xF96F, "M", "說"),
+ (0xF970, "M", "殺"),
+ (0xF971, "M", "辰"),
+ (0xF972, "M", "沈"),
+ (0xF973, "M", "拾"),
+ (0xF974, "M", "若"),
+ (0xF975, "M", "掠"),
+ (0xF976, "M", "略"),
+ (0xF977, "M", "亮"),
+ (0xF978, "M", "兩"),
+ (0xF979, "M", "凉"),
+ (0xF97A, "M", "梁"),
+ (0xF97B, "M", "糧"),
+ (0xF97C, "M", "良"),
+ (0xF97D, "M", "諒"),
+ (0xF97E, "M", "量"),
+ (0xF97F, "M", "勵"),
+ (0xF980, "M", "呂"),
+ (0xF981, "M", "女"),
+ (0xF982, "M", "廬"),
+ (0xF983, "M", "旅"),
+ (0xF984, "M", "濾"),
+ (0xF985, "M", "礪"),
+ (0xF986, "M", "閭"),
+ (0xF987, "M", "驪"),
+ (0xF988, "M", "麗"),
+ (0xF989, "M", "黎"),
+ (0xF98A, "M", "力"),
+ (0xF98B, "M", "曆"),
+ (0xF98C, "M", "歷"),
+ (0xF98D, "M", "轢"),
+ (0xF98E, "M", "年"),
+ (0xF98F, "M", "憐"),
+ (0xF990, "M", "戀"),
+ (0xF991, "M", "撚"),
+ (0xF992, "M", "漣"),
+ (0xF993, "M", "煉"),
+ (0xF994, "M", "璉"),
+ (0xF995, "M", "秊"),
+ (0xF996, "M", "練"),
+ (0xF997, "M", "聯"),
+ (0xF998, "M", "輦"),
+ (0xF999, "M", "蓮"),
+ (0xF99A, "M", "連"),
+ (0xF99B, "M", "鍊"),
+ (0xF99C, "M", "列"),
+ (0xF99D, "M", "劣"),
+ (0xF99E, "M", "咽"),
+ (0xF99F, "M", "烈"),
+ (0xF9A0, "M", "裂"),
+ (0xF9A1, "M", "說"),
+ (0xF9A2, "M", "廉"),
+ (0xF9A3, "M", "念"),
+ (0xF9A4, "M", "捻"),
+ (0xF9A5, "M", "殮"),
+ (0xF9A6, "M", "簾"),
+ (0xF9A7, "M", "獵"),
+ (0xF9A8, "M", "令"),
+ (0xF9A9, "M", "囹"),
+ (0xF9AA, "M", "寧"),
+ (0xF9AB, "M", "嶺"),
+ (0xF9AC, "M", "怜"),
+ (0xF9AD, "M", "玲"),
+ ]
+
+
+def _seg_41() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xF9AE, "M", "瑩"),
+ (0xF9AF, "M", "羚"),
+ (0xF9B0, "M", "聆"),
+ (0xF9B1, "M", "鈴"),
+ (0xF9B2, "M", "零"),
+ (0xF9B3, "M", "靈"),
+ (0xF9B4, "M", "領"),
+ (0xF9B5, "M", "例"),
+ (0xF9B6, "M", "禮"),
+ (0xF9B7, "M", "醴"),
+ (0xF9B8, "M", "隸"),
+ (0xF9B9, "M", "惡"),
+ (0xF9BA, "M", "了"),
+ (0xF9BB, "M", "僚"),
+ (0xF9BC, "M", "寮"),
+ (0xF9BD, "M", "尿"),
+ (0xF9BE, "M", "料"),
+ (0xF9BF, "M", "樂"),
+ (0xF9C0, "M", "燎"),
+ (0xF9C1, "M", "療"),
+ (0xF9C2, "M", "蓼"),
+ (0xF9C3, "M", "遼"),
+ (0xF9C4, "M", "龍"),
+ (0xF9C5, "M", "暈"),
+ (0xF9C6, "M", "阮"),
+ (0xF9C7, "M", "劉"),
+ (0xF9C8, "M", "杻"),
+ (0xF9C9, "M", "柳"),
+ (0xF9CA, "M", "流"),
+ (0xF9CB, "M", "溜"),
+ (0xF9CC, "M", "琉"),
+ (0xF9CD, "M", "留"),
+ (0xF9CE, "M", "硫"),
+ (0xF9CF, "M", "紐"),
+ (0xF9D0, "M", "類"),
+ (0xF9D1, "M", "六"),
+ (0xF9D2, "M", "戮"),
+ (0xF9D3, "M", "陸"),
+ (0xF9D4, "M", "倫"),
+ (0xF9D5, "M", "崙"),
+ (0xF9D6, "M", "淪"),
+ (0xF9D7, "M", "輪"),
+ (0xF9D8, "M", "律"),
+ (0xF9D9, "M", "慄"),
+ (0xF9DA, "M", "栗"),
+ (0xF9DB, "M", "率"),
+ (0xF9DC, "M", "隆"),
+ (0xF9DD, "M", "利"),
+ (0xF9DE, "M", "吏"),
+ (0xF9DF, "M", "履"),
+ (0xF9E0, "M", "易"),
+ (0xF9E1, "M", "李"),
+ (0xF9E2, "M", "梨"),
+ (0xF9E3, "M", "泥"),
+ (0xF9E4, "M", "理"),
+ (0xF9E5, "M", "痢"),
+ (0xF9E6, "M", "罹"),
+ (0xF9E7, "M", "裏"),
+ (0xF9E8, "M", "裡"),
+ (0xF9E9, "M", "里"),
+ (0xF9EA, "M", "離"),
+ (0xF9EB, "M", "匿"),
+ (0xF9EC, "M", "溺"),
+ (0xF9ED, "M", "吝"),
+ (0xF9EE, "M", "燐"),
+ (0xF9EF, "M", "璘"),
+ (0xF9F0, "M", "藺"),
+ (0xF9F1, "M", "隣"),
+ (0xF9F2, "M", "鱗"),
+ (0xF9F3, "M", "麟"),
+ (0xF9F4, "M", "林"),
+ (0xF9F5, "M", "淋"),
+ (0xF9F6, "M", "臨"),
+ (0xF9F7, "M", "立"),
+ (0xF9F8, "M", "笠"),
+ (0xF9F9, "M", "粒"),
+ (0xF9FA, "M", "狀"),
+ (0xF9FB, "M", "炙"),
+ (0xF9FC, "M", "識"),
+ (0xF9FD, "M", "什"),
+ (0xF9FE, "M", "茶"),
+ (0xF9FF, "M", "刺"),
+ (0xFA00, "M", "切"),
+ (0xFA01, "M", "度"),
+ (0xFA02, "M", "拓"),
+ (0xFA03, "M", "糖"),
+ (0xFA04, "M", "宅"),
+ (0xFA05, "M", "洞"),
+ (0xFA06, "M", "暴"),
+ (0xFA07, "M", "輻"),
+ (0xFA08, "M", "行"),
+ (0xFA09, "M", "降"),
+ (0xFA0A, "M", "見"),
+ (0xFA0B, "M", "廓"),
+ (0xFA0C, "M", "兀"),
+ (0xFA0D, "M", "嗀"),
+ (0xFA0E, "V"),
+ (0xFA10, "M", "塚"),
+ (0xFA11, "V"),
+ (0xFA12, "M", "晴"),
+ ]
+
+
+def _seg_42() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFA13, "V"),
+ (0xFA15, "M", "凞"),
+ (0xFA16, "M", "猪"),
+ (0xFA17, "M", "益"),
+ (0xFA18, "M", "礼"),
+ (0xFA19, "M", "神"),
+ (0xFA1A, "M", "祥"),
+ (0xFA1B, "M", "福"),
+ (0xFA1C, "M", "靖"),
+ (0xFA1D, "M", "精"),
+ (0xFA1E, "M", "羽"),
+ (0xFA1F, "V"),
+ (0xFA20, "M", "蘒"),
+ (0xFA21, "V"),
+ (0xFA22, "M", "諸"),
+ (0xFA23, "V"),
+ (0xFA25, "M", "逸"),
+ (0xFA26, "M", "都"),
+ (0xFA27, "V"),
+ (0xFA2A, "M", "飯"),
+ (0xFA2B, "M", "飼"),
+ (0xFA2C, "M", "館"),
+ (0xFA2D, "M", "鶴"),
+ (0xFA2E, "M", "郞"),
+ (0xFA2F, "M", "隷"),
+ (0xFA30, "M", "侮"),
+ (0xFA31, "M", "僧"),
+ (0xFA32, "M", "免"),
+ (0xFA33, "M", "勉"),
+ (0xFA34, "M", "勤"),
+ (0xFA35, "M", "卑"),
+ (0xFA36, "M", "喝"),
+ (0xFA37, "M", "嘆"),
+ (0xFA38, "M", "器"),
+ (0xFA39, "M", "塀"),
+ (0xFA3A, "M", "墨"),
+ (0xFA3B, "M", "層"),
+ (0xFA3C, "M", "屮"),
+ (0xFA3D, "M", "悔"),
+ (0xFA3E, "M", "慨"),
+ (0xFA3F, "M", "憎"),
+ (0xFA40, "M", "懲"),
+ (0xFA41, "M", "敏"),
+ (0xFA42, "M", "既"),
+ (0xFA43, "M", "暑"),
+ (0xFA44, "M", "梅"),
+ (0xFA45, "M", "海"),
+ (0xFA46, "M", "渚"),
+ (0xFA47, "M", "漢"),
+ (0xFA48, "M", "煮"),
+ (0xFA49, "M", "爫"),
+ (0xFA4A, "M", "琢"),
+ (0xFA4B, "M", "碑"),
+ (0xFA4C, "M", "社"),
+ (0xFA4D, "M", "祉"),
+ (0xFA4E, "M", "祈"),
+ (0xFA4F, "M", "祐"),
+ (0xFA50, "M", "祖"),
+ (0xFA51, "M", "祝"),
+ (0xFA52, "M", "禍"),
+ (0xFA53, "M", "禎"),
+ (0xFA54, "M", "穀"),
+ (0xFA55, "M", "突"),
+ (0xFA56, "M", "節"),
+ (0xFA57, "M", "練"),
+ (0xFA58, "M", "縉"),
+ (0xFA59, "M", "繁"),
+ (0xFA5A, "M", "署"),
+ (0xFA5B, "M", "者"),
+ (0xFA5C, "M", "臭"),
+ (0xFA5D, "M", "艹"),
+ (0xFA5F, "M", "著"),
+ (0xFA60, "M", "褐"),
+ (0xFA61, "M", "視"),
+ (0xFA62, "M", "謁"),
+ (0xFA63, "M", "謹"),
+ (0xFA64, "M", "賓"),
+ (0xFA65, "M", "贈"),
+ (0xFA66, "M", "辶"),
+ (0xFA67, "M", "逸"),
+ (0xFA68, "M", "難"),
+ (0xFA69, "M", "響"),
+ (0xFA6A, "M", "頻"),
+ (0xFA6B, "M", "恵"),
+ (0xFA6C, "M", "𤋮"),
+ (0xFA6D, "M", "舘"),
+ (0xFA6E, "X"),
+ (0xFA70, "M", "並"),
+ (0xFA71, "M", "况"),
+ (0xFA72, "M", "全"),
+ (0xFA73, "M", "侀"),
+ (0xFA74, "M", "充"),
+ (0xFA75, "M", "冀"),
+ (0xFA76, "M", "勇"),
+ (0xFA77, "M", "勺"),
+ (0xFA78, "M", "喝"),
+ (0xFA79, "M", "啕"),
+ (0xFA7A, "M", "喙"),
+ (0xFA7B, "M", "嗢"),
+ (0xFA7C, "M", "塚"),
+ ]
+
+
+def _seg_43() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFA7D, "M", "墳"),
+ (0xFA7E, "M", "奄"),
+ (0xFA7F, "M", "奔"),
+ (0xFA80, "M", "婢"),
+ (0xFA81, "M", "嬨"),
+ (0xFA82, "M", "廒"),
+ (0xFA83, "M", "廙"),
+ (0xFA84, "M", "彩"),
+ (0xFA85, "M", "徭"),
+ (0xFA86, "M", "惘"),
+ (0xFA87, "M", "慎"),
+ (0xFA88, "M", "愈"),
+ (0xFA89, "M", "憎"),
+ (0xFA8A, "M", "慠"),
+ (0xFA8B, "M", "懲"),
+ (0xFA8C, "M", "戴"),
+ (0xFA8D, "M", "揄"),
+ (0xFA8E, "M", "搜"),
+ (0xFA8F, "M", "摒"),
+ (0xFA90, "M", "敖"),
+ (0xFA91, "M", "晴"),
+ (0xFA92, "M", "朗"),
+ (0xFA93, "M", "望"),
+ (0xFA94, "M", "杖"),
+ (0xFA95, "M", "歹"),
+ (0xFA96, "M", "殺"),
+ (0xFA97, "M", "流"),
+ (0xFA98, "M", "滛"),
+ (0xFA99, "M", "滋"),
+ (0xFA9A, "M", "漢"),
+ (0xFA9B, "M", "瀞"),
+ (0xFA9C, "M", "煮"),
+ (0xFA9D, "M", "瞧"),
+ (0xFA9E, "M", "爵"),
+ (0xFA9F, "M", "犯"),
+ (0xFAA0, "M", "猪"),
+ (0xFAA1, "M", "瑱"),
+ (0xFAA2, "M", "甆"),
+ (0xFAA3, "M", "画"),
+ (0xFAA4, "M", "瘝"),
+ (0xFAA5, "M", "瘟"),
+ (0xFAA6, "M", "益"),
+ (0xFAA7, "M", "盛"),
+ (0xFAA8, "M", "直"),
+ (0xFAA9, "M", "睊"),
+ (0xFAAA, "M", "着"),
+ (0xFAAB, "M", "磌"),
+ (0xFAAC, "M", "窱"),
+ (0xFAAD, "M", "節"),
+ (0xFAAE, "M", "类"),
+ (0xFAAF, "M", "絛"),
+ (0xFAB0, "M", "練"),
+ (0xFAB1, "M", "缾"),
+ (0xFAB2, "M", "者"),
+ (0xFAB3, "M", "荒"),
+ (0xFAB4, "M", "華"),
+ (0xFAB5, "M", "蝹"),
+ (0xFAB6, "M", "襁"),
+ (0xFAB7, "M", "覆"),
+ (0xFAB8, "M", "視"),
+ (0xFAB9, "M", "調"),
+ (0xFABA, "M", "諸"),
+ (0xFABB, "M", "請"),
+ (0xFABC, "M", "謁"),
+ (0xFABD, "M", "諾"),
+ (0xFABE, "M", "諭"),
+ (0xFABF, "M", "謹"),
+ (0xFAC0, "M", "變"),
+ (0xFAC1, "M", "贈"),
+ (0xFAC2, "M", "輸"),
+ (0xFAC3, "M", "遲"),
+ (0xFAC4, "M", "醙"),
+ (0xFAC5, "M", "鉶"),
+ (0xFAC6, "M", "陼"),
+ (0xFAC7, "M", "難"),
+ (0xFAC8, "M", "靖"),
+ (0xFAC9, "M", "韛"),
+ (0xFACA, "M", "響"),
+ (0xFACB, "M", "頋"),
+ (0xFACC, "M", "頻"),
+ (0xFACD, "M", "鬒"),
+ (0xFACE, "M", "龜"),
+ (0xFACF, "M", "𢡊"),
+ (0xFAD0, "M", "𢡄"),
+ (0xFAD1, "M", "𣏕"),
+ (0xFAD2, "M", "㮝"),
+ (0xFAD3, "M", "䀘"),
+ (0xFAD4, "M", "䀹"),
+ (0xFAD5, "M", "𥉉"),
+ (0xFAD6, "M", "𥳐"),
+ (0xFAD7, "M", "𧻓"),
+ (0xFAD8, "M", "齃"),
+ (0xFAD9, "M", "龎"),
+ (0xFADA, "X"),
+ (0xFB00, "M", "ff"),
+ (0xFB01, "M", "fi"),
+ (0xFB02, "M", "fl"),
+ (0xFB03, "M", "ffi"),
+ (0xFB04, "M", "ffl"),
+ (0xFB05, "M", "st"),
+ ]
+
+
+def _seg_44() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFB07, "X"),
+ (0xFB13, "M", "մն"),
+ (0xFB14, "M", "մե"),
+ (0xFB15, "M", "մի"),
+ (0xFB16, "M", "վն"),
+ (0xFB17, "M", "մխ"),
+ (0xFB18, "X"),
+ (0xFB1D, "M", "יִ"),
+ (0xFB1E, "V"),
+ (0xFB1F, "M", "ײַ"),
+ (0xFB20, "M", "ע"),
+ (0xFB21, "M", "א"),
+ (0xFB22, "M", "ד"),
+ (0xFB23, "M", "ה"),
+ (0xFB24, "M", "כ"),
+ (0xFB25, "M", "ל"),
+ (0xFB26, "M", "ם"),
+ (0xFB27, "M", "ר"),
+ (0xFB28, "M", "ת"),
+ (0xFB29, "3", "+"),
+ (0xFB2A, "M", "שׁ"),
+ (0xFB2B, "M", "שׂ"),
+ (0xFB2C, "M", "שּׁ"),
+ (0xFB2D, "M", "שּׂ"),
+ (0xFB2E, "M", "אַ"),
+ (0xFB2F, "M", "אָ"),
+ (0xFB30, "M", "אּ"),
+ (0xFB31, "M", "בּ"),
+ (0xFB32, "M", "גּ"),
+ (0xFB33, "M", "דּ"),
+ (0xFB34, "M", "הּ"),
+ (0xFB35, "M", "וּ"),
+ (0xFB36, "M", "זּ"),
+ (0xFB37, "X"),
+ (0xFB38, "M", "טּ"),
+ (0xFB39, "M", "יּ"),
+ (0xFB3A, "M", "ךּ"),
+ (0xFB3B, "M", "כּ"),
+ (0xFB3C, "M", "לּ"),
+ (0xFB3D, "X"),
+ (0xFB3E, "M", "מּ"),
+ (0xFB3F, "X"),
+ (0xFB40, "M", "נּ"),
+ (0xFB41, "M", "סּ"),
+ (0xFB42, "X"),
+ (0xFB43, "M", "ףּ"),
+ (0xFB44, "M", "פּ"),
+ (0xFB45, "X"),
+ (0xFB46, "M", "צּ"),
+ (0xFB47, "M", "קּ"),
+ (0xFB48, "M", "רּ"),
+ (0xFB49, "M", "שּ"),
+ (0xFB4A, "M", "תּ"),
+ (0xFB4B, "M", "וֹ"),
+ (0xFB4C, "M", "בֿ"),
+ (0xFB4D, "M", "כֿ"),
+ (0xFB4E, "M", "פֿ"),
+ (0xFB4F, "M", "אל"),
+ (0xFB50, "M", "ٱ"),
+ (0xFB52, "M", "ٻ"),
+ (0xFB56, "M", "پ"),
+ (0xFB5A, "M", "ڀ"),
+ (0xFB5E, "M", "ٺ"),
+ (0xFB62, "M", "ٿ"),
+ (0xFB66, "M", "ٹ"),
+ (0xFB6A, "M", "ڤ"),
+ (0xFB6E, "M", "ڦ"),
+ (0xFB72, "M", "ڄ"),
+ (0xFB76, "M", "ڃ"),
+ (0xFB7A, "M", "چ"),
+ (0xFB7E, "M", "ڇ"),
+ (0xFB82, "M", "ڍ"),
+ (0xFB84, "M", "ڌ"),
+ (0xFB86, "M", "ڎ"),
+ (0xFB88, "M", "ڈ"),
+ (0xFB8A, "M", "ژ"),
+ (0xFB8C, "M", "ڑ"),
+ (0xFB8E, "M", "ک"),
+ (0xFB92, "M", "گ"),
+ (0xFB96, "M", "ڳ"),
+ (0xFB9A, "M", "ڱ"),
+ (0xFB9E, "M", "ں"),
+ (0xFBA0, "M", "ڻ"),
+ (0xFBA4, "M", "ۀ"),
+ (0xFBA6, "M", "ہ"),
+ (0xFBAA, "M", "ھ"),
+ (0xFBAE, "M", "ے"),
+ (0xFBB0, "M", "ۓ"),
+ (0xFBB2, "V"),
+ (0xFBC3, "X"),
+ (0xFBD3, "M", "ڭ"),
+ (0xFBD7, "M", "ۇ"),
+ (0xFBD9, "M", "ۆ"),
+ (0xFBDB, "M", "ۈ"),
+ (0xFBDD, "M", "ۇٴ"),
+ (0xFBDE, "M", "ۋ"),
+ (0xFBE0, "M", "ۅ"),
+ (0xFBE2, "M", "ۉ"),
+ (0xFBE4, "M", "ې"),
+ (0xFBE8, "M", "ى"),
+ ]
+
+
+def _seg_45() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFBEA, "M", "ئا"),
+ (0xFBEC, "M", "ئە"),
+ (0xFBEE, "M", "ئو"),
+ (0xFBF0, "M", "ئۇ"),
+ (0xFBF2, "M", "ئۆ"),
+ (0xFBF4, "M", "ئۈ"),
+ (0xFBF6, "M", "ئې"),
+ (0xFBF9, "M", "ئى"),
+ (0xFBFC, "M", "ی"),
+ (0xFC00, "M", "ئج"),
+ (0xFC01, "M", "ئح"),
+ (0xFC02, "M", "ئم"),
+ (0xFC03, "M", "ئى"),
+ (0xFC04, "M", "ئي"),
+ (0xFC05, "M", "بج"),
+ (0xFC06, "M", "بح"),
+ (0xFC07, "M", "بخ"),
+ (0xFC08, "M", "بم"),
+ (0xFC09, "M", "بى"),
+ (0xFC0A, "M", "بي"),
+ (0xFC0B, "M", "تج"),
+ (0xFC0C, "M", "تح"),
+ (0xFC0D, "M", "تخ"),
+ (0xFC0E, "M", "تم"),
+ (0xFC0F, "M", "تى"),
+ (0xFC10, "M", "تي"),
+ (0xFC11, "M", "ثج"),
+ (0xFC12, "M", "ثم"),
+ (0xFC13, "M", "ثى"),
+ (0xFC14, "M", "ثي"),
+ (0xFC15, "M", "جح"),
+ (0xFC16, "M", "جم"),
+ (0xFC17, "M", "حج"),
+ (0xFC18, "M", "حم"),
+ (0xFC19, "M", "خج"),
+ (0xFC1A, "M", "خح"),
+ (0xFC1B, "M", "خم"),
+ (0xFC1C, "M", "سج"),
+ (0xFC1D, "M", "سح"),
+ (0xFC1E, "M", "سخ"),
+ (0xFC1F, "M", "سم"),
+ (0xFC20, "M", "صح"),
+ (0xFC21, "M", "صم"),
+ (0xFC22, "M", "ضج"),
+ (0xFC23, "M", "ضح"),
+ (0xFC24, "M", "ضخ"),
+ (0xFC25, "M", "ضم"),
+ (0xFC26, "M", "طح"),
+ (0xFC27, "M", "طم"),
+ (0xFC28, "M", "ظم"),
+ (0xFC29, "M", "عج"),
+ (0xFC2A, "M", "عم"),
+ (0xFC2B, "M", "غج"),
+ (0xFC2C, "M", "غم"),
+ (0xFC2D, "M", "فج"),
+ (0xFC2E, "M", "فح"),
+ (0xFC2F, "M", "فخ"),
+ (0xFC30, "M", "فم"),
+ (0xFC31, "M", "فى"),
+ (0xFC32, "M", "في"),
+ (0xFC33, "M", "قح"),
+ (0xFC34, "M", "قم"),
+ (0xFC35, "M", "قى"),
+ (0xFC36, "M", "قي"),
+ (0xFC37, "M", "كا"),
+ (0xFC38, "M", "كج"),
+ (0xFC39, "M", "كح"),
+ (0xFC3A, "M", "كخ"),
+ (0xFC3B, "M", "كل"),
+ (0xFC3C, "M", "كم"),
+ (0xFC3D, "M", "كى"),
+ (0xFC3E, "M", "كي"),
+ (0xFC3F, "M", "لج"),
+ (0xFC40, "M", "لح"),
+ (0xFC41, "M", "لخ"),
+ (0xFC42, "M", "لم"),
+ (0xFC43, "M", "لى"),
+ (0xFC44, "M", "لي"),
+ (0xFC45, "M", "مج"),
+ (0xFC46, "M", "مح"),
+ (0xFC47, "M", "مخ"),
+ (0xFC48, "M", "مم"),
+ (0xFC49, "M", "مى"),
+ (0xFC4A, "M", "مي"),
+ (0xFC4B, "M", "نج"),
+ (0xFC4C, "M", "نح"),
+ (0xFC4D, "M", "نخ"),
+ (0xFC4E, "M", "نم"),
+ (0xFC4F, "M", "نى"),
+ (0xFC50, "M", "ني"),
+ (0xFC51, "M", "هج"),
+ (0xFC52, "M", "هم"),
+ (0xFC53, "M", "هى"),
+ (0xFC54, "M", "هي"),
+ (0xFC55, "M", "يج"),
+ (0xFC56, "M", "يح"),
+ (0xFC57, "M", "يخ"),
+ (0xFC58, "M", "يم"),
+ (0xFC59, "M", "يى"),
+ (0xFC5A, "M", "يي"),
+ ]
+
+
+def _seg_46() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFC5B, "M", "ذٰ"),
+ (0xFC5C, "M", "رٰ"),
+ (0xFC5D, "M", "ىٰ"),
+ (0xFC5E, "3", " ٌّ"),
+ (0xFC5F, "3", " ٍّ"),
+ (0xFC60, "3", " َّ"),
+ (0xFC61, "3", " ُّ"),
+ (0xFC62, "3", " ِّ"),
+ (0xFC63, "3", " ّٰ"),
+ (0xFC64, "M", "ئر"),
+ (0xFC65, "M", "ئز"),
+ (0xFC66, "M", "ئم"),
+ (0xFC67, "M", "ئن"),
+ (0xFC68, "M", "ئى"),
+ (0xFC69, "M", "ئي"),
+ (0xFC6A, "M", "بر"),
+ (0xFC6B, "M", "بز"),
+ (0xFC6C, "M", "بم"),
+ (0xFC6D, "M", "بن"),
+ (0xFC6E, "M", "بى"),
+ (0xFC6F, "M", "بي"),
+ (0xFC70, "M", "تر"),
+ (0xFC71, "M", "تز"),
+ (0xFC72, "M", "تم"),
+ (0xFC73, "M", "تن"),
+ (0xFC74, "M", "تى"),
+ (0xFC75, "M", "تي"),
+ (0xFC76, "M", "ثر"),
+ (0xFC77, "M", "ثز"),
+ (0xFC78, "M", "ثم"),
+ (0xFC79, "M", "ثن"),
+ (0xFC7A, "M", "ثى"),
+ (0xFC7B, "M", "ثي"),
+ (0xFC7C, "M", "فى"),
+ (0xFC7D, "M", "في"),
+ (0xFC7E, "M", "قى"),
+ (0xFC7F, "M", "قي"),
+ (0xFC80, "M", "كا"),
+ (0xFC81, "M", "كل"),
+ (0xFC82, "M", "كم"),
+ (0xFC83, "M", "كى"),
+ (0xFC84, "M", "كي"),
+ (0xFC85, "M", "لم"),
+ (0xFC86, "M", "لى"),
+ (0xFC87, "M", "لي"),
+ (0xFC88, "M", "ما"),
+ (0xFC89, "M", "مم"),
+ (0xFC8A, "M", "نر"),
+ (0xFC8B, "M", "نز"),
+ (0xFC8C, "M", "نم"),
+ (0xFC8D, "M", "نن"),
+ (0xFC8E, "M", "نى"),
+ (0xFC8F, "M", "ني"),
+ (0xFC90, "M", "ىٰ"),
+ (0xFC91, "M", "ير"),
+ (0xFC92, "M", "يز"),
+ (0xFC93, "M", "يم"),
+ (0xFC94, "M", "ين"),
+ (0xFC95, "M", "يى"),
+ (0xFC96, "M", "يي"),
+ (0xFC97, "M", "ئج"),
+ (0xFC98, "M", "ئح"),
+ (0xFC99, "M", "ئخ"),
+ (0xFC9A, "M", "ئم"),
+ (0xFC9B, "M", "ئه"),
+ (0xFC9C, "M", "بج"),
+ (0xFC9D, "M", "بح"),
+ (0xFC9E, "M", "بخ"),
+ (0xFC9F, "M", "بم"),
+ (0xFCA0, "M", "به"),
+ (0xFCA1, "M", "تج"),
+ (0xFCA2, "M", "تح"),
+ (0xFCA3, "M", "تخ"),
+ (0xFCA4, "M", "تم"),
+ (0xFCA5, "M", "ته"),
+ (0xFCA6, "M", "ثم"),
+ (0xFCA7, "M", "جح"),
+ (0xFCA8, "M", "جم"),
+ (0xFCA9, "M", "حج"),
+ (0xFCAA, "M", "حم"),
+ (0xFCAB, "M", "خج"),
+ (0xFCAC, "M", "خم"),
+ (0xFCAD, "M", "سج"),
+ (0xFCAE, "M", "سح"),
+ (0xFCAF, "M", "سخ"),
+ (0xFCB0, "M", "سم"),
+ (0xFCB1, "M", "صح"),
+ (0xFCB2, "M", "صخ"),
+ (0xFCB3, "M", "صم"),
+ (0xFCB4, "M", "ضج"),
+ (0xFCB5, "M", "ضح"),
+ (0xFCB6, "M", "ضخ"),
+ (0xFCB7, "M", "ضم"),
+ (0xFCB8, "M", "طح"),
+ (0xFCB9, "M", "ظم"),
+ (0xFCBA, "M", "عج"),
+ (0xFCBB, "M", "عم"),
+ (0xFCBC, "M", "غج"),
+ (0xFCBD, "M", "غم"),
+ (0xFCBE, "M", "فج"),
+ ]
+
+
+def _seg_47() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFCBF, "M", "فح"),
+ (0xFCC0, "M", "فخ"),
+ (0xFCC1, "M", "فم"),
+ (0xFCC2, "M", "قح"),
+ (0xFCC3, "M", "قم"),
+ (0xFCC4, "M", "كج"),
+ (0xFCC5, "M", "كح"),
+ (0xFCC6, "M", "كخ"),
+ (0xFCC7, "M", "كل"),
+ (0xFCC8, "M", "كم"),
+ (0xFCC9, "M", "لج"),
+ (0xFCCA, "M", "لح"),
+ (0xFCCB, "M", "لخ"),
+ (0xFCCC, "M", "لم"),
+ (0xFCCD, "M", "له"),
+ (0xFCCE, "M", "مج"),
+ (0xFCCF, "M", "مح"),
+ (0xFCD0, "M", "مخ"),
+ (0xFCD1, "M", "مم"),
+ (0xFCD2, "M", "نج"),
+ (0xFCD3, "M", "نح"),
+ (0xFCD4, "M", "نخ"),
+ (0xFCD5, "M", "نم"),
+ (0xFCD6, "M", "نه"),
+ (0xFCD7, "M", "هج"),
+ (0xFCD8, "M", "هم"),
+ (0xFCD9, "M", "هٰ"),
+ (0xFCDA, "M", "يج"),
+ (0xFCDB, "M", "يح"),
+ (0xFCDC, "M", "يخ"),
+ (0xFCDD, "M", "يم"),
+ (0xFCDE, "M", "يه"),
+ (0xFCDF, "M", "ئم"),
+ (0xFCE0, "M", "ئه"),
+ (0xFCE1, "M", "بم"),
+ (0xFCE2, "M", "به"),
+ (0xFCE3, "M", "تم"),
+ (0xFCE4, "M", "ته"),
+ (0xFCE5, "M", "ثم"),
+ (0xFCE6, "M", "ثه"),
+ (0xFCE7, "M", "سم"),
+ (0xFCE8, "M", "سه"),
+ (0xFCE9, "M", "شم"),
+ (0xFCEA, "M", "شه"),
+ (0xFCEB, "M", "كل"),
+ (0xFCEC, "M", "كم"),
+ (0xFCED, "M", "لم"),
+ (0xFCEE, "M", "نم"),
+ (0xFCEF, "M", "نه"),
+ (0xFCF0, "M", "يم"),
+ (0xFCF1, "M", "يه"),
+ (0xFCF2, "M", "ـَّ"),
+ (0xFCF3, "M", "ـُّ"),
+ (0xFCF4, "M", "ـِّ"),
+ (0xFCF5, "M", "طى"),
+ (0xFCF6, "M", "طي"),
+ (0xFCF7, "M", "عى"),
+ (0xFCF8, "M", "عي"),
+ (0xFCF9, "M", "غى"),
+ (0xFCFA, "M", "غي"),
+ (0xFCFB, "M", "سى"),
+ (0xFCFC, "M", "سي"),
+ (0xFCFD, "M", "شى"),
+ (0xFCFE, "M", "شي"),
+ (0xFCFF, "M", "حى"),
+ (0xFD00, "M", "حي"),
+ (0xFD01, "M", "جى"),
+ (0xFD02, "M", "جي"),
+ (0xFD03, "M", "خى"),
+ (0xFD04, "M", "خي"),
+ (0xFD05, "M", "صى"),
+ (0xFD06, "M", "صي"),
+ (0xFD07, "M", "ضى"),
+ (0xFD08, "M", "ضي"),
+ (0xFD09, "M", "شج"),
+ (0xFD0A, "M", "شح"),
+ (0xFD0B, "M", "شخ"),
+ (0xFD0C, "M", "شم"),
+ (0xFD0D, "M", "شر"),
+ (0xFD0E, "M", "سر"),
+ (0xFD0F, "M", "صر"),
+ (0xFD10, "M", "ضر"),
+ (0xFD11, "M", "طى"),
+ (0xFD12, "M", "طي"),
+ (0xFD13, "M", "عى"),
+ (0xFD14, "M", "عي"),
+ (0xFD15, "M", "غى"),
+ (0xFD16, "M", "غي"),
+ (0xFD17, "M", "سى"),
+ (0xFD18, "M", "سي"),
+ (0xFD19, "M", "شى"),
+ (0xFD1A, "M", "شي"),
+ (0xFD1B, "M", "حى"),
+ (0xFD1C, "M", "حي"),
+ (0xFD1D, "M", "جى"),
+ (0xFD1E, "M", "جي"),
+ (0xFD1F, "M", "خى"),
+ (0xFD20, "M", "خي"),
+ (0xFD21, "M", "صى"),
+ (0xFD22, "M", "صي"),
+ ]
+
+
+def _seg_48() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFD23, "M", "ضى"),
+ (0xFD24, "M", "ضي"),
+ (0xFD25, "M", "شج"),
+ (0xFD26, "M", "شح"),
+ (0xFD27, "M", "شخ"),
+ (0xFD28, "M", "شم"),
+ (0xFD29, "M", "شر"),
+ (0xFD2A, "M", "سر"),
+ (0xFD2B, "M", "صر"),
+ (0xFD2C, "M", "ضر"),
+ (0xFD2D, "M", "شج"),
+ (0xFD2E, "M", "شح"),
+ (0xFD2F, "M", "شخ"),
+ (0xFD30, "M", "شم"),
+ (0xFD31, "M", "سه"),
+ (0xFD32, "M", "شه"),
+ (0xFD33, "M", "طم"),
+ (0xFD34, "M", "سج"),
+ (0xFD35, "M", "سح"),
+ (0xFD36, "M", "سخ"),
+ (0xFD37, "M", "شج"),
+ (0xFD38, "M", "شح"),
+ (0xFD39, "M", "شخ"),
+ (0xFD3A, "M", "طم"),
+ (0xFD3B, "M", "ظم"),
+ (0xFD3C, "M", "اً"),
+ (0xFD3E, "V"),
+ (0xFD50, "M", "تجم"),
+ (0xFD51, "M", "تحج"),
+ (0xFD53, "M", "تحم"),
+ (0xFD54, "M", "تخم"),
+ (0xFD55, "M", "تمج"),
+ (0xFD56, "M", "تمح"),
+ (0xFD57, "M", "تمخ"),
+ (0xFD58, "M", "جمح"),
+ (0xFD5A, "M", "حمي"),
+ (0xFD5B, "M", "حمى"),
+ (0xFD5C, "M", "سحج"),
+ (0xFD5D, "M", "سجح"),
+ (0xFD5E, "M", "سجى"),
+ (0xFD5F, "M", "سمح"),
+ (0xFD61, "M", "سمج"),
+ (0xFD62, "M", "سمم"),
+ (0xFD64, "M", "صحح"),
+ (0xFD66, "M", "صمم"),
+ (0xFD67, "M", "شحم"),
+ (0xFD69, "M", "شجي"),
+ (0xFD6A, "M", "شمخ"),
+ (0xFD6C, "M", "شمم"),
+ (0xFD6E, "M", "ضحى"),
+ (0xFD6F, "M", "ضخم"),
+ (0xFD71, "M", "طمح"),
+ (0xFD73, "M", "طمم"),
+ (0xFD74, "M", "طمي"),
+ (0xFD75, "M", "عجم"),
+ (0xFD76, "M", "عمم"),
+ (0xFD78, "M", "عمى"),
+ (0xFD79, "M", "غمم"),
+ (0xFD7A, "M", "غمي"),
+ (0xFD7B, "M", "غمى"),
+ (0xFD7C, "M", "فخم"),
+ (0xFD7E, "M", "قمح"),
+ (0xFD7F, "M", "قمم"),
+ (0xFD80, "M", "لحم"),
+ (0xFD81, "M", "لحي"),
+ (0xFD82, "M", "لحى"),
+ (0xFD83, "M", "لجج"),
+ (0xFD85, "M", "لخم"),
+ (0xFD87, "M", "لمح"),
+ (0xFD89, "M", "محج"),
+ (0xFD8A, "M", "محم"),
+ (0xFD8B, "M", "محي"),
+ (0xFD8C, "M", "مجح"),
+ (0xFD8D, "M", "مجم"),
+ (0xFD8E, "M", "مخج"),
+ (0xFD8F, "M", "مخم"),
+ (0xFD90, "X"),
+ (0xFD92, "M", "مجخ"),
+ (0xFD93, "M", "همج"),
+ (0xFD94, "M", "همم"),
+ (0xFD95, "M", "نحم"),
+ (0xFD96, "M", "نحى"),
+ (0xFD97, "M", "نجم"),
+ (0xFD99, "M", "نجى"),
+ (0xFD9A, "M", "نمي"),
+ (0xFD9B, "M", "نمى"),
+ (0xFD9C, "M", "يمم"),
+ (0xFD9E, "M", "بخي"),
+ (0xFD9F, "M", "تجي"),
+ (0xFDA0, "M", "تجى"),
+ (0xFDA1, "M", "تخي"),
+ (0xFDA2, "M", "تخى"),
+ (0xFDA3, "M", "تمي"),
+ (0xFDA4, "M", "تمى"),
+ (0xFDA5, "M", "جمي"),
+ (0xFDA6, "M", "جحى"),
+ (0xFDA7, "M", "جمى"),
+ (0xFDA8, "M", "سخى"),
+ (0xFDA9, "M", "صحي"),
+ (0xFDAA, "M", "شحي"),
+ ]
+
+
+def _seg_49() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFDAB, "M", "ضحي"),
+ (0xFDAC, "M", "لجي"),
+ (0xFDAD, "M", "لمي"),
+ (0xFDAE, "M", "يحي"),
+ (0xFDAF, "M", "يجي"),
+ (0xFDB0, "M", "يمي"),
+ (0xFDB1, "M", "ممي"),
+ (0xFDB2, "M", "قمي"),
+ (0xFDB3, "M", "نحي"),
+ (0xFDB4, "M", "قمح"),
+ (0xFDB5, "M", "لحم"),
+ (0xFDB6, "M", "عمي"),
+ (0xFDB7, "M", "كمي"),
+ (0xFDB8, "M", "نجح"),
+ (0xFDB9, "M", "مخي"),
+ (0xFDBA, "M", "لجم"),
+ (0xFDBB, "M", "كمم"),
+ (0xFDBC, "M", "لجم"),
+ (0xFDBD, "M", "نجح"),
+ (0xFDBE, "M", "جحي"),
+ (0xFDBF, "M", "حجي"),
+ (0xFDC0, "M", "مجي"),
+ (0xFDC1, "M", "فمي"),
+ (0xFDC2, "M", "بحي"),
+ (0xFDC3, "M", "كمم"),
+ (0xFDC4, "M", "عجم"),
+ (0xFDC5, "M", "صمم"),
+ (0xFDC6, "M", "سخي"),
+ (0xFDC7, "M", "نجي"),
+ (0xFDC8, "X"),
+ (0xFDCF, "V"),
+ (0xFDD0, "X"),
+ (0xFDF0, "M", "صلے"),
+ (0xFDF1, "M", "قلے"),
+ (0xFDF2, "M", "الله"),
+ (0xFDF3, "M", "اكبر"),
+ (0xFDF4, "M", "محمد"),
+ (0xFDF5, "M", "صلعم"),
+ (0xFDF6, "M", "رسول"),
+ (0xFDF7, "M", "عليه"),
+ (0xFDF8, "M", "وسلم"),
+ (0xFDF9, "M", "صلى"),
+ (0xFDFA, "3", "صلى الله عليه وسلم"),
+ (0xFDFB, "3", "جل جلاله"),
+ (0xFDFC, "M", "ریال"),
+ (0xFDFD, "V"),
+ (0xFE00, "I"),
+ (0xFE10, "3", ","),
+ (0xFE11, "M", "、"),
+ (0xFE12, "X"),
+ (0xFE13, "3", ":"),
+ (0xFE14, "3", ";"),
+ (0xFE15, "3", "!"),
+ (0xFE16, "3", "?"),
+ (0xFE17, "M", "〖"),
+ (0xFE18, "M", "〗"),
+ (0xFE19, "X"),
+ (0xFE20, "V"),
+ (0xFE30, "X"),
+ (0xFE31, "M", "—"),
+ (0xFE32, "M", "–"),
+ (0xFE33, "3", "_"),
+ (0xFE35, "3", "("),
+ (0xFE36, "3", ")"),
+ (0xFE37, "3", "{"),
+ (0xFE38, "3", "}"),
+ (0xFE39, "M", "〔"),
+ (0xFE3A, "M", "〕"),
+ (0xFE3B, "M", "【"),
+ (0xFE3C, "M", "】"),
+ (0xFE3D, "M", "《"),
+ (0xFE3E, "M", "》"),
+ (0xFE3F, "M", "〈"),
+ (0xFE40, "M", "〉"),
+ (0xFE41, "M", "「"),
+ (0xFE42, "M", "」"),
+ (0xFE43, "M", "『"),
+ (0xFE44, "M", "』"),
+ (0xFE45, "V"),
+ (0xFE47, "3", "["),
+ (0xFE48, "3", "]"),
+ (0xFE49, "3", " ̅"),
+ (0xFE4D, "3", "_"),
+ (0xFE50, "3", ","),
+ (0xFE51, "M", "、"),
+ (0xFE52, "X"),
+ (0xFE54, "3", ";"),
+ (0xFE55, "3", ":"),
+ (0xFE56, "3", "?"),
+ (0xFE57, "3", "!"),
+ (0xFE58, "M", "—"),
+ (0xFE59, "3", "("),
+ (0xFE5A, "3", ")"),
+ (0xFE5B, "3", "{"),
+ (0xFE5C, "3", "}"),
+ (0xFE5D, "M", "〔"),
+ (0xFE5E, "M", "〕"),
+ (0xFE5F, "3", "#"),
+ (0xFE60, "3", "&"),
+ (0xFE61, "3", "*"),
+ ]
+
+
+def _seg_50() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFE62, "3", "+"),
+ (0xFE63, "M", "-"),
+ (0xFE64, "3", "<"),
+ (0xFE65, "3", ">"),
+ (0xFE66, "3", "="),
+ (0xFE67, "X"),
+ (0xFE68, "3", "\\"),
+ (0xFE69, "3", "$"),
+ (0xFE6A, "3", "%"),
+ (0xFE6B, "3", "@"),
+ (0xFE6C, "X"),
+ (0xFE70, "3", " ً"),
+ (0xFE71, "M", "ـً"),
+ (0xFE72, "3", " ٌ"),
+ (0xFE73, "V"),
+ (0xFE74, "3", " ٍ"),
+ (0xFE75, "X"),
+ (0xFE76, "3", " َ"),
+ (0xFE77, "M", "ـَ"),
+ (0xFE78, "3", " ُ"),
+ (0xFE79, "M", "ـُ"),
+ (0xFE7A, "3", " ِ"),
+ (0xFE7B, "M", "ـِ"),
+ (0xFE7C, "3", " ّ"),
+ (0xFE7D, "M", "ـّ"),
+ (0xFE7E, "3", " ْ"),
+ (0xFE7F, "M", "ـْ"),
+ (0xFE80, "M", "ء"),
+ (0xFE81, "M", "آ"),
+ (0xFE83, "M", "أ"),
+ (0xFE85, "M", "ؤ"),
+ (0xFE87, "M", "إ"),
+ (0xFE89, "M", "ئ"),
+ (0xFE8D, "M", "ا"),
+ (0xFE8F, "M", "ب"),
+ (0xFE93, "M", "ة"),
+ (0xFE95, "M", "ت"),
+ (0xFE99, "M", "ث"),
+ (0xFE9D, "M", "ج"),
+ (0xFEA1, "M", "ح"),
+ (0xFEA5, "M", "خ"),
+ (0xFEA9, "M", "د"),
+ (0xFEAB, "M", "ذ"),
+ (0xFEAD, "M", "ر"),
+ (0xFEAF, "M", "ز"),
+ (0xFEB1, "M", "س"),
+ (0xFEB5, "M", "ش"),
+ (0xFEB9, "M", "ص"),
+ (0xFEBD, "M", "ض"),
+ (0xFEC1, "M", "ط"),
+ (0xFEC5, "M", "ظ"),
+ (0xFEC9, "M", "ع"),
+ (0xFECD, "M", "غ"),
+ (0xFED1, "M", "ف"),
+ (0xFED5, "M", "ق"),
+ (0xFED9, "M", "ك"),
+ (0xFEDD, "M", "ل"),
+ (0xFEE1, "M", "م"),
+ (0xFEE5, "M", "ن"),
+ (0xFEE9, "M", "ه"),
+ (0xFEED, "M", "و"),
+ (0xFEEF, "M", "ى"),
+ (0xFEF1, "M", "ي"),
+ (0xFEF5, "M", "لآ"),
+ (0xFEF7, "M", "لأ"),
+ (0xFEF9, "M", "لإ"),
+ (0xFEFB, "M", "لا"),
+ (0xFEFD, "X"),
+ (0xFEFF, "I"),
+ (0xFF00, "X"),
+ (0xFF01, "3", "!"),
+ (0xFF02, "3", '"'),
+ (0xFF03, "3", "#"),
+ (0xFF04, "3", "$"),
+ (0xFF05, "3", "%"),
+ (0xFF06, "3", "&"),
+ (0xFF07, "3", "'"),
+ (0xFF08, "3", "("),
+ (0xFF09, "3", ")"),
+ (0xFF0A, "3", "*"),
+ (0xFF0B, "3", "+"),
+ (0xFF0C, "3", ","),
+ (0xFF0D, "M", "-"),
+ (0xFF0E, "M", "."),
+ (0xFF0F, "3", "/"),
+ (0xFF10, "M", "0"),
+ (0xFF11, "M", "1"),
+ (0xFF12, "M", "2"),
+ (0xFF13, "M", "3"),
+ (0xFF14, "M", "4"),
+ (0xFF15, "M", "5"),
+ (0xFF16, "M", "6"),
+ (0xFF17, "M", "7"),
+ (0xFF18, "M", "8"),
+ (0xFF19, "M", "9"),
+ (0xFF1A, "3", ":"),
+ (0xFF1B, "3", ";"),
+ (0xFF1C, "3", "<"),
+ (0xFF1D, "3", "="),
+ (0xFF1E, "3", ">"),
+ ]
+
+
+def _seg_51() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFF1F, "3", "?"),
+ (0xFF20, "3", "@"),
+ (0xFF21, "M", "a"),
+ (0xFF22, "M", "b"),
+ (0xFF23, "M", "c"),
+ (0xFF24, "M", "d"),
+ (0xFF25, "M", "e"),
+ (0xFF26, "M", "f"),
+ (0xFF27, "M", "g"),
+ (0xFF28, "M", "h"),
+ (0xFF29, "M", "i"),
+ (0xFF2A, "M", "j"),
+ (0xFF2B, "M", "k"),
+ (0xFF2C, "M", "l"),
+ (0xFF2D, "M", "m"),
+ (0xFF2E, "M", "n"),
+ (0xFF2F, "M", "o"),
+ (0xFF30, "M", "p"),
+ (0xFF31, "M", "q"),
+ (0xFF32, "M", "r"),
+ (0xFF33, "M", "s"),
+ (0xFF34, "M", "t"),
+ (0xFF35, "M", "u"),
+ (0xFF36, "M", "v"),
+ (0xFF37, "M", "w"),
+ (0xFF38, "M", "x"),
+ (0xFF39, "M", "y"),
+ (0xFF3A, "M", "z"),
+ (0xFF3B, "3", "["),
+ (0xFF3C, "3", "\\"),
+ (0xFF3D, "3", "]"),
+ (0xFF3E, "3", "^"),
+ (0xFF3F, "3", "_"),
+ (0xFF40, "3", "`"),
+ (0xFF41, "M", "a"),
+ (0xFF42, "M", "b"),
+ (0xFF43, "M", "c"),
+ (0xFF44, "M", "d"),
+ (0xFF45, "M", "e"),
+ (0xFF46, "M", "f"),
+ (0xFF47, "M", "g"),
+ (0xFF48, "M", "h"),
+ (0xFF49, "M", "i"),
+ (0xFF4A, "M", "j"),
+ (0xFF4B, "M", "k"),
+ (0xFF4C, "M", "l"),
+ (0xFF4D, "M", "m"),
+ (0xFF4E, "M", "n"),
+ (0xFF4F, "M", "o"),
+ (0xFF50, "M", "p"),
+ (0xFF51, "M", "q"),
+ (0xFF52, "M", "r"),
+ (0xFF53, "M", "s"),
+ (0xFF54, "M", "t"),
+ (0xFF55, "M", "u"),
+ (0xFF56, "M", "v"),
+ (0xFF57, "M", "w"),
+ (0xFF58, "M", "x"),
+ (0xFF59, "M", "y"),
+ (0xFF5A, "M", "z"),
+ (0xFF5B, "3", "{"),
+ (0xFF5C, "3", "|"),
+ (0xFF5D, "3", "}"),
+ (0xFF5E, "3", "~"),
+ (0xFF5F, "M", "⦅"),
+ (0xFF60, "M", "⦆"),
+ (0xFF61, "M", "."),
+ (0xFF62, "M", "「"),
+ (0xFF63, "M", "」"),
+ (0xFF64, "M", "、"),
+ (0xFF65, "M", "・"),
+ (0xFF66, "M", "ヲ"),
+ (0xFF67, "M", "ァ"),
+ (0xFF68, "M", "ィ"),
+ (0xFF69, "M", "ゥ"),
+ (0xFF6A, "M", "ェ"),
+ (0xFF6B, "M", "ォ"),
+ (0xFF6C, "M", "ャ"),
+ (0xFF6D, "M", "ュ"),
+ (0xFF6E, "M", "ョ"),
+ (0xFF6F, "M", "ッ"),
+ (0xFF70, "M", "ー"),
+ (0xFF71, "M", "ア"),
+ (0xFF72, "M", "イ"),
+ (0xFF73, "M", "ウ"),
+ (0xFF74, "M", "エ"),
+ (0xFF75, "M", "オ"),
+ (0xFF76, "M", "カ"),
+ (0xFF77, "M", "キ"),
+ (0xFF78, "M", "ク"),
+ (0xFF79, "M", "ケ"),
+ (0xFF7A, "M", "コ"),
+ (0xFF7B, "M", "サ"),
+ (0xFF7C, "M", "シ"),
+ (0xFF7D, "M", "ス"),
+ (0xFF7E, "M", "セ"),
+ (0xFF7F, "M", "ソ"),
+ (0xFF80, "M", "タ"),
+ (0xFF81, "M", "チ"),
+ (0xFF82, "M", "ツ"),
+ ]
+
+
+def _seg_52() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFF83, "M", "テ"),
+ (0xFF84, "M", "ト"),
+ (0xFF85, "M", "ナ"),
+ (0xFF86, "M", "ニ"),
+ (0xFF87, "M", "ヌ"),
+ (0xFF88, "M", "ネ"),
+ (0xFF89, "M", "ノ"),
+ (0xFF8A, "M", "ハ"),
+ (0xFF8B, "M", "ヒ"),
+ (0xFF8C, "M", "フ"),
+ (0xFF8D, "M", "ヘ"),
+ (0xFF8E, "M", "ホ"),
+ (0xFF8F, "M", "マ"),
+ (0xFF90, "M", "ミ"),
+ (0xFF91, "M", "ム"),
+ (0xFF92, "M", "メ"),
+ (0xFF93, "M", "モ"),
+ (0xFF94, "M", "ヤ"),
+ (0xFF95, "M", "ユ"),
+ (0xFF96, "M", "ヨ"),
+ (0xFF97, "M", "ラ"),
+ (0xFF98, "M", "リ"),
+ (0xFF99, "M", "ル"),
+ (0xFF9A, "M", "レ"),
+ (0xFF9B, "M", "ロ"),
+ (0xFF9C, "M", "ワ"),
+ (0xFF9D, "M", "ン"),
+ (0xFF9E, "M", "゙"),
+ (0xFF9F, "M", "゚"),
+ (0xFFA0, "X"),
+ (0xFFA1, "M", "ᄀ"),
+ (0xFFA2, "M", "ᄁ"),
+ (0xFFA3, "M", "ᆪ"),
+ (0xFFA4, "M", "ᄂ"),
+ (0xFFA5, "M", "ᆬ"),
+ (0xFFA6, "M", "ᆭ"),
+ (0xFFA7, "M", "ᄃ"),
+ (0xFFA8, "M", "ᄄ"),
+ (0xFFA9, "M", "ᄅ"),
+ (0xFFAA, "M", "ᆰ"),
+ (0xFFAB, "M", "ᆱ"),
+ (0xFFAC, "M", "ᆲ"),
+ (0xFFAD, "M", "ᆳ"),
+ (0xFFAE, "M", "ᆴ"),
+ (0xFFAF, "M", "ᆵ"),
+ (0xFFB0, "M", "ᄚ"),
+ (0xFFB1, "M", "ᄆ"),
+ (0xFFB2, "M", "ᄇ"),
+ (0xFFB3, "M", "ᄈ"),
+ (0xFFB4, "M", "ᄡ"),
+ (0xFFB5, "M", "ᄉ"),
+ (0xFFB6, "M", "ᄊ"),
+ (0xFFB7, "M", "ᄋ"),
+ (0xFFB8, "M", "ᄌ"),
+ (0xFFB9, "M", "ᄍ"),
+ (0xFFBA, "M", "ᄎ"),
+ (0xFFBB, "M", "ᄏ"),
+ (0xFFBC, "M", "ᄐ"),
+ (0xFFBD, "M", "ᄑ"),
+ (0xFFBE, "M", "ᄒ"),
+ (0xFFBF, "X"),
+ (0xFFC2, "M", "ᅡ"),
+ (0xFFC3, "M", "ᅢ"),
+ (0xFFC4, "M", "ᅣ"),
+ (0xFFC5, "M", "ᅤ"),
+ (0xFFC6, "M", "ᅥ"),
+ (0xFFC7, "M", "ᅦ"),
+ (0xFFC8, "X"),
+ (0xFFCA, "M", "ᅧ"),
+ (0xFFCB, "M", "ᅨ"),
+ (0xFFCC, "M", "ᅩ"),
+ (0xFFCD, "M", "ᅪ"),
+ (0xFFCE, "M", "ᅫ"),
+ (0xFFCF, "M", "ᅬ"),
+ (0xFFD0, "X"),
+ (0xFFD2, "M", "ᅭ"),
+ (0xFFD3, "M", "ᅮ"),
+ (0xFFD4, "M", "ᅯ"),
+ (0xFFD5, "M", "ᅰ"),
+ (0xFFD6, "M", "ᅱ"),
+ (0xFFD7, "M", "ᅲ"),
+ (0xFFD8, "X"),
+ (0xFFDA, "M", "ᅳ"),
+ (0xFFDB, "M", "ᅴ"),
+ (0xFFDC, "M", "ᅵ"),
+ (0xFFDD, "X"),
+ (0xFFE0, "M", "¢"),
+ (0xFFE1, "M", "£"),
+ (0xFFE2, "M", "¬"),
+ (0xFFE3, "3", " ̄"),
+ (0xFFE4, "M", "¦"),
+ (0xFFE5, "M", "¥"),
+ (0xFFE6, "M", "₩"),
+ (0xFFE7, "X"),
+ (0xFFE8, "M", "│"),
+ (0xFFE9, "M", "←"),
+ (0xFFEA, "M", "↑"),
+ (0xFFEB, "M", "→"),
+ (0xFFEC, "M", "↓"),
+ (0xFFED, "M", "■"),
+ ]
+
+
+def _seg_53() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0xFFEE, "M", "○"),
+ (0xFFEF, "X"),
+ (0x10000, "V"),
+ (0x1000C, "X"),
+ (0x1000D, "V"),
+ (0x10027, "X"),
+ (0x10028, "V"),
+ (0x1003B, "X"),
+ (0x1003C, "V"),
+ (0x1003E, "X"),
+ (0x1003F, "V"),
+ (0x1004E, "X"),
+ (0x10050, "V"),
+ (0x1005E, "X"),
+ (0x10080, "V"),
+ (0x100FB, "X"),
+ (0x10100, "V"),
+ (0x10103, "X"),
+ (0x10107, "V"),
+ (0x10134, "X"),
+ (0x10137, "V"),
+ (0x1018F, "X"),
+ (0x10190, "V"),
+ (0x1019D, "X"),
+ (0x101A0, "V"),
+ (0x101A1, "X"),
+ (0x101D0, "V"),
+ (0x101FE, "X"),
+ (0x10280, "V"),
+ (0x1029D, "X"),
+ (0x102A0, "V"),
+ (0x102D1, "X"),
+ (0x102E0, "V"),
+ (0x102FC, "X"),
+ (0x10300, "V"),
+ (0x10324, "X"),
+ (0x1032D, "V"),
+ (0x1034B, "X"),
+ (0x10350, "V"),
+ (0x1037B, "X"),
+ (0x10380, "V"),
+ (0x1039E, "X"),
+ (0x1039F, "V"),
+ (0x103C4, "X"),
+ (0x103C8, "V"),
+ (0x103D6, "X"),
+ (0x10400, "M", "𐐨"),
+ (0x10401, "M", "𐐩"),
+ (0x10402, "M", "𐐪"),
+ (0x10403, "M", "𐐫"),
+ (0x10404, "M", "𐐬"),
+ (0x10405, "M", "𐐭"),
+ (0x10406, "M", "𐐮"),
+ (0x10407, "M", "𐐯"),
+ (0x10408, "M", "𐐰"),
+ (0x10409, "M", "𐐱"),
+ (0x1040A, "M", "𐐲"),
+ (0x1040B, "M", "𐐳"),
+ (0x1040C, "M", "𐐴"),
+ (0x1040D, "M", "𐐵"),
+ (0x1040E, "M", "𐐶"),
+ (0x1040F, "M", "𐐷"),
+ (0x10410, "M", "𐐸"),
+ (0x10411, "M", "𐐹"),
+ (0x10412, "M", "𐐺"),
+ (0x10413, "M", "𐐻"),
+ (0x10414, "M", "𐐼"),
+ (0x10415, "M", "𐐽"),
+ (0x10416, "M", "𐐾"),
+ (0x10417, "M", "𐐿"),
+ (0x10418, "M", "𐑀"),
+ (0x10419, "M", "𐑁"),
+ (0x1041A, "M", "𐑂"),
+ (0x1041B, "M", "𐑃"),
+ (0x1041C, "M", "𐑄"),
+ (0x1041D, "M", "𐑅"),
+ (0x1041E, "M", "𐑆"),
+ (0x1041F, "M", "𐑇"),
+ (0x10420, "M", "𐑈"),
+ (0x10421, "M", "𐑉"),
+ (0x10422, "M", "𐑊"),
+ (0x10423, "M", "𐑋"),
+ (0x10424, "M", "𐑌"),
+ (0x10425, "M", "𐑍"),
+ (0x10426, "M", "𐑎"),
+ (0x10427, "M", "𐑏"),
+ (0x10428, "V"),
+ (0x1049E, "X"),
+ (0x104A0, "V"),
+ (0x104AA, "X"),
+ (0x104B0, "M", "𐓘"),
+ (0x104B1, "M", "𐓙"),
+ (0x104B2, "M", "𐓚"),
+ (0x104B3, "M", "𐓛"),
+ (0x104B4, "M", "𐓜"),
+ (0x104B5, "M", "𐓝"),
+ (0x104B6, "M", "𐓞"),
+ (0x104B7, "M", "𐓟"),
+ (0x104B8, "M", "𐓠"),
+ (0x104B9, "M", "𐓡"),
+ ]
+
+
+def _seg_54() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x104BA, "M", "𐓢"),
+ (0x104BB, "M", "𐓣"),
+ (0x104BC, "M", "𐓤"),
+ (0x104BD, "M", "𐓥"),
+ (0x104BE, "M", "𐓦"),
+ (0x104BF, "M", "𐓧"),
+ (0x104C0, "M", "𐓨"),
+ (0x104C1, "M", "𐓩"),
+ (0x104C2, "M", "𐓪"),
+ (0x104C3, "M", "𐓫"),
+ (0x104C4, "M", "𐓬"),
+ (0x104C5, "M", "𐓭"),
+ (0x104C6, "M", "𐓮"),
+ (0x104C7, "M", "𐓯"),
+ (0x104C8, "M", "𐓰"),
+ (0x104C9, "M", "𐓱"),
+ (0x104CA, "M", "𐓲"),
+ (0x104CB, "M", "𐓳"),
+ (0x104CC, "M", "𐓴"),
+ (0x104CD, "M", "𐓵"),
+ (0x104CE, "M", "𐓶"),
+ (0x104CF, "M", "𐓷"),
+ (0x104D0, "M", "𐓸"),
+ (0x104D1, "M", "𐓹"),
+ (0x104D2, "M", "𐓺"),
+ (0x104D3, "M", "𐓻"),
+ (0x104D4, "X"),
+ (0x104D8, "V"),
+ (0x104FC, "X"),
+ (0x10500, "V"),
+ (0x10528, "X"),
+ (0x10530, "V"),
+ (0x10564, "X"),
+ (0x1056F, "V"),
+ (0x10570, "M", "𐖗"),
+ (0x10571, "M", "𐖘"),
+ (0x10572, "M", "𐖙"),
+ (0x10573, "M", "𐖚"),
+ (0x10574, "M", "𐖛"),
+ (0x10575, "M", "𐖜"),
+ (0x10576, "M", "𐖝"),
+ (0x10577, "M", "𐖞"),
+ (0x10578, "M", "𐖟"),
+ (0x10579, "M", "𐖠"),
+ (0x1057A, "M", "𐖡"),
+ (0x1057B, "X"),
+ (0x1057C, "M", "𐖣"),
+ (0x1057D, "M", "𐖤"),
+ (0x1057E, "M", "𐖥"),
+ (0x1057F, "M", "𐖦"),
+ (0x10580, "M", "𐖧"),
+ (0x10581, "M", "𐖨"),
+ (0x10582, "M", "𐖩"),
+ (0x10583, "M", "𐖪"),
+ (0x10584, "M", "𐖫"),
+ (0x10585, "M", "𐖬"),
+ (0x10586, "M", "𐖭"),
+ (0x10587, "M", "𐖮"),
+ (0x10588, "M", "𐖯"),
+ (0x10589, "M", "𐖰"),
+ (0x1058A, "M", "𐖱"),
+ (0x1058B, "X"),
+ (0x1058C, "M", "𐖳"),
+ (0x1058D, "M", "𐖴"),
+ (0x1058E, "M", "𐖵"),
+ (0x1058F, "M", "𐖶"),
+ (0x10590, "M", "𐖷"),
+ (0x10591, "M", "𐖸"),
+ (0x10592, "M", "𐖹"),
+ (0x10593, "X"),
+ (0x10594, "M", "𐖻"),
+ (0x10595, "M", "𐖼"),
+ (0x10596, "X"),
+ (0x10597, "V"),
+ (0x105A2, "X"),
+ (0x105A3, "V"),
+ (0x105B2, "X"),
+ (0x105B3, "V"),
+ (0x105BA, "X"),
+ (0x105BB, "V"),
+ (0x105BD, "X"),
+ (0x10600, "V"),
+ (0x10737, "X"),
+ (0x10740, "V"),
+ (0x10756, "X"),
+ (0x10760, "V"),
+ (0x10768, "X"),
+ (0x10780, "V"),
+ (0x10781, "M", "ː"),
+ (0x10782, "M", "ˑ"),
+ (0x10783, "M", "æ"),
+ (0x10784, "M", "ʙ"),
+ (0x10785, "M", "ɓ"),
+ (0x10786, "X"),
+ (0x10787, "M", "ʣ"),
+ (0x10788, "M", "ꭦ"),
+ (0x10789, "M", "ʥ"),
+ (0x1078A, "M", "ʤ"),
+ (0x1078B, "M", "ɖ"),
+ (0x1078C, "M", "ɗ"),
+ ]
+
+
+def _seg_55() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1078D, "M", "ᶑ"),
+ (0x1078E, "M", "ɘ"),
+ (0x1078F, "M", "ɞ"),
+ (0x10790, "M", "ʩ"),
+ (0x10791, "M", "ɤ"),
+ (0x10792, "M", "ɢ"),
+ (0x10793, "M", "ɠ"),
+ (0x10794, "M", "ʛ"),
+ (0x10795, "M", "ħ"),
+ (0x10796, "M", "ʜ"),
+ (0x10797, "M", "ɧ"),
+ (0x10798, "M", "ʄ"),
+ (0x10799, "M", "ʪ"),
+ (0x1079A, "M", "ʫ"),
+ (0x1079B, "M", "ɬ"),
+ (0x1079C, "M", "𝼄"),
+ (0x1079D, "M", "ꞎ"),
+ (0x1079E, "M", "ɮ"),
+ (0x1079F, "M", "𝼅"),
+ (0x107A0, "M", "ʎ"),
+ (0x107A1, "M", "𝼆"),
+ (0x107A2, "M", "ø"),
+ (0x107A3, "M", "ɶ"),
+ (0x107A4, "M", "ɷ"),
+ (0x107A5, "M", "q"),
+ (0x107A6, "M", "ɺ"),
+ (0x107A7, "M", "𝼈"),
+ (0x107A8, "M", "ɽ"),
+ (0x107A9, "M", "ɾ"),
+ (0x107AA, "M", "ʀ"),
+ (0x107AB, "M", "ʨ"),
+ (0x107AC, "M", "ʦ"),
+ (0x107AD, "M", "ꭧ"),
+ (0x107AE, "M", "ʧ"),
+ (0x107AF, "M", "ʈ"),
+ (0x107B0, "M", "ⱱ"),
+ (0x107B1, "X"),
+ (0x107B2, "M", "ʏ"),
+ (0x107B3, "M", "ʡ"),
+ (0x107B4, "M", "ʢ"),
+ (0x107B5, "M", "ʘ"),
+ (0x107B6, "M", "ǀ"),
+ (0x107B7, "M", "ǁ"),
+ (0x107B8, "M", "ǂ"),
+ (0x107B9, "M", "𝼊"),
+ (0x107BA, "M", "𝼞"),
+ (0x107BB, "X"),
+ (0x10800, "V"),
+ (0x10806, "X"),
+ (0x10808, "V"),
+ (0x10809, "X"),
+ (0x1080A, "V"),
+ (0x10836, "X"),
+ (0x10837, "V"),
+ (0x10839, "X"),
+ (0x1083C, "V"),
+ (0x1083D, "X"),
+ (0x1083F, "V"),
+ (0x10856, "X"),
+ (0x10857, "V"),
+ (0x1089F, "X"),
+ (0x108A7, "V"),
+ (0x108B0, "X"),
+ (0x108E0, "V"),
+ (0x108F3, "X"),
+ (0x108F4, "V"),
+ (0x108F6, "X"),
+ (0x108FB, "V"),
+ (0x1091C, "X"),
+ (0x1091F, "V"),
+ (0x1093A, "X"),
+ (0x1093F, "V"),
+ (0x10940, "X"),
+ (0x10980, "V"),
+ (0x109B8, "X"),
+ (0x109BC, "V"),
+ (0x109D0, "X"),
+ (0x109D2, "V"),
+ (0x10A04, "X"),
+ (0x10A05, "V"),
+ (0x10A07, "X"),
+ (0x10A0C, "V"),
+ (0x10A14, "X"),
+ (0x10A15, "V"),
+ (0x10A18, "X"),
+ (0x10A19, "V"),
+ (0x10A36, "X"),
+ (0x10A38, "V"),
+ (0x10A3B, "X"),
+ (0x10A3F, "V"),
+ (0x10A49, "X"),
+ (0x10A50, "V"),
+ (0x10A59, "X"),
+ (0x10A60, "V"),
+ (0x10AA0, "X"),
+ (0x10AC0, "V"),
+ (0x10AE7, "X"),
+ (0x10AEB, "V"),
+ (0x10AF7, "X"),
+ (0x10B00, "V"),
+ ]
+
+
+def _seg_56() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x10B36, "X"),
+ (0x10B39, "V"),
+ (0x10B56, "X"),
+ (0x10B58, "V"),
+ (0x10B73, "X"),
+ (0x10B78, "V"),
+ (0x10B92, "X"),
+ (0x10B99, "V"),
+ (0x10B9D, "X"),
+ (0x10BA9, "V"),
+ (0x10BB0, "X"),
+ (0x10C00, "V"),
+ (0x10C49, "X"),
+ (0x10C80, "M", "𐳀"),
+ (0x10C81, "M", "𐳁"),
+ (0x10C82, "M", "𐳂"),
+ (0x10C83, "M", "𐳃"),
+ (0x10C84, "M", "𐳄"),
+ (0x10C85, "M", "𐳅"),
+ (0x10C86, "M", "𐳆"),
+ (0x10C87, "M", "𐳇"),
+ (0x10C88, "M", "𐳈"),
+ (0x10C89, "M", "𐳉"),
+ (0x10C8A, "M", "𐳊"),
+ (0x10C8B, "M", "𐳋"),
+ (0x10C8C, "M", "𐳌"),
+ (0x10C8D, "M", "𐳍"),
+ (0x10C8E, "M", "𐳎"),
+ (0x10C8F, "M", "𐳏"),
+ (0x10C90, "M", "𐳐"),
+ (0x10C91, "M", "𐳑"),
+ (0x10C92, "M", "𐳒"),
+ (0x10C93, "M", "𐳓"),
+ (0x10C94, "M", "𐳔"),
+ (0x10C95, "M", "𐳕"),
+ (0x10C96, "M", "𐳖"),
+ (0x10C97, "M", "𐳗"),
+ (0x10C98, "M", "𐳘"),
+ (0x10C99, "M", "𐳙"),
+ (0x10C9A, "M", "𐳚"),
+ (0x10C9B, "M", "𐳛"),
+ (0x10C9C, "M", "𐳜"),
+ (0x10C9D, "M", "𐳝"),
+ (0x10C9E, "M", "𐳞"),
+ (0x10C9F, "M", "𐳟"),
+ (0x10CA0, "M", "𐳠"),
+ (0x10CA1, "M", "𐳡"),
+ (0x10CA2, "M", "𐳢"),
+ (0x10CA3, "M", "𐳣"),
+ (0x10CA4, "M", "𐳤"),
+ (0x10CA5, "M", "𐳥"),
+ (0x10CA6, "M", "𐳦"),
+ (0x10CA7, "M", "𐳧"),
+ (0x10CA8, "M", "𐳨"),
+ (0x10CA9, "M", "𐳩"),
+ (0x10CAA, "M", "𐳪"),
+ (0x10CAB, "M", "𐳫"),
+ (0x10CAC, "M", "𐳬"),
+ (0x10CAD, "M", "𐳭"),
+ (0x10CAE, "M", "𐳮"),
+ (0x10CAF, "M", "𐳯"),
+ (0x10CB0, "M", "𐳰"),
+ (0x10CB1, "M", "𐳱"),
+ (0x10CB2, "M", "𐳲"),
+ (0x10CB3, "X"),
+ (0x10CC0, "V"),
+ (0x10CF3, "X"),
+ (0x10CFA, "V"),
+ (0x10D28, "X"),
+ (0x10D30, "V"),
+ (0x10D3A, "X"),
+ (0x10E60, "V"),
+ (0x10E7F, "X"),
+ (0x10E80, "V"),
+ (0x10EAA, "X"),
+ (0x10EAB, "V"),
+ (0x10EAE, "X"),
+ (0x10EB0, "V"),
+ (0x10EB2, "X"),
+ (0x10EFD, "V"),
+ (0x10F28, "X"),
+ (0x10F30, "V"),
+ (0x10F5A, "X"),
+ (0x10F70, "V"),
+ (0x10F8A, "X"),
+ (0x10FB0, "V"),
+ (0x10FCC, "X"),
+ (0x10FE0, "V"),
+ (0x10FF7, "X"),
+ (0x11000, "V"),
+ (0x1104E, "X"),
+ (0x11052, "V"),
+ (0x11076, "X"),
+ (0x1107F, "V"),
+ (0x110BD, "X"),
+ (0x110BE, "V"),
+ (0x110C3, "X"),
+ (0x110D0, "V"),
+ (0x110E9, "X"),
+ (0x110F0, "V"),
+ ]
+
+
+def _seg_57() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x110FA, "X"),
+ (0x11100, "V"),
+ (0x11135, "X"),
+ (0x11136, "V"),
+ (0x11148, "X"),
+ (0x11150, "V"),
+ (0x11177, "X"),
+ (0x11180, "V"),
+ (0x111E0, "X"),
+ (0x111E1, "V"),
+ (0x111F5, "X"),
+ (0x11200, "V"),
+ (0x11212, "X"),
+ (0x11213, "V"),
+ (0x11242, "X"),
+ (0x11280, "V"),
+ (0x11287, "X"),
+ (0x11288, "V"),
+ (0x11289, "X"),
+ (0x1128A, "V"),
+ (0x1128E, "X"),
+ (0x1128F, "V"),
+ (0x1129E, "X"),
+ (0x1129F, "V"),
+ (0x112AA, "X"),
+ (0x112B0, "V"),
+ (0x112EB, "X"),
+ (0x112F0, "V"),
+ (0x112FA, "X"),
+ (0x11300, "V"),
+ (0x11304, "X"),
+ (0x11305, "V"),
+ (0x1130D, "X"),
+ (0x1130F, "V"),
+ (0x11311, "X"),
+ (0x11313, "V"),
+ (0x11329, "X"),
+ (0x1132A, "V"),
+ (0x11331, "X"),
+ (0x11332, "V"),
+ (0x11334, "X"),
+ (0x11335, "V"),
+ (0x1133A, "X"),
+ (0x1133B, "V"),
+ (0x11345, "X"),
+ (0x11347, "V"),
+ (0x11349, "X"),
+ (0x1134B, "V"),
+ (0x1134E, "X"),
+ (0x11350, "V"),
+ (0x11351, "X"),
+ (0x11357, "V"),
+ (0x11358, "X"),
+ (0x1135D, "V"),
+ (0x11364, "X"),
+ (0x11366, "V"),
+ (0x1136D, "X"),
+ (0x11370, "V"),
+ (0x11375, "X"),
+ (0x11400, "V"),
+ (0x1145C, "X"),
+ (0x1145D, "V"),
+ (0x11462, "X"),
+ (0x11480, "V"),
+ (0x114C8, "X"),
+ (0x114D0, "V"),
+ (0x114DA, "X"),
+ (0x11580, "V"),
+ (0x115B6, "X"),
+ (0x115B8, "V"),
+ (0x115DE, "X"),
+ (0x11600, "V"),
+ (0x11645, "X"),
+ (0x11650, "V"),
+ (0x1165A, "X"),
+ (0x11660, "V"),
+ (0x1166D, "X"),
+ (0x11680, "V"),
+ (0x116BA, "X"),
+ (0x116C0, "V"),
+ (0x116CA, "X"),
+ (0x11700, "V"),
+ (0x1171B, "X"),
+ (0x1171D, "V"),
+ (0x1172C, "X"),
+ (0x11730, "V"),
+ (0x11747, "X"),
+ (0x11800, "V"),
+ (0x1183C, "X"),
+ (0x118A0, "M", "𑣀"),
+ (0x118A1, "M", "𑣁"),
+ (0x118A2, "M", "𑣂"),
+ (0x118A3, "M", "𑣃"),
+ (0x118A4, "M", "𑣄"),
+ (0x118A5, "M", "𑣅"),
+ (0x118A6, "M", "𑣆"),
+ (0x118A7, "M", "𑣇"),
+ (0x118A8, "M", "𑣈"),
+ (0x118A9, "M", "𑣉"),
+ (0x118AA, "M", "𑣊"),
+ ]
+
+
+def _seg_58() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x118AB, "M", "𑣋"),
+ (0x118AC, "M", "𑣌"),
+ (0x118AD, "M", "𑣍"),
+ (0x118AE, "M", "𑣎"),
+ (0x118AF, "M", "𑣏"),
+ (0x118B0, "M", "𑣐"),
+ (0x118B1, "M", "𑣑"),
+ (0x118B2, "M", "𑣒"),
+ (0x118B3, "M", "𑣓"),
+ (0x118B4, "M", "𑣔"),
+ (0x118B5, "M", "𑣕"),
+ (0x118B6, "M", "𑣖"),
+ (0x118B7, "M", "𑣗"),
+ (0x118B8, "M", "𑣘"),
+ (0x118B9, "M", "𑣙"),
+ (0x118BA, "M", "𑣚"),
+ (0x118BB, "M", "𑣛"),
+ (0x118BC, "M", "𑣜"),
+ (0x118BD, "M", "𑣝"),
+ (0x118BE, "M", "𑣞"),
+ (0x118BF, "M", "𑣟"),
+ (0x118C0, "V"),
+ (0x118F3, "X"),
+ (0x118FF, "V"),
+ (0x11907, "X"),
+ (0x11909, "V"),
+ (0x1190A, "X"),
+ (0x1190C, "V"),
+ (0x11914, "X"),
+ (0x11915, "V"),
+ (0x11917, "X"),
+ (0x11918, "V"),
+ (0x11936, "X"),
+ (0x11937, "V"),
+ (0x11939, "X"),
+ (0x1193B, "V"),
+ (0x11947, "X"),
+ (0x11950, "V"),
+ (0x1195A, "X"),
+ (0x119A0, "V"),
+ (0x119A8, "X"),
+ (0x119AA, "V"),
+ (0x119D8, "X"),
+ (0x119DA, "V"),
+ (0x119E5, "X"),
+ (0x11A00, "V"),
+ (0x11A48, "X"),
+ (0x11A50, "V"),
+ (0x11AA3, "X"),
+ (0x11AB0, "V"),
+ (0x11AF9, "X"),
+ (0x11B00, "V"),
+ (0x11B0A, "X"),
+ (0x11C00, "V"),
+ (0x11C09, "X"),
+ (0x11C0A, "V"),
+ (0x11C37, "X"),
+ (0x11C38, "V"),
+ (0x11C46, "X"),
+ (0x11C50, "V"),
+ (0x11C6D, "X"),
+ (0x11C70, "V"),
+ (0x11C90, "X"),
+ (0x11C92, "V"),
+ (0x11CA8, "X"),
+ (0x11CA9, "V"),
+ (0x11CB7, "X"),
+ (0x11D00, "V"),
+ (0x11D07, "X"),
+ (0x11D08, "V"),
+ (0x11D0A, "X"),
+ (0x11D0B, "V"),
+ (0x11D37, "X"),
+ (0x11D3A, "V"),
+ (0x11D3B, "X"),
+ (0x11D3C, "V"),
+ (0x11D3E, "X"),
+ (0x11D3F, "V"),
+ (0x11D48, "X"),
+ (0x11D50, "V"),
+ (0x11D5A, "X"),
+ (0x11D60, "V"),
+ (0x11D66, "X"),
+ (0x11D67, "V"),
+ (0x11D69, "X"),
+ (0x11D6A, "V"),
+ (0x11D8F, "X"),
+ (0x11D90, "V"),
+ (0x11D92, "X"),
+ (0x11D93, "V"),
+ (0x11D99, "X"),
+ (0x11DA0, "V"),
+ (0x11DAA, "X"),
+ (0x11EE0, "V"),
+ (0x11EF9, "X"),
+ (0x11F00, "V"),
+ (0x11F11, "X"),
+ (0x11F12, "V"),
+ (0x11F3B, "X"),
+ (0x11F3E, "V"),
+ ]
+
+
+def _seg_59() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x11F5A, "X"),
+ (0x11FB0, "V"),
+ (0x11FB1, "X"),
+ (0x11FC0, "V"),
+ (0x11FF2, "X"),
+ (0x11FFF, "V"),
+ (0x1239A, "X"),
+ (0x12400, "V"),
+ (0x1246F, "X"),
+ (0x12470, "V"),
+ (0x12475, "X"),
+ (0x12480, "V"),
+ (0x12544, "X"),
+ (0x12F90, "V"),
+ (0x12FF3, "X"),
+ (0x13000, "V"),
+ (0x13430, "X"),
+ (0x13440, "V"),
+ (0x13456, "X"),
+ (0x14400, "V"),
+ (0x14647, "X"),
+ (0x16800, "V"),
+ (0x16A39, "X"),
+ (0x16A40, "V"),
+ (0x16A5F, "X"),
+ (0x16A60, "V"),
+ (0x16A6A, "X"),
+ (0x16A6E, "V"),
+ (0x16ABF, "X"),
+ (0x16AC0, "V"),
+ (0x16ACA, "X"),
+ (0x16AD0, "V"),
+ (0x16AEE, "X"),
+ (0x16AF0, "V"),
+ (0x16AF6, "X"),
+ (0x16B00, "V"),
+ (0x16B46, "X"),
+ (0x16B50, "V"),
+ (0x16B5A, "X"),
+ (0x16B5B, "V"),
+ (0x16B62, "X"),
+ (0x16B63, "V"),
+ (0x16B78, "X"),
+ (0x16B7D, "V"),
+ (0x16B90, "X"),
+ (0x16E40, "M", "𖹠"),
+ (0x16E41, "M", "𖹡"),
+ (0x16E42, "M", "𖹢"),
+ (0x16E43, "M", "𖹣"),
+ (0x16E44, "M", "𖹤"),
+ (0x16E45, "M", "𖹥"),
+ (0x16E46, "M", "𖹦"),
+ (0x16E47, "M", "𖹧"),
+ (0x16E48, "M", "𖹨"),
+ (0x16E49, "M", "𖹩"),
+ (0x16E4A, "M", "𖹪"),
+ (0x16E4B, "M", "𖹫"),
+ (0x16E4C, "M", "𖹬"),
+ (0x16E4D, "M", "𖹭"),
+ (0x16E4E, "M", "𖹮"),
+ (0x16E4F, "M", "𖹯"),
+ (0x16E50, "M", "𖹰"),
+ (0x16E51, "M", "𖹱"),
+ (0x16E52, "M", "𖹲"),
+ (0x16E53, "M", "𖹳"),
+ (0x16E54, "M", "𖹴"),
+ (0x16E55, "M", "𖹵"),
+ (0x16E56, "M", "𖹶"),
+ (0x16E57, "M", "𖹷"),
+ (0x16E58, "M", "𖹸"),
+ (0x16E59, "M", "𖹹"),
+ (0x16E5A, "M", "𖹺"),
+ (0x16E5B, "M", "𖹻"),
+ (0x16E5C, "M", "𖹼"),
+ (0x16E5D, "M", "𖹽"),
+ (0x16E5E, "M", "𖹾"),
+ (0x16E5F, "M", "𖹿"),
+ (0x16E60, "V"),
+ (0x16E9B, "X"),
+ (0x16F00, "V"),
+ (0x16F4B, "X"),
+ (0x16F4F, "V"),
+ (0x16F88, "X"),
+ (0x16F8F, "V"),
+ (0x16FA0, "X"),
+ (0x16FE0, "V"),
+ (0x16FE5, "X"),
+ (0x16FF0, "V"),
+ (0x16FF2, "X"),
+ (0x17000, "V"),
+ (0x187F8, "X"),
+ (0x18800, "V"),
+ (0x18CD6, "X"),
+ (0x18D00, "V"),
+ (0x18D09, "X"),
+ (0x1AFF0, "V"),
+ (0x1AFF4, "X"),
+ (0x1AFF5, "V"),
+ (0x1AFFC, "X"),
+ (0x1AFFD, "V"),
+ ]
+
+
+def _seg_60() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1AFFF, "X"),
+ (0x1B000, "V"),
+ (0x1B123, "X"),
+ (0x1B132, "V"),
+ (0x1B133, "X"),
+ (0x1B150, "V"),
+ (0x1B153, "X"),
+ (0x1B155, "V"),
+ (0x1B156, "X"),
+ (0x1B164, "V"),
+ (0x1B168, "X"),
+ (0x1B170, "V"),
+ (0x1B2FC, "X"),
+ (0x1BC00, "V"),
+ (0x1BC6B, "X"),
+ (0x1BC70, "V"),
+ (0x1BC7D, "X"),
+ (0x1BC80, "V"),
+ (0x1BC89, "X"),
+ (0x1BC90, "V"),
+ (0x1BC9A, "X"),
+ (0x1BC9C, "V"),
+ (0x1BCA0, "I"),
+ (0x1BCA4, "X"),
+ (0x1CF00, "V"),
+ (0x1CF2E, "X"),
+ (0x1CF30, "V"),
+ (0x1CF47, "X"),
+ (0x1CF50, "V"),
+ (0x1CFC4, "X"),
+ (0x1D000, "V"),
+ (0x1D0F6, "X"),
+ (0x1D100, "V"),
+ (0x1D127, "X"),
+ (0x1D129, "V"),
+ (0x1D15E, "M", "𝅗𝅥"),
+ (0x1D15F, "M", "𝅘𝅥"),
+ (0x1D160, "M", "𝅘𝅥𝅮"),
+ (0x1D161, "M", "𝅘𝅥𝅯"),
+ (0x1D162, "M", "𝅘𝅥𝅰"),
+ (0x1D163, "M", "𝅘𝅥𝅱"),
+ (0x1D164, "M", "𝅘𝅥𝅲"),
+ (0x1D165, "V"),
+ (0x1D173, "X"),
+ (0x1D17B, "V"),
+ (0x1D1BB, "M", "𝆹𝅥"),
+ (0x1D1BC, "M", "𝆺𝅥"),
+ (0x1D1BD, "M", "𝆹𝅥𝅮"),
+ (0x1D1BE, "M", "𝆺𝅥𝅮"),
+ (0x1D1BF, "M", "𝆹𝅥𝅯"),
+ (0x1D1C0, "M", "𝆺𝅥𝅯"),
+ (0x1D1C1, "V"),
+ (0x1D1EB, "X"),
+ (0x1D200, "V"),
+ (0x1D246, "X"),
+ (0x1D2C0, "V"),
+ (0x1D2D4, "X"),
+ (0x1D2E0, "V"),
+ (0x1D2F4, "X"),
+ (0x1D300, "V"),
+ (0x1D357, "X"),
+ (0x1D360, "V"),
+ (0x1D379, "X"),
+ (0x1D400, "M", "a"),
+ (0x1D401, "M", "b"),
+ (0x1D402, "M", "c"),
+ (0x1D403, "M", "d"),
+ (0x1D404, "M", "e"),
+ (0x1D405, "M", "f"),
+ (0x1D406, "M", "g"),
+ (0x1D407, "M", "h"),
+ (0x1D408, "M", "i"),
+ (0x1D409, "M", "j"),
+ (0x1D40A, "M", "k"),
+ (0x1D40B, "M", "l"),
+ (0x1D40C, "M", "m"),
+ (0x1D40D, "M", "n"),
+ (0x1D40E, "M", "o"),
+ (0x1D40F, "M", "p"),
+ (0x1D410, "M", "q"),
+ (0x1D411, "M", "r"),
+ (0x1D412, "M", "s"),
+ (0x1D413, "M", "t"),
+ (0x1D414, "M", "u"),
+ (0x1D415, "M", "v"),
+ (0x1D416, "M", "w"),
+ (0x1D417, "M", "x"),
+ (0x1D418, "M", "y"),
+ (0x1D419, "M", "z"),
+ (0x1D41A, "M", "a"),
+ (0x1D41B, "M", "b"),
+ (0x1D41C, "M", "c"),
+ (0x1D41D, "M", "d"),
+ (0x1D41E, "M", "e"),
+ (0x1D41F, "M", "f"),
+ (0x1D420, "M", "g"),
+ (0x1D421, "M", "h"),
+ (0x1D422, "M", "i"),
+ (0x1D423, "M", "j"),
+ (0x1D424, "M", "k"),
+ ]
+
+
+def _seg_61() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1D425, "M", "l"),
+ (0x1D426, "M", "m"),
+ (0x1D427, "M", "n"),
+ (0x1D428, "M", "o"),
+ (0x1D429, "M", "p"),
+ (0x1D42A, "M", "q"),
+ (0x1D42B, "M", "r"),
+ (0x1D42C, "M", "s"),
+ (0x1D42D, "M", "t"),
+ (0x1D42E, "M", "u"),
+ (0x1D42F, "M", "v"),
+ (0x1D430, "M", "w"),
+ (0x1D431, "M", "x"),
+ (0x1D432, "M", "y"),
+ (0x1D433, "M", "z"),
+ (0x1D434, "M", "a"),
+ (0x1D435, "M", "b"),
+ (0x1D436, "M", "c"),
+ (0x1D437, "M", "d"),
+ (0x1D438, "M", "e"),
+ (0x1D439, "M", "f"),
+ (0x1D43A, "M", "g"),
+ (0x1D43B, "M", "h"),
+ (0x1D43C, "M", "i"),
+ (0x1D43D, "M", "j"),
+ (0x1D43E, "M", "k"),
+ (0x1D43F, "M", "l"),
+ (0x1D440, "M", "m"),
+ (0x1D441, "M", "n"),
+ (0x1D442, "M", "o"),
+ (0x1D443, "M", "p"),
+ (0x1D444, "M", "q"),
+ (0x1D445, "M", "r"),
+ (0x1D446, "M", "s"),
+ (0x1D447, "M", "t"),
+ (0x1D448, "M", "u"),
+ (0x1D449, "M", "v"),
+ (0x1D44A, "M", "w"),
+ (0x1D44B, "M", "x"),
+ (0x1D44C, "M", "y"),
+ (0x1D44D, "M", "z"),
+ (0x1D44E, "M", "a"),
+ (0x1D44F, "M", "b"),
+ (0x1D450, "M", "c"),
+ (0x1D451, "M", "d"),
+ (0x1D452, "M", "e"),
+ (0x1D453, "M", "f"),
+ (0x1D454, "M", "g"),
+ (0x1D455, "X"),
+ (0x1D456, "M", "i"),
+ (0x1D457, "M", "j"),
+ (0x1D458, "M", "k"),
+ (0x1D459, "M", "l"),
+ (0x1D45A, "M", "m"),
+ (0x1D45B, "M", "n"),
+ (0x1D45C, "M", "o"),
+ (0x1D45D, "M", "p"),
+ (0x1D45E, "M", "q"),
+ (0x1D45F, "M", "r"),
+ (0x1D460, "M", "s"),
+ (0x1D461, "M", "t"),
+ (0x1D462, "M", "u"),
+ (0x1D463, "M", "v"),
+ (0x1D464, "M", "w"),
+ (0x1D465, "M", "x"),
+ (0x1D466, "M", "y"),
+ (0x1D467, "M", "z"),
+ (0x1D468, "M", "a"),
+ (0x1D469, "M", "b"),
+ (0x1D46A, "M", "c"),
+ (0x1D46B, "M", "d"),
+ (0x1D46C, "M", "e"),
+ (0x1D46D, "M", "f"),
+ (0x1D46E, "M", "g"),
+ (0x1D46F, "M", "h"),
+ (0x1D470, "M", "i"),
+ (0x1D471, "M", "j"),
+ (0x1D472, "M", "k"),
+ (0x1D473, "M", "l"),
+ (0x1D474, "M", "m"),
+ (0x1D475, "M", "n"),
+ (0x1D476, "M", "o"),
+ (0x1D477, "M", "p"),
+ (0x1D478, "M", "q"),
+ (0x1D479, "M", "r"),
+ (0x1D47A, "M", "s"),
+ (0x1D47B, "M", "t"),
+ (0x1D47C, "M", "u"),
+ (0x1D47D, "M", "v"),
+ (0x1D47E, "M", "w"),
+ (0x1D47F, "M", "x"),
+ (0x1D480, "M", "y"),
+ (0x1D481, "M", "z"),
+ (0x1D482, "M", "a"),
+ (0x1D483, "M", "b"),
+ (0x1D484, "M", "c"),
+ (0x1D485, "M", "d"),
+ (0x1D486, "M", "e"),
+ (0x1D487, "M", "f"),
+ (0x1D488, "M", "g"),
+ ]
+
+
+def _seg_62() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1D489, "M", "h"),
+ (0x1D48A, "M", "i"),
+ (0x1D48B, "M", "j"),
+ (0x1D48C, "M", "k"),
+ (0x1D48D, "M", "l"),
+ (0x1D48E, "M", "m"),
+ (0x1D48F, "M", "n"),
+ (0x1D490, "M", "o"),
+ (0x1D491, "M", "p"),
+ (0x1D492, "M", "q"),
+ (0x1D493, "M", "r"),
+ (0x1D494, "M", "s"),
+ (0x1D495, "M", "t"),
+ (0x1D496, "M", "u"),
+ (0x1D497, "M", "v"),
+ (0x1D498, "M", "w"),
+ (0x1D499, "M", "x"),
+ (0x1D49A, "M", "y"),
+ (0x1D49B, "M", "z"),
+ (0x1D49C, "M", "a"),
+ (0x1D49D, "X"),
+ (0x1D49E, "M", "c"),
+ (0x1D49F, "M", "d"),
+ (0x1D4A0, "X"),
+ (0x1D4A2, "M", "g"),
+ (0x1D4A3, "X"),
+ (0x1D4A5, "M", "j"),
+ (0x1D4A6, "M", "k"),
+ (0x1D4A7, "X"),
+ (0x1D4A9, "M", "n"),
+ (0x1D4AA, "M", "o"),
+ (0x1D4AB, "M", "p"),
+ (0x1D4AC, "M", "q"),
+ (0x1D4AD, "X"),
+ (0x1D4AE, "M", "s"),
+ (0x1D4AF, "M", "t"),
+ (0x1D4B0, "M", "u"),
+ (0x1D4B1, "M", "v"),
+ (0x1D4B2, "M", "w"),
+ (0x1D4B3, "M", "x"),
+ (0x1D4B4, "M", "y"),
+ (0x1D4B5, "M", "z"),
+ (0x1D4B6, "M", "a"),
+ (0x1D4B7, "M", "b"),
+ (0x1D4B8, "M", "c"),
+ (0x1D4B9, "M", "d"),
+ (0x1D4BA, "X"),
+ (0x1D4BB, "M", "f"),
+ (0x1D4BC, "X"),
+ (0x1D4BD, "M", "h"),
+ (0x1D4BE, "M", "i"),
+ (0x1D4BF, "M", "j"),
+ (0x1D4C0, "M", "k"),
+ (0x1D4C1, "M", "l"),
+ (0x1D4C2, "M", "m"),
+ (0x1D4C3, "M", "n"),
+ (0x1D4C4, "X"),
+ (0x1D4C5, "M", "p"),
+ (0x1D4C6, "M", "q"),
+ (0x1D4C7, "M", "r"),
+ (0x1D4C8, "M", "s"),
+ (0x1D4C9, "M", "t"),
+ (0x1D4CA, "M", "u"),
+ (0x1D4CB, "M", "v"),
+ (0x1D4CC, "M", "w"),
+ (0x1D4CD, "M", "x"),
+ (0x1D4CE, "M", "y"),
+ (0x1D4CF, "M", "z"),
+ (0x1D4D0, "M", "a"),
+ (0x1D4D1, "M", "b"),
+ (0x1D4D2, "M", "c"),
+ (0x1D4D3, "M", "d"),
+ (0x1D4D4, "M", "e"),
+ (0x1D4D5, "M", "f"),
+ (0x1D4D6, "M", "g"),
+ (0x1D4D7, "M", "h"),
+ (0x1D4D8, "M", "i"),
+ (0x1D4D9, "M", "j"),
+ (0x1D4DA, "M", "k"),
+ (0x1D4DB, "M", "l"),
+ (0x1D4DC, "M", "m"),
+ (0x1D4DD, "M", "n"),
+ (0x1D4DE, "M", "o"),
+ (0x1D4DF, "M", "p"),
+ (0x1D4E0, "M", "q"),
+ (0x1D4E1, "M", "r"),
+ (0x1D4E2, "M", "s"),
+ (0x1D4E3, "M", "t"),
+ (0x1D4E4, "M", "u"),
+ (0x1D4E5, "M", "v"),
+ (0x1D4E6, "M", "w"),
+ (0x1D4E7, "M", "x"),
+ (0x1D4E8, "M", "y"),
+ (0x1D4E9, "M", "z"),
+ (0x1D4EA, "M", "a"),
+ (0x1D4EB, "M", "b"),
+ (0x1D4EC, "M", "c"),
+ (0x1D4ED, "M", "d"),
+ (0x1D4EE, "M", "e"),
+ (0x1D4EF, "M", "f"),
+ ]
+
+
+def _seg_63() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1D4F0, "M", "g"),
+ (0x1D4F1, "M", "h"),
+ (0x1D4F2, "M", "i"),
+ (0x1D4F3, "M", "j"),
+ (0x1D4F4, "M", "k"),
+ (0x1D4F5, "M", "l"),
+ (0x1D4F6, "M", "m"),
+ (0x1D4F7, "M", "n"),
+ (0x1D4F8, "M", "o"),
+ (0x1D4F9, "M", "p"),
+ (0x1D4FA, "M", "q"),
+ (0x1D4FB, "M", "r"),
+ (0x1D4FC, "M", "s"),
+ (0x1D4FD, "M", "t"),
+ (0x1D4FE, "M", "u"),
+ (0x1D4FF, "M", "v"),
+ (0x1D500, "M", "w"),
+ (0x1D501, "M", "x"),
+ (0x1D502, "M", "y"),
+ (0x1D503, "M", "z"),
+ (0x1D504, "M", "a"),
+ (0x1D505, "M", "b"),
+ (0x1D506, "X"),
+ (0x1D507, "M", "d"),
+ (0x1D508, "M", "e"),
+ (0x1D509, "M", "f"),
+ (0x1D50A, "M", "g"),
+ (0x1D50B, "X"),
+ (0x1D50D, "M", "j"),
+ (0x1D50E, "M", "k"),
+ (0x1D50F, "M", "l"),
+ (0x1D510, "M", "m"),
+ (0x1D511, "M", "n"),
+ (0x1D512, "M", "o"),
+ (0x1D513, "M", "p"),
+ (0x1D514, "M", "q"),
+ (0x1D515, "X"),
+ (0x1D516, "M", "s"),
+ (0x1D517, "M", "t"),
+ (0x1D518, "M", "u"),
+ (0x1D519, "M", "v"),
+ (0x1D51A, "M", "w"),
+ (0x1D51B, "M", "x"),
+ (0x1D51C, "M", "y"),
+ (0x1D51D, "X"),
+ (0x1D51E, "M", "a"),
+ (0x1D51F, "M", "b"),
+ (0x1D520, "M", "c"),
+ (0x1D521, "M", "d"),
+ (0x1D522, "M", "e"),
+ (0x1D523, "M", "f"),
+ (0x1D524, "M", "g"),
+ (0x1D525, "M", "h"),
+ (0x1D526, "M", "i"),
+ (0x1D527, "M", "j"),
+ (0x1D528, "M", "k"),
+ (0x1D529, "M", "l"),
+ (0x1D52A, "M", "m"),
+ (0x1D52B, "M", "n"),
+ (0x1D52C, "M", "o"),
+ (0x1D52D, "M", "p"),
+ (0x1D52E, "M", "q"),
+ (0x1D52F, "M", "r"),
+ (0x1D530, "M", "s"),
+ (0x1D531, "M", "t"),
+ (0x1D532, "M", "u"),
+ (0x1D533, "M", "v"),
+ (0x1D534, "M", "w"),
+ (0x1D535, "M", "x"),
+ (0x1D536, "M", "y"),
+ (0x1D537, "M", "z"),
+ (0x1D538, "M", "a"),
+ (0x1D539, "M", "b"),
+ (0x1D53A, "X"),
+ (0x1D53B, "M", "d"),
+ (0x1D53C, "M", "e"),
+ (0x1D53D, "M", "f"),
+ (0x1D53E, "M", "g"),
+ (0x1D53F, "X"),
+ (0x1D540, "M", "i"),
+ (0x1D541, "M", "j"),
+ (0x1D542, "M", "k"),
+ (0x1D543, "M", "l"),
+ (0x1D544, "M", "m"),
+ (0x1D545, "X"),
+ (0x1D546, "M", "o"),
+ (0x1D547, "X"),
+ (0x1D54A, "M", "s"),
+ (0x1D54B, "M", "t"),
+ (0x1D54C, "M", "u"),
+ (0x1D54D, "M", "v"),
+ (0x1D54E, "M", "w"),
+ (0x1D54F, "M", "x"),
+ (0x1D550, "M", "y"),
+ (0x1D551, "X"),
+ (0x1D552, "M", "a"),
+ (0x1D553, "M", "b"),
+ (0x1D554, "M", "c"),
+ (0x1D555, "M", "d"),
+ (0x1D556, "M", "e"),
+ ]
+
+
+def _seg_64() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1D557, "M", "f"),
+ (0x1D558, "M", "g"),
+ (0x1D559, "M", "h"),
+ (0x1D55A, "M", "i"),
+ (0x1D55B, "M", "j"),
+ (0x1D55C, "M", "k"),
+ (0x1D55D, "M", "l"),
+ (0x1D55E, "M", "m"),
+ (0x1D55F, "M", "n"),
+ (0x1D560, "M", "o"),
+ (0x1D561, "M", "p"),
+ (0x1D562, "M", "q"),
+ (0x1D563, "M", "r"),
+ (0x1D564, "M", "s"),
+ (0x1D565, "M", "t"),
+ (0x1D566, "M", "u"),
+ (0x1D567, "M", "v"),
+ (0x1D568, "M", "w"),
+ (0x1D569, "M", "x"),
+ (0x1D56A, "M", "y"),
+ (0x1D56B, "M", "z"),
+ (0x1D56C, "M", "a"),
+ (0x1D56D, "M", "b"),
+ (0x1D56E, "M", "c"),
+ (0x1D56F, "M", "d"),
+ (0x1D570, "M", "e"),
+ (0x1D571, "M", "f"),
+ (0x1D572, "M", "g"),
+ (0x1D573, "M", "h"),
+ (0x1D574, "M", "i"),
+ (0x1D575, "M", "j"),
+ (0x1D576, "M", "k"),
+ (0x1D577, "M", "l"),
+ (0x1D578, "M", "m"),
+ (0x1D579, "M", "n"),
+ (0x1D57A, "M", "o"),
+ (0x1D57B, "M", "p"),
+ (0x1D57C, "M", "q"),
+ (0x1D57D, "M", "r"),
+ (0x1D57E, "M", "s"),
+ (0x1D57F, "M", "t"),
+ (0x1D580, "M", "u"),
+ (0x1D581, "M", "v"),
+ (0x1D582, "M", "w"),
+ (0x1D583, "M", "x"),
+ (0x1D584, "M", "y"),
+ (0x1D585, "M", "z"),
+ (0x1D586, "M", "a"),
+ (0x1D587, "M", "b"),
+ (0x1D588, "M", "c"),
+ (0x1D589, "M", "d"),
+ (0x1D58A, "M", "e"),
+ (0x1D58B, "M", "f"),
+ (0x1D58C, "M", "g"),
+ (0x1D58D, "M", "h"),
+ (0x1D58E, "M", "i"),
+ (0x1D58F, "M", "j"),
+ (0x1D590, "M", "k"),
+ (0x1D591, "M", "l"),
+ (0x1D592, "M", "m"),
+ (0x1D593, "M", "n"),
+ (0x1D594, "M", "o"),
+ (0x1D595, "M", "p"),
+ (0x1D596, "M", "q"),
+ (0x1D597, "M", "r"),
+ (0x1D598, "M", "s"),
+ (0x1D599, "M", "t"),
+ (0x1D59A, "M", "u"),
+ (0x1D59B, "M", "v"),
+ (0x1D59C, "M", "w"),
+ (0x1D59D, "M", "x"),
+ (0x1D59E, "M", "y"),
+ (0x1D59F, "M", "z"),
+ (0x1D5A0, "M", "a"),
+ (0x1D5A1, "M", "b"),
+ (0x1D5A2, "M", "c"),
+ (0x1D5A3, "M", "d"),
+ (0x1D5A4, "M", "e"),
+ (0x1D5A5, "M", "f"),
+ (0x1D5A6, "M", "g"),
+ (0x1D5A7, "M", "h"),
+ (0x1D5A8, "M", "i"),
+ (0x1D5A9, "M", "j"),
+ (0x1D5AA, "M", "k"),
+ (0x1D5AB, "M", "l"),
+ (0x1D5AC, "M", "m"),
+ (0x1D5AD, "M", "n"),
+ (0x1D5AE, "M", "o"),
+ (0x1D5AF, "M", "p"),
+ (0x1D5B0, "M", "q"),
+ (0x1D5B1, "M", "r"),
+ (0x1D5B2, "M", "s"),
+ (0x1D5B3, "M", "t"),
+ (0x1D5B4, "M", "u"),
+ (0x1D5B5, "M", "v"),
+ (0x1D5B6, "M", "w"),
+ (0x1D5B7, "M", "x"),
+ (0x1D5B8, "M", "y"),
+ (0x1D5B9, "M", "z"),
+ (0x1D5BA, "M", "a"),
+ ]
+
+
+def _seg_65() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1D5BB, "M", "b"),
+ (0x1D5BC, "M", "c"),
+ (0x1D5BD, "M", "d"),
+ (0x1D5BE, "M", "e"),
+ (0x1D5BF, "M", "f"),
+ (0x1D5C0, "M", "g"),
+ (0x1D5C1, "M", "h"),
+ (0x1D5C2, "M", "i"),
+ (0x1D5C3, "M", "j"),
+ (0x1D5C4, "M", "k"),
+ (0x1D5C5, "M", "l"),
+ (0x1D5C6, "M", "m"),
+ (0x1D5C7, "M", "n"),
+ (0x1D5C8, "M", "o"),
+ (0x1D5C9, "M", "p"),
+ (0x1D5CA, "M", "q"),
+ (0x1D5CB, "M", "r"),
+ (0x1D5CC, "M", "s"),
+ (0x1D5CD, "M", "t"),
+ (0x1D5CE, "M", "u"),
+ (0x1D5CF, "M", "v"),
+ (0x1D5D0, "M", "w"),
+ (0x1D5D1, "M", "x"),
+ (0x1D5D2, "M", "y"),
+ (0x1D5D3, "M", "z"),
+ (0x1D5D4, "M", "a"),
+ (0x1D5D5, "M", "b"),
+ (0x1D5D6, "M", "c"),
+ (0x1D5D7, "M", "d"),
+ (0x1D5D8, "M", "e"),
+ (0x1D5D9, "M", "f"),
+ (0x1D5DA, "M", "g"),
+ (0x1D5DB, "M", "h"),
+ (0x1D5DC, "M", "i"),
+ (0x1D5DD, "M", "j"),
+ (0x1D5DE, "M", "k"),
+ (0x1D5DF, "M", "l"),
+ (0x1D5E0, "M", "m"),
+ (0x1D5E1, "M", "n"),
+ (0x1D5E2, "M", "o"),
+ (0x1D5E3, "M", "p"),
+ (0x1D5E4, "M", "q"),
+ (0x1D5E5, "M", "r"),
+ (0x1D5E6, "M", "s"),
+ (0x1D5E7, "M", "t"),
+ (0x1D5E8, "M", "u"),
+ (0x1D5E9, "M", "v"),
+ (0x1D5EA, "M", "w"),
+ (0x1D5EB, "M", "x"),
+ (0x1D5EC, "M", "y"),
+ (0x1D5ED, "M", "z"),
+ (0x1D5EE, "M", "a"),
+ (0x1D5EF, "M", "b"),
+ (0x1D5F0, "M", "c"),
+ (0x1D5F1, "M", "d"),
+ (0x1D5F2, "M", "e"),
+ (0x1D5F3, "M", "f"),
+ (0x1D5F4, "M", "g"),
+ (0x1D5F5, "M", "h"),
+ (0x1D5F6, "M", "i"),
+ (0x1D5F7, "M", "j"),
+ (0x1D5F8, "M", "k"),
+ (0x1D5F9, "M", "l"),
+ (0x1D5FA, "M", "m"),
+ (0x1D5FB, "M", "n"),
+ (0x1D5FC, "M", "o"),
+ (0x1D5FD, "M", "p"),
+ (0x1D5FE, "M", "q"),
+ (0x1D5FF, "M", "r"),
+ (0x1D600, "M", "s"),
+ (0x1D601, "M", "t"),
+ (0x1D602, "M", "u"),
+ (0x1D603, "M", "v"),
+ (0x1D604, "M", "w"),
+ (0x1D605, "M", "x"),
+ (0x1D606, "M", "y"),
+ (0x1D607, "M", "z"),
+ (0x1D608, "M", "a"),
+ (0x1D609, "M", "b"),
+ (0x1D60A, "M", "c"),
+ (0x1D60B, "M", "d"),
+ (0x1D60C, "M", "e"),
+ (0x1D60D, "M", "f"),
+ (0x1D60E, "M", "g"),
+ (0x1D60F, "M", "h"),
+ (0x1D610, "M", "i"),
+ (0x1D611, "M", "j"),
+ (0x1D612, "M", "k"),
+ (0x1D613, "M", "l"),
+ (0x1D614, "M", "m"),
+ (0x1D615, "M", "n"),
+ (0x1D616, "M", "o"),
+ (0x1D617, "M", "p"),
+ (0x1D618, "M", "q"),
+ (0x1D619, "M", "r"),
+ (0x1D61A, "M", "s"),
+ (0x1D61B, "M", "t"),
+ (0x1D61C, "M", "u"),
+ (0x1D61D, "M", "v"),
+ (0x1D61E, "M", "w"),
+ ]
+
+
+def _seg_66() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1D61F, "M", "x"),
+ (0x1D620, "M", "y"),
+ (0x1D621, "M", "z"),
+ (0x1D622, "M", "a"),
+ (0x1D623, "M", "b"),
+ (0x1D624, "M", "c"),
+ (0x1D625, "M", "d"),
+ (0x1D626, "M", "e"),
+ (0x1D627, "M", "f"),
+ (0x1D628, "M", "g"),
+ (0x1D629, "M", "h"),
+ (0x1D62A, "M", "i"),
+ (0x1D62B, "M", "j"),
+ (0x1D62C, "M", "k"),
+ (0x1D62D, "M", "l"),
+ (0x1D62E, "M", "m"),
+ (0x1D62F, "M", "n"),
+ (0x1D630, "M", "o"),
+ (0x1D631, "M", "p"),
+ (0x1D632, "M", "q"),
+ (0x1D633, "M", "r"),
+ (0x1D634, "M", "s"),
+ (0x1D635, "M", "t"),
+ (0x1D636, "M", "u"),
+ (0x1D637, "M", "v"),
+ (0x1D638, "M", "w"),
+ (0x1D639, "M", "x"),
+ (0x1D63A, "M", "y"),
+ (0x1D63B, "M", "z"),
+ (0x1D63C, "M", "a"),
+ (0x1D63D, "M", "b"),
+ (0x1D63E, "M", "c"),
+ (0x1D63F, "M", "d"),
+ (0x1D640, "M", "e"),
+ (0x1D641, "M", "f"),
+ (0x1D642, "M", "g"),
+ (0x1D643, "M", "h"),
+ (0x1D644, "M", "i"),
+ (0x1D645, "M", "j"),
+ (0x1D646, "M", "k"),
+ (0x1D647, "M", "l"),
+ (0x1D648, "M", "m"),
+ (0x1D649, "M", "n"),
+ (0x1D64A, "M", "o"),
+ (0x1D64B, "M", "p"),
+ (0x1D64C, "M", "q"),
+ (0x1D64D, "M", "r"),
+ (0x1D64E, "M", "s"),
+ (0x1D64F, "M", "t"),
+ (0x1D650, "M", "u"),
+ (0x1D651, "M", "v"),
+ (0x1D652, "M", "w"),
+ (0x1D653, "M", "x"),
+ (0x1D654, "M", "y"),
+ (0x1D655, "M", "z"),
+ (0x1D656, "M", "a"),
+ (0x1D657, "M", "b"),
+ (0x1D658, "M", "c"),
+ (0x1D659, "M", "d"),
+ (0x1D65A, "M", "e"),
+ (0x1D65B, "M", "f"),
+ (0x1D65C, "M", "g"),
+ (0x1D65D, "M", "h"),
+ (0x1D65E, "M", "i"),
+ (0x1D65F, "M", "j"),
+ (0x1D660, "M", "k"),
+ (0x1D661, "M", "l"),
+ (0x1D662, "M", "m"),
+ (0x1D663, "M", "n"),
+ (0x1D664, "M", "o"),
+ (0x1D665, "M", "p"),
+ (0x1D666, "M", "q"),
+ (0x1D667, "M", "r"),
+ (0x1D668, "M", "s"),
+ (0x1D669, "M", "t"),
+ (0x1D66A, "M", "u"),
+ (0x1D66B, "M", "v"),
+ (0x1D66C, "M", "w"),
+ (0x1D66D, "M", "x"),
+ (0x1D66E, "M", "y"),
+ (0x1D66F, "M", "z"),
+ (0x1D670, "M", "a"),
+ (0x1D671, "M", "b"),
+ (0x1D672, "M", "c"),
+ (0x1D673, "M", "d"),
+ (0x1D674, "M", "e"),
+ (0x1D675, "M", "f"),
+ (0x1D676, "M", "g"),
+ (0x1D677, "M", "h"),
+ (0x1D678, "M", "i"),
+ (0x1D679, "M", "j"),
+ (0x1D67A, "M", "k"),
+ (0x1D67B, "M", "l"),
+ (0x1D67C, "M", "m"),
+ (0x1D67D, "M", "n"),
+ (0x1D67E, "M", "o"),
+ (0x1D67F, "M", "p"),
+ (0x1D680, "M", "q"),
+ (0x1D681, "M", "r"),
+ (0x1D682, "M", "s"),
+ ]
+
+
+def _seg_67() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1D683, "M", "t"),
+ (0x1D684, "M", "u"),
+ (0x1D685, "M", "v"),
+ (0x1D686, "M", "w"),
+ (0x1D687, "M", "x"),
+ (0x1D688, "M", "y"),
+ (0x1D689, "M", "z"),
+ (0x1D68A, "M", "a"),
+ (0x1D68B, "M", "b"),
+ (0x1D68C, "M", "c"),
+ (0x1D68D, "M", "d"),
+ (0x1D68E, "M", "e"),
+ (0x1D68F, "M", "f"),
+ (0x1D690, "M", "g"),
+ (0x1D691, "M", "h"),
+ (0x1D692, "M", "i"),
+ (0x1D693, "M", "j"),
+ (0x1D694, "M", "k"),
+ (0x1D695, "M", "l"),
+ (0x1D696, "M", "m"),
+ (0x1D697, "M", "n"),
+ (0x1D698, "M", "o"),
+ (0x1D699, "M", "p"),
+ (0x1D69A, "M", "q"),
+ (0x1D69B, "M", "r"),
+ (0x1D69C, "M", "s"),
+ (0x1D69D, "M", "t"),
+ (0x1D69E, "M", "u"),
+ (0x1D69F, "M", "v"),
+ (0x1D6A0, "M", "w"),
+ (0x1D6A1, "M", "x"),
+ (0x1D6A2, "M", "y"),
+ (0x1D6A3, "M", "z"),
+ (0x1D6A4, "M", "ı"),
+ (0x1D6A5, "M", "ȷ"),
+ (0x1D6A6, "X"),
+ (0x1D6A8, "M", "α"),
+ (0x1D6A9, "M", "β"),
+ (0x1D6AA, "M", "γ"),
+ (0x1D6AB, "M", "δ"),
+ (0x1D6AC, "M", "ε"),
+ (0x1D6AD, "M", "ζ"),
+ (0x1D6AE, "M", "η"),
+ (0x1D6AF, "M", "θ"),
+ (0x1D6B0, "M", "ι"),
+ (0x1D6B1, "M", "κ"),
+ (0x1D6B2, "M", "λ"),
+ (0x1D6B3, "M", "μ"),
+ (0x1D6B4, "M", "ν"),
+ (0x1D6B5, "M", "ξ"),
+ (0x1D6B6, "M", "ο"),
+ (0x1D6B7, "M", "π"),
+ (0x1D6B8, "M", "ρ"),
+ (0x1D6B9, "M", "θ"),
+ (0x1D6BA, "M", "σ"),
+ (0x1D6BB, "M", "τ"),
+ (0x1D6BC, "M", "υ"),
+ (0x1D6BD, "M", "φ"),
+ (0x1D6BE, "M", "χ"),
+ (0x1D6BF, "M", "ψ"),
+ (0x1D6C0, "M", "ω"),
+ (0x1D6C1, "M", "∇"),
+ (0x1D6C2, "M", "α"),
+ (0x1D6C3, "M", "β"),
+ (0x1D6C4, "M", "γ"),
+ (0x1D6C5, "M", "δ"),
+ (0x1D6C6, "M", "ε"),
+ (0x1D6C7, "M", "ζ"),
+ (0x1D6C8, "M", "η"),
+ (0x1D6C9, "M", "θ"),
+ (0x1D6CA, "M", "ι"),
+ (0x1D6CB, "M", "κ"),
+ (0x1D6CC, "M", "λ"),
+ (0x1D6CD, "M", "μ"),
+ (0x1D6CE, "M", "ν"),
+ (0x1D6CF, "M", "ξ"),
+ (0x1D6D0, "M", "ο"),
+ (0x1D6D1, "M", "π"),
+ (0x1D6D2, "M", "ρ"),
+ (0x1D6D3, "M", "σ"),
+ (0x1D6D5, "M", "τ"),
+ (0x1D6D6, "M", "υ"),
+ (0x1D6D7, "M", "φ"),
+ (0x1D6D8, "M", "χ"),
+ (0x1D6D9, "M", "ψ"),
+ (0x1D6DA, "M", "ω"),
+ (0x1D6DB, "M", "∂"),
+ (0x1D6DC, "M", "ε"),
+ (0x1D6DD, "M", "θ"),
+ (0x1D6DE, "M", "κ"),
+ (0x1D6DF, "M", "φ"),
+ (0x1D6E0, "M", "ρ"),
+ (0x1D6E1, "M", "π"),
+ (0x1D6E2, "M", "α"),
+ (0x1D6E3, "M", "β"),
+ (0x1D6E4, "M", "γ"),
+ (0x1D6E5, "M", "δ"),
+ (0x1D6E6, "M", "ε"),
+ (0x1D6E7, "M", "ζ"),
+ (0x1D6E8, "M", "η"),
+ ]
+
+
+def _seg_68() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1D6E9, "M", "θ"),
+ (0x1D6EA, "M", "ι"),
+ (0x1D6EB, "M", "κ"),
+ (0x1D6EC, "M", "λ"),
+ (0x1D6ED, "M", "μ"),
+ (0x1D6EE, "M", "ν"),
+ (0x1D6EF, "M", "ξ"),
+ (0x1D6F0, "M", "ο"),
+ (0x1D6F1, "M", "π"),
+ (0x1D6F2, "M", "ρ"),
+ (0x1D6F3, "M", "θ"),
+ (0x1D6F4, "M", "σ"),
+ (0x1D6F5, "M", "τ"),
+ (0x1D6F6, "M", "υ"),
+ (0x1D6F7, "M", "φ"),
+ (0x1D6F8, "M", "χ"),
+ (0x1D6F9, "M", "ψ"),
+ (0x1D6FA, "M", "ω"),
+ (0x1D6FB, "M", "∇"),
+ (0x1D6FC, "M", "α"),
+ (0x1D6FD, "M", "β"),
+ (0x1D6FE, "M", "γ"),
+ (0x1D6FF, "M", "δ"),
+ (0x1D700, "M", "ε"),
+ (0x1D701, "M", "ζ"),
+ (0x1D702, "M", "η"),
+ (0x1D703, "M", "θ"),
+ (0x1D704, "M", "ι"),
+ (0x1D705, "M", "κ"),
+ (0x1D706, "M", "λ"),
+ (0x1D707, "M", "μ"),
+ (0x1D708, "M", "ν"),
+ (0x1D709, "M", "ξ"),
+ (0x1D70A, "M", "ο"),
+ (0x1D70B, "M", "π"),
+ (0x1D70C, "M", "ρ"),
+ (0x1D70D, "M", "σ"),
+ (0x1D70F, "M", "τ"),
+ (0x1D710, "M", "υ"),
+ (0x1D711, "M", "φ"),
+ (0x1D712, "M", "χ"),
+ (0x1D713, "M", "ψ"),
+ (0x1D714, "M", "ω"),
+ (0x1D715, "M", "∂"),
+ (0x1D716, "M", "ε"),
+ (0x1D717, "M", "θ"),
+ (0x1D718, "M", "κ"),
+ (0x1D719, "M", "φ"),
+ (0x1D71A, "M", "ρ"),
+ (0x1D71B, "M", "π"),
+ (0x1D71C, "M", "α"),
+ (0x1D71D, "M", "β"),
+ (0x1D71E, "M", "γ"),
+ (0x1D71F, "M", "δ"),
+ (0x1D720, "M", "ε"),
+ (0x1D721, "M", "ζ"),
+ (0x1D722, "M", "η"),
+ (0x1D723, "M", "θ"),
+ (0x1D724, "M", "ι"),
+ (0x1D725, "M", "κ"),
+ (0x1D726, "M", "λ"),
+ (0x1D727, "M", "μ"),
+ (0x1D728, "M", "ν"),
+ (0x1D729, "M", "ξ"),
+ (0x1D72A, "M", "ο"),
+ (0x1D72B, "M", "π"),
+ (0x1D72C, "M", "ρ"),
+ (0x1D72D, "M", "θ"),
+ (0x1D72E, "M", "σ"),
+ (0x1D72F, "M", "τ"),
+ (0x1D730, "M", "υ"),
+ (0x1D731, "M", "φ"),
+ (0x1D732, "M", "χ"),
+ (0x1D733, "M", "ψ"),
+ (0x1D734, "M", "ω"),
+ (0x1D735, "M", "∇"),
+ (0x1D736, "M", "α"),
+ (0x1D737, "M", "β"),
+ (0x1D738, "M", "γ"),
+ (0x1D739, "M", "δ"),
+ (0x1D73A, "M", "ε"),
+ (0x1D73B, "M", "ζ"),
+ (0x1D73C, "M", "η"),
+ (0x1D73D, "M", "θ"),
+ (0x1D73E, "M", "ι"),
+ (0x1D73F, "M", "κ"),
+ (0x1D740, "M", "λ"),
+ (0x1D741, "M", "μ"),
+ (0x1D742, "M", "ν"),
+ (0x1D743, "M", "ξ"),
+ (0x1D744, "M", "ο"),
+ (0x1D745, "M", "π"),
+ (0x1D746, "M", "ρ"),
+ (0x1D747, "M", "σ"),
+ (0x1D749, "M", "τ"),
+ (0x1D74A, "M", "υ"),
+ (0x1D74B, "M", "φ"),
+ (0x1D74C, "M", "χ"),
+ (0x1D74D, "M", "ψ"),
+ (0x1D74E, "M", "ω"),
+ ]
+
+
+def _seg_69() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1D74F, "M", "∂"),
+ (0x1D750, "M", "ε"),
+ (0x1D751, "M", "θ"),
+ (0x1D752, "M", "κ"),
+ (0x1D753, "M", "φ"),
+ (0x1D754, "M", "ρ"),
+ (0x1D755, "M", "π"),
+ (0x1D756, "M", "α"),
+ (0x1D757, "M", "β"),
+ (0x1D758, "M", "γ"),
+ (0x1D759, "M", "δ"),
+ (0x1D75A, "M", "ε"),
+ (0x1D75B, "M", "ζ"),
+ (0x1D75C, "M", "η"),
+ (0x1D75D, "M", "θ"),
+ (0x1D75E, "M", "ι"),
+ (0x1D75F, "M", "κ"),
+ (0x1D760, "M", "λ"),
+ (0x1D761, "M", "μ"),
+ (0x1D762, "M", "ν"),
+ (0x1D763, "M", "ξ"),
+ (0x1D764, "M", "ο"),
+ (0x1D765, "M", "π"),
+ (0x1D766, "M", "ρ"),
+ (0x1D767, "M", "θ"),
+ (0x1D768, "M", "σ"),
+ (0x1D769, "M", "τ"),
+ (0x1D76A, "M", "υ"),
+ (0x1D76B, "M", "φ"),
+ (0x1D76C, "M", "χ"),
+ (0x1D76D, "M", "ψ"),
+ (0x1D76E, "M", "ω"),
+ (0x1D76F, "M", "∇"),
+ (0x1D770, "M", "α"),
+ (0x1D771, "M", "β"),
+ (0x1D772, "M", "γ"),
+ (0x1D773, "M", "δ"),
+ (0x1D774, "M", "ε"),
+ (0x1D775, "M", "ζ"),
+ (0x1D776, "M", "η"),
+ (0x1D777, "M", "θ"),
+ (0x1D778, "M", "ι"),
+ (0x1D779, "M", "κ"),
+ (0x1D77A, "M", "λ"),
+ (0x1D77B, "M", "μ"),
+ (0x1D77C, "M", "ν"),
+ (0x1D77D, "M", "ξ"),
+ (0x1D77E, "M", "ο"),
+ (0x1D77F, "M", "π"),
+ (0x1D780, "M", "ρ"),
+ (0x1D781, "M", "σ"),
+ (0x1D783, "M", "τ"),
+ (0x1D784, "M", "υ"),
+ (0x1D785, "M", "φ"),
+ (0x1D786, "M", "χ"),
+ (0x1D787, "M", "ψ"),
+ (0x1D788, "M", "ω"),
+ (0x1D789, "M", "∂"),
+ (0x1D78A, "M", "ε"),
+ (0x1D78B, "M", "θ"),
+ (0x1D78C, "M", "κ"),
+ (0x1D78D, "M", "φ"),
+ (0x1D78E, "M", "ρ"),
+ (0x1D78F, "M", "π"),
+ (0x1D790, "M", "α"),
+ (0x1D791, "M", "β"),
+ (0x1D792, "M", "γ"),
+ (0x1D793, "M", "δ"),
+ (0x1D794, "M", "ε"),
+ (0x1D795, "M", "ζ"),
+ (0x1D796, "M", "η"),
+ (0x1D797, "M", "θ"),
+ (0x1D798, "M", "ι"),
+ (0x1D799, "M", "κ"),
+ (0x1D79A, "M", "λ"),
+ (0x1D79B, "M", "μ"),
+ (0x1D79C, "M", "ν"),
+ (0x1D79D, "M", "ξ"),
+ (0x1D79E, "M", "ο"),
+ (0x1D79F, "M", "π"),
+ (0x1D7A0, "M", "ρ"),
+ (0x1D7A1, "M", "θ"),
+ (0x1D7A2, "M", "σ"),
+ (0x1D7A3, "M", "τ"),
+ (0x1D7A4, "M", "υ"),
+ (0x1D7A5, "M", "φ"),
+ (0x1D7A6, "M", "χ"),
+ (0x1D7A7, "M", "ψ"),
+ (0x1D7A8, "M", "ω"),
+ (0x1D7A9, "M", "∇"),
+ (0x1D7AA, "M", "α"),
+ (0x1D7AB, "M", "β"),
+ (0x1D7AC, "M", "γ"),
+ (0x1D7AD, "M", "δ"),
+ (0x1D7AE, "M", "ε"),
+ (0x1D7AF, "M", "ζ"),
+ (0x1D7B0, "M", "η"),
+ (0x1D7B1, "M", "θ"),
+ (0x1D7B2, "M", "ι"),
+ (0x1D7B3, "M", "κ"),
+ ]
+
+
+def _seg_70() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1D7B4, "M", "λ"),
+ (0x1D7B5, "M", "μ"),
+ (0x1D7B6, "M", "ν"),
+ (0x1D7B7, "M", "ξ"),
+ (0x1D7B8, "M", "ο"),
+ (0x1D7B9, "M", "π"),
+ (0x1D7BA, "M", "ρ"),
+ (0x1D7BB, "M", "σ"),
+ (0x1D7BD, "M", "τ"),
+ (0x1D7BE, "M", "υ"),
+ (0x1D7BF, "M", "φ"),
+ (0x1D7C0, "M", "χ"),
+ (0x1D7C1, "M", "ψ"),
+ (0x1D7C2, "M", "ω"),
+ (0x1D7C3, "M", "∂"),
+ (0x1D7C4, "M", "ε"),
+ (0x1D7C5, "M", "θ"),
+ (0x1D7C6, "M", "κ"),
+ (0x1D7C7, "M", "φ"),
+ (0x1D7C8, "M", "ρ"),
+ (0x1D7C9, "M", "π"),
+ (0x1D7CA, "M", "ϝ"),
+ (0x1D7CC, "X"),
+ (0x1D7CE, "M", "0"),
+ (0x1D7CF, "M", "1"),
+ (0x1D7D0, "M", "2"),
+ (0x1D7D1, "M", "3"),
+ (0x1D7D2, "M", "4"),
+ (0x1D7D3, "M", "5"),
+ (0x1D7D4, "M", "6"),
+ (0x1D7D5, "M", "7"),
+ (0x1D7D6, "M", "8"),
+ (0x1D7D7, "M", "9"),
+ (0x1D7D8, "M", "0"),
+ (0x1D7D9, "M", "1"),
+ (0x1D7DA, "M", "2"),
+ (0x1D7DB, "M", "3"),
+ (0x1D7DC, "M", "4"),
+ (0x1D7DD, "M", "5"),
+ (0x1D7DE, "M", "6"),
+ (0x1D7DF, "M", "7"),
+ (0x1D7E0, "M", "8"),
+ (0x1D7E1, "M", "9"),
+ (0x1D7E2, "M", "0"),
+ (0x1D7E3, "M", "1"),
+ (0x1D7E4, "M", "2"),
+ (0x1D7E5, "M", "3"),
+ (0x1D7E6, "M", "4"),
+ (0x1D7E7, "M", "5"),
+ (0x1D7E8, "M", "6"),
+ (0x1D7E9, "M", "7"),
+ (0x1D7EA, "M", "8"),
+ (0x1D7EB, "M", "9"),
+ (0x1D7EC, "M", "0"),
+ (0x1D7ED, "M", "1"),
+ (0x1D7EE, "M", "2"),
+ (0x1D7EF, "M", "3"),
+ (0x1D7F0, "M", "4"),
+ (0x1D7F1, "M", "5"),
+ (0x1D7F2, "M", "6"),
+ (0x1D7F3, "M", "7"),
+ (0x1D7F4, "M", "8"),
+ (0x1D7F5, "M", "9"),
+ (0x1D7F6, "M", "0"),
+ (0x1D7F7, "M", "1"),
+ (0x1D7F8, "M", "2"),
+ (0x1D7F9, "M", "3"),
+ (0x1D7FA, "M", "4"),
+ (0x1D7FB, "M", "5"),
+ (0x1D7FC, "M", "6"),
+ (0x1D7FD, "M", "7"),
+ (0x1D7FE, "M", "8"),
+ (0x1D7FF, "M", "9"),
+ (0x1D800, "V"),
+ (0x1DA8C, "X"),
+ (0x1DA9B, "V"),
+ (0x1DAA0, "X"),
+ (0x1DAA1, "V"),
+ (0x1DAB0, "X"),
+ (0x1DF00, "V"),
+ (0x1DF1F, "X"),
+ (0x1DF25, "V"),
+ (0x1DF2B, "X"),
+ (0x1E000, "V"),
+ (0x1E007, "X"),
+ (0x1E008, "V"),
+ (0x1E019, "X"),
+ (0x1E01B, "V"),
+ (0x1E022, "X"),
+ (0x1E023, "V"),
+ (0x1E025, "X"),
+ (0x1E026, "V"),
+ (0x1E02B, "X"),
+ (0x1E030, "M", "а"),
+ (0x1E031, "M", "б"),
+ (0x1E032, "M", "в"),
+ (0x1E033, "M", "г"),
+ (0x1E034, "M", "д"),
+ (0x1E035, "M", "е"),
+ (0x1E036, "M", "ж"),
+ ]
+
+
+def _seg_71() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1E037, "M", "з"),
+ (0x1E038, "M", "и"),
+ (0x1E039, "M", "к"),
+ (0x1E03A, "M", "л"),
+ (0x1E03B, "M", "м"),
+ (0x1E03C, "M", "о"),
+ (0x1E03D, "M", "п"),
+ (0x1E03E, "M", "р"),
+ (0x1E03F, "M", "с"),
+ (0x1E040, "M", "т"),
+ (0x1E041, "M", "у"),
+ (0x1E042, "M", "ф"),
+ (0x1E043, "M", "х"),
+ (0x1E044, "M", "ц"),
+ (0x1E045, "M", "ч"),
+ (0x1E046, "M", "ш"),
+ (0x1E047, "M", "ы"),
+ (0x1E048, "M", "э"),
+ (0x1E049, "M", "ю"),
+ (0x1E04A, "M", "ꚉ"),
+ (0x1E04B, "M", "ә"),
+ (0x1E04C, "M", "і"),
+ (0x1E04D, "M", "ј"),
+ (0x1E04E, "M", "ө"),
+ (0x1E04F, "M", "ү"),
+ (0x1E050, "M", "ӏ"),
+ (0x1E051, "M", "а"),
+ (0x1E052, "M", "б"),
+ (0x1E053, "M", "в"),
+ (0x1E054, "M", "г"),
+ (0x1E055, "M", "д"),
+ (0x1E056, "M", "е"),
+ (0x1E057, "M", "ж"),
+ (0x1E058, "M", "з"),
+ (0x1E059, "M", "и"),
+ (0x1E05A, "M", "к"),
+ (0x1E05B, "M", "л"),
+ (0x1E05C, "M", "о"),
+ (0x1E05D, "M", "п"),
+ (0x1E05E, "M", "с"),
+ (0x1E05F, "M", "у"),
+ (0x1E060, "M", "ф"),
+ (0x1E061, "M", "х"),
+ (0x1E062, "M", "ц"),
+ (0x1E063, "M", "ч"),
+ (0x1E064, "M", "ш"),
+ (0x1E065, "M", "ъ"),
+ (0x1E066, "M", "ы"),
+ (0x1E067, "M", "ґ"),
+ (0x1E068, "M", "і"),
+ (0x1E069, "M", "ѕ"),
+ (0x1E06A, "M", "џ"),
+ (0x1E06B, "M", "ҫ"),
+ (0x1E06C, "M", "ꙑ"),
+ (0x1E06D, "M", "ұ"),
+ (0x1E06E, "X"),
+ (0x1E08F, "V"),
+ (0x1E090, "X"),
+ (0x1E100, "V"),
+ (0x1E12D, "X"),
+ (0x1E130, "V"),
+ (0x1E13E, "X"),
+ (0x1E140, "V"),
+ (0x1E14A, "X"),
+ (0x1E14E, "V"),
+ (0x1E150, "X"),
+ (0x1E290, "V"),
+ (0x1E2AF, "X"),
+ (0x1E2C0, "V"),
+ (0x1E2FA, "X"),
+ (0x1E2FF, "V"),
+ (0x1E300, "X"),
+ (0x1E4D0, "V"),
+ (0x1E4FA, "X"),
+ (0x1E7E0, "V"),
+ (0x1E7E7, "X"),
+ (0x1E7E8, "V"),
+ (0x1E7EC, "X"),
+ (0x1E7ED, "V"),
+ (0x1E7EF, "X"),
+ (0x1E7F0, "V"),
+ (0x1E7FF, "X"),
+ (0x1E800, "V"),
+ (0x1E8C5, "X"),
+ (0x1E8C7, "V"),
+ (0x1E8D7, "X"),
+ (0x1E900, "M", "𞤢"),
+ (0x1E901, "M", "𞤣"),
+ (0x1E902, "M", "𞤤"),
+ (0x1E903, "M", "𞤥"),
+ (0x1E904, "M", "𞤦"),
+ (0x1E905, "M", "𞤧"),
+ (0x1E906, "M", "𞤨"),
+ (0x1E907, "M", "𞤩"),
+ (0x1E908, "M", "𞤪"),
+ (0x1E909, "M", "𞤫"),
+ (0x1E90A, "M", "𞤬"),
+ (0x1E90B, "M", "𞤭"),
+ (0x1E90C, "M", "𞤮"),
+ (0x1E90D, "M", "𞤯"),
+ ]
+
+
+def _seg_72() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1E90E, "M", "𞤰"),
+ (0x1E90F, "M", "𞤱"),
+ (0x1E910, "M", "𞤲"),
+ (0x1E911, "M", "𞤳"),
+ (0x1E912, "M", "𞤴"),
+ (0x1E913, "M", "𞤵"),
+ (0x1E914, "M", "𞤶"),
+ (0x1E915, "M", "𞤷"),
+ (0x1E916, "M", "𞤸"),
+ (0x1E917, "M", "𞤹"),
+ (0x1E918, "M", "𞤺"),
+ (0x1E919, "M", "𞤻"),
+ (0x1E91A, "M", "𞤼"),
+ (0x1E91B, "M", "𞤽"),
+ (0x1E91C, "M", "𞤾"),
+ (0x1E91D, "M", "𞤿"),
+ (0x1E91E, "M", "𞥀"),
+ (0x1E91F, "M", "𞥁"),
+ (0x1E920, "M", "𞥂"),
+ (0x1E921, "M", "𞥃"),
+ (0x1E922, "V"),
+ (0x1E94C, "X"),
+ (0x1E950, "V"),
+ (0x1E95A, "X"),
+ (0x1E95E, "V"),
+ (0x1E960, "X"),
+ (0x1EC71, "V"),
+ (0x1ECB5, "X"),
+ (0x1ED01, "V"),
+ (0x1ED3E, "X"),
+ (0x1EE00, "M", "ا"),
+ (0x1EE01, "M", "ب"),
+ (0x1EE02, "M", "ج"),
+ (0x1EE03, "M", "د"),
+ (0x1EE04, "X"),
+ (0x1EE05, "M", "و"),
+ (0x1EE06, "M", "ز"),
+ (0x1EE07, "M", "ح"),
+ (0x1EE08, "M", "ط"),
+ (0x1EE09, "M", "ي"),
+ (0x1EE0A, "M", "ك"),
+ (0x1EE0B, "M", "ل"),
+ (0x1EE0C, "M", "م"),
+ (0x1EE0D, "M", "ن"),
+ (0x1EE0E, "M", "س"),
+ (0x1EE0F, "M", "ع"),
+ (0x1EE10, "M", "ف"),
+ (0x1EE11, "M", "ص"),
+ (0x1EE12, "M", "ق"),
+ (0x1EE13, "M", "ر"),
+ (0x1EE14, "M", "ش"),
+ (0x1EE15, "M", "ت"),
+ (0x1EE16, "M", "ث"),
+ (0x1EE17, "M", "خ"),
+ (0x1EE18, "M", "ذ"),
+ (0x1EE19, "M", "ض"),
+ (0x1EE1A, "M", "ظ"),
+ (0x1EE1B, "M", "غ"),
+ (0x1EE1C, "M", "ٮ"),
+ (0x1EE1D, "M", "ں"),
+ (0x1EE1E, "M", "ڡ"),
+ (0x1EE1F, "M", "ٯ"),
+ (0x1EE20, "X"),
+ (0x1EE21, "M", "ب"),
+ (0x1EE22, "M", "ج"),
+ (0x1EE23, "X"),
+ (0x1EE24, "M", "ه"),
+ (0x1EE25, "X"),
+ (0x1EE27, "M", "ح"),
+ (0x1EE28, "X"),
+ (0x1EE29, "M", "ي"),
+ (0x1EE2A, "M", "ك"),
+ (0x1EE2B, "M", "ل"),
+ (0x1EE2C, "M", "م"),
+ (0x1EE2D, "M", "ن"),
+ (0x1EE2E, "M", "س"),
+ (0x1EE2F, "M", "ع"),
+ (0x1EE30, "M", "ف"),
+ (0x1EE31, "M", "ص"),
+ (0x1EE32, "M", "ق"),
+ (0x1EE33, "X"),
+ (0x1EE34, "M", "ش"),
+ (0x1EE35, "M", "ت"),
+ (0x1EE36, "M", "ث"),
+ (0x1EE37, "M", "خ"),
+ (0x1EE38, "X"),
+ (0x1EE39, "M", "ض"),
+ (0x1EE3A, "X"),
+ (0x1EE3B, "M", "غ"),
+ (0x1EE3C, "X"),
+ (0x1EE42, "M", "ج"),
+ (0x1EE43, "X"),
+ (0x1EE47, "M", "ح"),
+ (0x1EE48, "X"),
+ (0x1EE49, "M", "ي"),
+ (0x1EE4A, "X"),
+ (0x1EE4B, "M", "ل"),
+ (0x1EE4C, "X"),
+ (0x1EE4D, "M", "ن"),
+ (0x1EE4E, "M", "س"),
+ ]
+
+
+def _seg_73() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1EE4F, "M", "ع"),
+ (0x1EE50, "X"),
+ (0x1EE51, "M", "ص"),
+ (0x1EE52, "M", "ق"),
+ (0x1EE53, "X"),
+ (0x1EE54, "M", "ش"),
+ (0x1EE55, "X"),
+ (0x1EE57, "M", "خ"),
+ (0x1EE58, "X"),
+ (0x1EE59, "M", "ض"),
+ (0x1EE5A, "X"),
+ (0x1EE5B, "M", "غ"),
+ (0x1EE5C, "X"),
+ (0x1EE5D, "M", "ں"),
+ (0x1EE5E, "X"),
+ (0x1EE5F, "M", "ٯ"),
+ (0x1EE60, "X"),
+ (0x1EE61, "M", "ب"),
+ (0x1EE62, "M", "ج"),
+ (0x1EE63, "X"),
+ (0x1EE64, "M", "ه"),
+ (0x1EE65, "X"),
+ (0x1EE67, "M", "ح"),
+ (0x1EE68, "M", "ط"),
+ (0x1EE69, "M", "ي"),
+ (0x1EE6A, "M", "ك"),
+ (0x1EE6B, "X"),
+ (0x1EE6C, "M", "م"),
+ (0x1EE6D, "M", "ن"),
+ (0x1EE6E, "M", "س"),
+ (0x1EE6F, "M", "ع"),
+ (0x1EE70, "M", "ف"),
+ (0x1EE71, "M", "ص"),
+ (0x1EE72, "M", "ق"),
+ (0x1EE73, "X"),
+ (0x1EE74, "M", "ش"),
+ (0x1EE75, "M", "ت"),
+ (0x1EE76, "M", "ث"),
+ (0x1EE77, "M", "خ"),
+ (0x1EE78, "X"),
+ (0x1EE79, "M", "ض"),
+ (0x1EE7A, "M", "ظ"),
+ (0x1EE7B, "M", "غ"),
+ (0x1EE7C, "M", "ٮ"),
+ (0x1EE7D, "X"),
+ (0x1EE7E, "M", "ڡ"),
+ (0x1EE7F, "X"),
+ (0x1EE80, "M", "ا"),
+ (0x1EE81, "M", "ب"),
+ (0x1EE82, "M", "ج"),
+ (0x1EE83, "M", "د"),
+ (0x1EE84, "M", "ه"),
+ (0x1EE85, "M", "و"),
+ (0x1EE86, "M", "ز"),
+ (0x1EE87, "M", "ح"),
+ (0x1EE88, "M", "ط"),
+ (0x1EE89, "M", "ي"),
+ (0x1EE8A, "X"),
+ (0x1EE8B, "M", "ل"),
+ (0x1EE8C, "M", "م"),
+ (0x1EE8D, "M", "ن"),
+ (0x1EE8E, "M", "س"),
+ (0x1EE8F, "M", "ع"),
+ (0x1EE90, "M", "ف"),
+ (0x1EE91, "M", "ص"),
+ (0x1EE92, "M", "ق"),
+ (0x1EE93, "M", "ر"),
+ (0x1EE94, "M", "ش"),
+ (0x1EE95, "M", "ت"),
+ (0x1EE96, "M", "ث"),
+ (0x1EE97, "M", "خ"),
+ (0x1EE98, "M", "ذ"),
+ (0x1EE99, "M", "ض"),
+ (0x1EE9A, "M", "ظ"),
+ (0x1EE9B, "M", "غ"),
+ (0x1EE9C, "X"),
+ (0x1EEA1, "M", "ب"),
+ (0x1EEA2, "M", "ج"),
+ (0x1EEA3, "M", "د"),
+ (0x1EEA4, "X"),
+ (0x1EEA5, "M", "و"),
+ (0x1EEA6, "M", "ز"),
+ (0x1EEA7, "M", "ح"),
+ (0x1EEA8, "M", "ط"),
+ (0x1EEA9, "M", "ي"),
+ (0x1EEAA, "X"),
+ (0x1EEAB, "M", "ل"),
+ (0x1EEAC, "M", "م"),
+ (0x1EEAD, "M", "ن"),
+ (0x1EEAE, "M", "س"),
+ (0x1EEAF, "M", "ع"),
+ (0x1EEB0, "M", "ف"),
+ (0x1EEB1, "M", "ص"),
+ (0x1EEB2, "M", "ق"),
+ (0x1EEB3, "M", "ر"),
+ (0x1EEB4, "M", "ش"),
+ (0x1EEB5, "M", "ت"),
+ (0x1EEB6, "M", "ث"),
+ (0x1EEB7, "M", "خ"),
+ (0x1EEB8, "M", "ذ"),
+ ]
+
+
+def _seg_74() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1EEB9, "M", "ض"),
+ (0x1EEBA, "M", "ظ"),
+ (0x1EEBB, "M", "غ"),
+ (0x1EEBC, "X"),
+ (0x1EEF0, "V"),
+ (0x1EEF2, "X"),
+ (0x1F000, "V"),
+ (0x1F02C, "X"),
+ (0x1F030, "V"),
+ (0x1F094, "X"),
+ (0x1F0A0, "V"),
+ (0x1F0AF, "X"),
+ (0x1F0B1, "V"),
+ (0x1F0C0, "X"),
+ (0x1F0C1, "V"),
+ (0x1F0D0, "X"),
+ (0x1F0D1, "V"),
+ (0x1F0F6, "X"),
+ (0x1F101, "3", "0,"),
+ (0x1F102, "3", "1,"),
+ (0x1F103, "3", "2,"),
+ (0x1F104, "3", "3,"),
+ (0x1F105, "3", "4,"),
+ (0x1F106, "3", "5,"),
+ (0x1F107, "3", "6,"),
+ (0x1F108, "3", "7,"),
+ (0x1F109, "3", "8,"),
+ (0x1F10A, "3", "9,"),
+ (0x1F10B, "V"),
+ (0x1F110, "3", "(a)"),
+ (0x1F111, "3", "(b)"),
+ (0x1F112, "3", "(c)"),
+ (0x1F113, "3", "(d)"),
+ (0x1F114, "3", "(e)"),
+ (0x1F115, "3", "(f)"),
+ (0x1F116, "3", "(g)"),
+ (0x1F117, "3", "(h)"),
+ (0x1F118, "3", "(i)"),
+ (0x1F119, "3", "(j)"),
+ (0x1F11A, "3", "(k)"),
+ (0x1F11B, "3", "(l)"),
+ (0x1F11C, "3", "(m)"),
+ (0x1F11D, "3", "(n)"),
+ (0x1F11E, "3", "(o)"),
+ (0x1F11F, "3", "(p)"),
+ (0x1F120, "3", "(q)"),
+ (0x1F121, "3", "(r)"),
+ (0x1F122, "3", "(s)"),
+ (0x1F123, "3", "(t)"),
+ (0x1F124, "3", "(u)"),
+ (0x1F125, "3", "(v)"),
+ (0x1F126, "3", "(w)"),
+ (0x1F127, "3", "(x)"),
+ (0x1F128, "3", "(y)"),
+ (0x1F129, "3", "(z)"),
+ (0x1F12A, "M", "〔s〕"),
+ (0x1F12B, "M", "c"),
+ (0x1F12C, "M", "r"),
+ (0x1F12D, "M", "cd"),
+ (0x1F12E, "M", "wz"),
+ (0x1F12F, "V"),
+ (0x1F130, "M", "a"),
+ (0x1F131, "M", "b"),
+ (0x1F132, "M", "c"),
+ (0x1F133, "M", "d"),
+ (0x1F134, "M", "e"),
+ (0x1F135, "M", "f"),
+ (0x1F136, "M", "g"),
+ (0x1F137, "M", "h"),
+ (0x1F138, "M", "i"),
+ (0x1F139, "M", "j"),
+ (0x1F13A, "M", "k"),
+ (0x1F13B, "M", "l"),
+ (0x1F13C, "M", "m"),
+ (0x1F13D, "M", "n"),
+ (0x1F13E, "M", "o"),
+ (0x1F13F, "M", "p"),
+ (0x1F140, "M", "q"),
+ (0x1F141, "M", "r"),
+ (0x1F142, "M", "s"),
+ (0x1F143, "M", "t"),
+ (0x1F144, "M", "u"),
+ (0x1F145, "M", "v"),
+ (0x1F146, "M", "w"),
+ (0x1F147, "M", "x"),
+ (0x1F148, "M", "y"),
+ (0x1F149, "M", "z"),
+ (0x1F14A, "M", "hv"),
+ (0x1F14B, "M", "mv"),
+ (0x1F14C, "M", "sd"),
+ (0x1F14D, "M", "ss"),
+ (0x1F14E, "M", "ppv"),
+ (0x1F14F, "M", "wc"),
+ (0x1F150, "V"),
+ (0x1F16A, "M", "mc"),
+ (0x1F16B, "M", "md"),
+ (0x1F16C, "M", "mr"),
+ (0x1F16D, "V"),
+ (0x1F190, "M", "dj"),
+ (0x1F191, "V"),
+ ]
+
+
+def _seg_75() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1F1AE, "X"),
+ (0x1F1E6, "V"),
+ (0x1F200, "M", "ほか"),
+ (0x1F201, "M", "ココ"),
+ (0x1F202, "M", "サ"),
+ (0x1F203, "X"),
+ (0x1F210, "M", "手"),
+ (0x1F211, "M", "字"),
+ (0x1F212, "M", "双"),
+ (0x1F213, "M", "デ"),
+ (0x1F214, "M", "二"),
+ (0x1F215, "M", "多"),
+ (0x1F216, "M", "解"),
+ (0x1F217, "M", "天"),
+ (0x1F218, "M", "交"),
+ (0x1F219, "M", "映"),
+ (0x1F21A, "M", "無"),
+ (0x1F21B, "M", "料"),
+ (0x1F21C, "M", "前"),
+ (0x1F21D, "M", "後"),
+ (0x1F21E, "M", "再"),
+ (0x1F21F, "M", "新"),
+ (0x1F220, "M", "初"),
+ (0x1F221, "M", "終"),
+ (0x1F222, "M", "生"),
+ (0x1F223, "M", "販"),
+ (0x1F224, "M", "声"),
+ (0x1F225, "M", "吹"),
+ (0x1F226, "M", "演"),
+ (0x1F227, "M", "投"),
+ (0x1F228, "M", "捕"),
+ (0x1F229, "M", "一"),
+ (0x1F22A, "M", "三"),
+ (0x1F22B, "M", "遊"),
+ (0x1F22C, "M", "左"),
+ (0x1F22D, "M", "中"),
+ (0x1F22E, "M", "右"),
+ (0x1F22F, "M", "指"),
+ (0x1F230, "M", "走"),
+ (0x1F231, "M", "打"),
+ (0x1F232, "M", "禁"),
+ (0x1F233, "M", "空"),
+ (0x1F234, "M", "合"),
+ (0x1F235, "M", "満"),
+ (0x1F236, "M", "有"),
+ (0x1F237, "M", "月"),
+ (0x1F238, "M", "申"),
+ (0x1F239, "M", "割"),
+ (0x1F23A, "M", "営"),
+ (0x1F23B, "M", "配"),
+ (0x1F23C, "X"),
+ (0x1F240, "M", "〔本〕"),
+ (0x1F241, "M", "〔三〕"),
+ (0x1F242, "M", "〔二〕"),
+ (0x1F243, "M", "〔安〕"),
+ (0x1F244, "M", "〔点〕"),
+ (0x1F245, "M", "〔打〕"),
+ (0x1F246, "M", "〔盗〕"),
+ (0x1F247, "M", "〔勝〕"),
+ (0x1F248, "M", "〔敗〕"),
+ (0x1F249, "X"),
+ (0x1F250, "M", "得"),
+ (0x1F251, "M", "可"),
+ (0x1F252, "X"),
+ (0x1F260, "V"),
+ (0x1F266, "X"),
+ (0x1F300, "V"),
+ (0x1F6D8, "X"),
+ (0x1F6DC, "V"),
+ (0x1F6ED, "X"),
+ (0x1F6F0, "V"),
+ (0x1F6FD, "X"),
+ (0x1F700, "V"),
+ (0x1F777, "X"),
+ (0x1F77B, "V"),
+ (0x1F7DA, "X"),
+ (0x1F7E0, "V"),
+ (0x1F7EC, "X"),
+ (0x1F7F0, "V"),
+ (0x1F7F1, "X"),
+ (0x1F800, "V"),
+ (0x1F80C, "X"),
+ (0x1F810, "V"),
+ (0x1F848, "X"),
+ (0x1F850, "V"),
+ (0x1F85A, "X"),
+ (0x1F860, "V"),
+ (0x1F888, "X"),
+ (0x1F890, "V"),
+ (0x1F8AE, "X"),
+ (0x1F8B0, "V"),
+ (0x1F8B2, "X"),
+ (0x1F900, "V"),
+ (0x1FA54, "X"),
+ (0x1FA60, "V"),
+ (0x1FA6E, "X"),
+ (0x1FA70, "V"),
+ (0x1FA7D, "X"),
+ (0x1FA80, "V"),
+ (0x1FA89, "X"),
+ ]
+
+
+def _seg_76() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x1FA90, "V"),
+ (0x1FABE, "X"),
+ (0x1FABF, "V"),
+ (0x1FAC6, "X"),
+ (0x1FACE, "V"),
+ (0x1FADC, "X"),
+ (0x1FAE0, "V"),
+ (0x1FAE9, "X"),
+ (0x1FAF0, "V"),
+ (0x1FAF9, "X"),
+ (0x1FB00, "V"),
+ (0x1FB93, "X"),
+ (0x1FB94, "V"),
+ (0x1FBCB, "X"),
+ (0x1FBF0, "M", "0"),
+ (0x1FBF1, "M", "1"),
+ (0x1FBF2, "M", "2"),
+ (0x1FBF3, "M", "3"),
+ (0x1FBF4, "M", "4"),
+ (0x1FBF5, "M", "5"),
+ (0x1FBF6, "M", "6"),
+ (0x1FBF7, "M", "7"),
+ (0x1FBF8, "M", "8"),
+ (0x1FBF9, "M", "9"),
+ (0x1FBFA, "X"),
+ (0x20000, "V"),
+ (0x2A6E0, "X"),
+ (0x2A700, "V"),
+ (0x2B73A, "X"),
+ (0x2B740, "V"),
+ (0x2B81E, "X"),
+ (0x2B820, "V"),
+ (0x2CEA2, "X"),
+ (0x2CEB0, "V"),
+ (0x2EBE1, "X"),
+ (0x2EBF0, "V"),
+ (0x2EE5E, "X"),
+ (0x2F800, "M", "丽"),
+ (0x2F801, "M", "丸"),
+ (0x2F802, "M", "乁"),
+ (0x2F803, "M", "𠄢"),
+ (0x2F804, "M", "你"),
+ (0x2F805, "M", "侮"),
+ (0x2F806, "M", "侻"),
+ (0x2F807, "M", "倂"),
+ (0x2F808, "M", "偺"),
+ (0x2F809, "M", "備"),
+ (0x2F80A, "M", "僧"),
+ (0x2F80B, "M", "像"),
+ (0x2F80C, "M", "㒞"),
+ (0x2F80D, "M", "𠘺"),
+ (0x2F80E, "M", "免"),
+ (0x2F80F, "M", "兔"),
+ (0x2F810, "M", "兤"),
+ (0x2F811, "M", "具"),
+ (0x2F812, "M", "𠔜"),
+ (0x2F813, "M", "㒹"),
+ (0x2F814, "M", "內"),
+ (0x2F815, "M", "再"),
+ (0x2F816, "M", "𠕋"),
+ (0x2F817, "M", "冗"),
+ (0x2F818, "M", "冤"),
+ (0x2F819, "M", "仌"),
+ (0x2F81A, "M", "冬"),
+ (0x2F81B, "M", "况"),
+ (0x2F81C, "M", "𩇟"),
+ (0x2F81D, "M", "凵"),
+ (0x2F81E, "M", "刃"),
+ (0x2F81F, "M", "㓟"),
+ (0x2F820, "M", "刻"),
+ (0x2F821, "M", "剆"),
+ (0x2F822, "M", "割"),
+ (0x2F823, "M", "剷"),
+ (0x2F824, "M", "㔕"),
+ (0x2F825, "M", "勇"),
+ (0x2F826, "M", "勉"),
+ (0x2F827, "M", "勤"),
+ (0x2F828, "M", "勺"),
+ (0x2F829, "M", "包"),
+ (0x2F82A, "M", "匆"),
+ (0x2F82B, "M", "北"),
+ (0x2F82C, "M", "卉"),
+ (0x2F82D, "M", "卑"),
+ (0x2F82E, "M", "博"),
+ (0x2F82F, "M", "即"),
+ (0x2F830, "M", "卽"),
+ (0x2F831, "M", "卿"),
+ (0x2F834, "M", "𠨬"),
+ (0x2F835, "M", "灰"),
+ (0x2F836, "M", "及"),
+ (0x2F837, "M", "叟"),
+ (0x2F838, "M", "𠭣"),
+ (0x2F839, "M", "叫"),
+ (0x2F83A, "M", "叱"),
+ (0x2F83B, "M", "吆"),
+ (0x2F83C, "M", "咞"),
+ (0x2F83D, "M", "吸"),
+ (0x2F83E, "M", "呈"),
+ (0x2F83F, "M", "周"),
+ (0x2F840, "M", "咢"),
+ ]
+
+
+def _seg_77() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x2F841, "M", "哶"),
+ (0x2F842, "M", "唐"),
+ (0x2F843, "M", "啓"),
+ (0x2F844, "M", "啣"),
+ (0x2F845, "M", "善"),
+ (0x2F847, "M", "喙"),
+ (0x2F848, "M", "喫"),
+ (0x2F849, "M", "喳"),
+ (0x2F84A, "M", "嗂"),
+ (0x2F84B, "M", "圖"),
+ (0x2F84C, "M", "嘆"),
+ (0x2F84D, "M", "圗"),
+ (0x2F84E, "M", "噑"),
+ (0x2F84F, "M", "噴"),
+ (0x2F850, "M", "切"),
+ (0x2F851, "M", "壮"),
+ (0x2F852, "M", "城"),
+ (0x2F853, "M", "埴"),
+ (0x2F854, "M", "堍"),
+ (0x2F855, "M", "型"),
+ (0x2F856, "M", "堲"),
+ (0x2F857, "M", "報"),
+ (0x2F858, "M", "墬"),
+ (0x2F859, "M", "𡓤"),
+ (0x2F85A, "M", "売"),
+ (0x2F85B, "M", "壷"),
+ (0x2F85C, "M", "夆"),
+ (0x2F85D, "M", "多"),
+ (0x2F85E, "M", "夢"),
+ (0x2F85F, "M", "奢"),
+ (0x2F860, "M", "𡚨"),
+ (0x2F861, "M", "𡛪"),
+ (0x2F862, "M", "姬"),
+ (0x2F863, "M", "娛"),
+ (0x2F864, "M", "娧"),
+ (0x2F865, "M", "姘"),
+ (0x2F866, "M", "婦"),
+ (0x2F867, "M", "㛮"),
+ (0x2F868, "X"),
+ (0x2F869, "M", "嬈"),
+ (0x2F86A, "M", "嬾"),
+ (0x2F86C, "M", "𡧈"),
+ (0x2F86D, "M", "寃"),
+ (0x2F86E, "M", "寘"),
+ (0x2F86F, "M", "寧"),
+ (0x2F870, "M", "寳"),
+ (0x2F871, "M", "𡬘"),
+ (0x2F872, "M", "寿"),
+ (0x2F873, "M", "将"),
+ (0x2F874, "X"),
+ (0x2F875, "M", "尢"),
+ (0x2F876, "M", "㞁"),
+ (0x2F877, "M", "屠"),
+ (0x2F878, "M", "屮"),
+ (0x2F879, "M", "峀"),
+ (0x2F87A, "M", "岍"),
+ (0x2F87B, "M", "𡷤"),
+ (0x2F87C, "M", "嵃"),
+ (0x2F87D, "M", "𡷦"),
+ (0x2F87E, "M", "嵮"),
+ (0x2F87F, "M", "嵫"),
+ (0x2F880, "M", "嵼"),
+ (0x2F881, "M", "巡"),
+ (0x2F882, "M", "巢"),
+ (0x2F883, "M", "㠯"),
+ (0x2F884, "M", "巽"),
+ (0x2F885, "M", "帨"),
+ (0x2F886, "M", "帽"),
+ (0x2F887, "M", "幩"),
+ (0x2F888, "M", "㡢"),
+ (0x2F889, "M", "𢆃"),
+ (0x2F88A, "M", "㡼"),
+ (0x2F88B, "M", "庰"),
+ (0x2F88C, "M", "庳"),
+ (0x2F88D, "M", "庶"),
+ (0x2F88E, "M", "廊"),
+ (0x2F88F, "M", "𪎒"),
+ (0x2F890, "M", "廾"),
+ (0x2F891, "M", "𢌱"),
+ (0x2F893, "M", "舁"),
+ (0x2F894, "M", "弢"),
+ (0x2F896, "M", "㣇"),
+ (0x2F897, "M", "𣊸"),
+ (0x2F898, "M", "𦇚"),
+ (0x2F899, "M", "形"),
+ (0x2F89A, "M", "彫"),
+ (0x2F89B, "M", "㣣"),
+ (0x2F89C, "M", "徚"),
+ (0x2F89D, "M", "忍"),
+ (0x2F89E, "M", "志"),
+ (0x2F89F, "M", "忹"),
+ (0x2F8A0, "M", "悁"),
+ (0x2F8A1, "M", "㤺"),
+ (0x2F8A2, "M", "㤜"),
+ (0x2F8A3, "M", "悔"),
+ (0x2F8A4, "M", "𢛔"),
+ (0x2F8A5, "M", "惇"),
+ (0x2F8A6, "M", "慈"),
+ (0x2F8A7, "M", "慌"),
+ (0x2F8A8, "M", "慎"),
+ ]
+
+
+def _seg_78() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x2F8A9, "M", "慌"),
+ (0x2F8AA, "M", "慺"),
+ (0x2F8AB, "M", "憎"),
+ (0x2F8AC, "M", "憲"),
+ (0x2F8AD, "M", "憤"),
+ (0x2F8AE, "M", "憯"),
+ (0x2F8AF, "M", "懞"),
+ (0x2F8B0, "M", "懲"),
+ (0x2F8B1, "M", "懶"),
+ (0x2F8B2, "M", "成"),
+ (0x2F8B3, "M", "戛"),
+ (0x2F8B4, "M", "扝"),
+ (0x2F8B5, "M", "抱"),
+ (0x2F8B6, "M", "拔"),
+ (0x2F8B7, "M", "捐"),
+ (0x2F8B8, "M", "𢬌"),
+ (0x2F8B9, "M", "挽"),
+ (0x2F8BA, "M", "拼"),
+ (0x2F8BB, "M", "捨"),
+ (0x2F8BC, "M", "掃"),
+ (0x2F8BD, "M", "揤"),
+ (0x2F8BE, "M", "𢯱"),
+ (0x2F8BF, "M", "搢"),
+ (0x2F8C0, "M", "揅"),
+ (0x2F8C1, "M", "掩"),
+ (0x2F8C2, "M", "㨮"),
+ (0x2F8C3, "M", "摩"),
+ (0x2F8C4, "M", "摾"),
+ (0x2F8C5, "M", "撝"),
+ (0x2F8C6, "M", "摷"),
+ (0x2F8C7, "M", "㩬"),
+ (0x2F8C8, "M", "敏"),
+ (0x2F8C9, "M", "敬"),
+ (0x2F8CA, "M", "𣀊"),
+ (0x2F8CB, "M", "旣"),
+ (0x2F8CC, "M", "書"),
+ (0x2F8CD, "M", "晉"),
+ (0x2F8CE, "M", "㬙"),
+ (0x2F8CF, "M", "暑"),
+ (0x2F8D0, "M", "㬈"),
+ (0x2F8D1, "M", "㫤"),
+ (0x2F8D2, "M", "冒"),
+ (0x2F8D3, "M", "冕"),
+ (0x2F8D4, "M", "最"),
+ (0x2F8D5, "M", "暜"),
+ (0x2F8D6, "M", "肭"),
+ (0x2F8D7, "M", "䏙"),
+ (0x2F8D8, "M", "朗"),
+ (0x2F8D9, "M", "望"),
+ (0x2F8DA, "M", "朡"),
+ (0x2F8DB, "M", "杞"),
+ (0x2F8DC, "M", "杓"),
+ (0x2F8DD, "M", "𣏃"),
+ (0x2F8DE, "M", "㭉"),
+ (0x2F8DF, "M", "柺"),
+ (0x2F8E0, "M", "枅"),
+ (0x2F8E1, "M", "桒"),
+ (0x2F8E2, "M", "梅"),
+ (0x2F8E3, "M", "𣑭"),
+ (0x2F8E4, "M", "梎"),
+ (0x2F8E5, "M", "栟"),
+ (0x2F8E6, "M", "椔"),
+ (0x2F8E7, "M", "㮝"),
+ (0x2F8E8, "M", "楂"),
+ (0x2F8E9, "M", "榣"),
+ (0x2F8EA, "M", "槪"),
+ (0x2F8EB, "M", "檨"),
+ (0x2F8EC, "M", "𣚣"),
+ (0x2F8ED, "M", "櫛"),
+ (0x2F8EE, "M", "㰘"),
+ (0x2F8EF, "M", "次"),
+ (0x2F8F0, "M", "𣢧"),
+ (0x2F8F1, "M", "歔"),
+ (0x2F8F2, "M", "㱎"),
+ (0x2F8F3, "M", "歲"),
+ (0x2F8F4, "M", "殟"),
+ (0x2F8F5, "M", "殺"),
+ (0x2F8F6, "M", "殻"),
+ (0x2F8F7, "M", "𣪍"),
+ (0x2F8F8, "M", "𡴋"),
+ (0x2F8F9, "M", "𣫺"),
+ (0x2F8FA, "M", "汎"),
+ (0x2F8FB, "M", "𣲼"),
+ (0x2F8FC, "M", "沿"),
+ (0x2F8FD, "M", "泍"),
+ (0x2F8FE, "M", "汧"),
+ (0x2F8FF, "M", "洖"),
+ (0x2F900, "M", "派"),
+ (0x2F901, "M", "海"),
+ (0x2F902, "M", "流"),
+ (0x2F903, "M", "浩"),
+ (0x2F904, "M", "浸"),
+ (0x2F905, "M", "涅"),
+ (0x2F906, "M", "𣴞"),
+ (0x2F907, "M", "洴"),
+ (0x2F908, "M", "港"),
+ (0x2F909, "M", "湮"),
+ (0x2F90A, "M", "㴳"),
+ (0x2F90B, "M", "滋"),
+ (0x2F90C, "M", "滇"),
+ ]
+
+
+def _seg_79() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x2F90D, "M", "𣻑"),
+ (0x2F90E, "M", "淹"),
+ (0x2F90F, "M", "潮"),
+ (0x2F910, "M", "𣽞"),
+ (0x2F911, "M", "𣾎"),
+ (0x2F912, "M", "濆"),
+ (0x2F913, "M", "瀹"),
+ (0x2F914, "M", "瀞"),
+ (0x2F915, "M", "瀛"),
+ (0x2F916, "M", "㶖"),
+ (0x2F917, "M", "灊"),
+ (0x2F918, "M", "災"),
+ (0x2F919, "M", "灷"),
+ (0x2F91A, "M", "炭"),
+ (0x2F91B, "M", "𠔥"),
+ (0x2F91C, "M", "煅"),
+ (0x2F91D, "M", "𤉣"),
+ (0x2F91E, "M", "熜"),
+ (0x2F91F, "X"),
+ (0x2F920, "M", "爨"),
+ (0x2F921, "M", "爵"),
+ (0x2F922, "M", "牐"),
+ (0x2F923, "M", "𤘈"),
+ (0x2F924, "M", "犀"),
+ (0x2F925, "M", "犕"),
+ (0x2F926, "M", "𤜵"),
+ (0x2F927, "M", "𤠔"),
+ (0x2F928, "M", "獺"),
+ (0x2F929, "M", "王"),
+ (0x2F92A, "M", "㺬"),
+ (0x2F92B, "M", "玥"),
+ (0x2F92C, "M", "㺸"),
+ (0x2F92E, "M", "瑇"),
+ (0x2F92F, "M", "瑜"),
+ (0x2F930, "M", "瑱"),
+ (0x2F931, "M", "璅"),
+ (0x2F932, "M", "瓊"),
+ (0x2F933, "M", "㼛"),
+ (0x2F934, "M", "甤"),
+ (0x2F935, "M", "𤰶"),
+ (0x2F936, "M", "甾"),
+ (0x2F937, "M", "𤲒"),
+ (0x2F938, "M", "異"),
+ (0x2F939, "M", "𢆟"),
+ (0x2F93A, "M", "瘐"),
+ (0x2F93B, "M", "𤾡"),
+ (0x2F93C, "M", "𤾸"),
+ (0x2F93D, "M", "𥁄"),
+ (0x2F93E, "M", "㿼"),
+ (0x2F93F, "M", "䀈"),
+ (0x2F940, "M", "直"),
+ (0x2F941, "M", "𥃳"),
+ (0x2F942, "M", "𥃲"),
+ (0x2F943, "M", "𥄙"),
+ (0x2F944, "M", "𥄳"),
+ (0x2F945, "M", "眞"),
+ (0x2F946, "M", "真"),
+ (0x2F948, "M", "睊"),
+ (0x2F949, "M", "䀹"),
+ (0x2F94A, "M", "瞋"),
+ (0x2F94B, "M", "䁆"),
+ (0x2F94C, "M", "䂖"),
+ (0x2F94D, "M", "𥐝"),
+ (0x2F94E, "M", "硎"),
+ (0x2F94F, "M", "碌"),
+ (0x2F950, "M", "磌"),
+ (0x2F951, "M", "䃣"),
+ (0x2F952, "M", "𥘦"),
+ (0x2F953, "M", "祖"),
+ (0x2F954, "M", "𥚚"),
+ (0x2F955, "M", "𥛅"),
+ (0x2F956, "M", "福"),
+ (0x2F957, "M", "秫"),
+ (0x2F958, "M", "䄯"),
+ (0x2F959, "M", "穀"),
+ (0x2F95A, "M", "穊"),
+ (0x2F95B, "M", "穏"),
+ (0x2F95C, "M", "𥥼"),
+ (0x2F95D, "M", "𥪧"),
+ (0x2F95F, "X"),
+ (0x2F960, "M", "䈂"),
+ (0x2F961, "M", "𥮫"),
+ (0x2F962, "M", "篆"),
+ (0x2F963, "M", "築"),
+ (0x2F964, "M", "䈧"),
+ (0x2F965, "M", "𥲀"),
+ (0x2F966, "M", "糒"),
+ (0x2F967, "M", "䊠"),
+ (0x2F968, "M", "糨"),
+ (0x2F969, "M", "糣"),
+ (0x2F96A, "M", "紀"),
+ (0x2F96B, "M", "𥾆"),
+ (0x2F96C, "M", "絣"),
+ (0x2F96D, "M", "䌁"),
+ (0x2F96E, "M", "緇"),
+ (0x2F96F, "M", "縂"),
+ (0x2F970, "M", "繅"),
+ (0x2F971, "M", "䌴"),
+ (0x2F972, "M", "𦈨"),
+ (0x2F973, "M", "𦉇"),
+ ]
+
+
+def _seg_80() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x2F974, "M", "䍙"),
+ (0x2F975, "M", "𦋙"),
+ (0x2F976, "M", "罺"),
+ (0x2F977, "M", "𦌾"),
+ (0x2F978, "M", "羕"),
+ (0x2F979, "M", "翺"),
+ (0x2F97A, "M", "者"),
+ (0x2F97B, "M", "𦓚"),
+ (0x2F97C, "M", "𦔣"),
+ (0x2F97D, "M", "聠"),
+ (0x2F97E, "M", "𦖨"),
+ (0x2F97F, "M", "聰"),
+ (0x2F980, "M", "𣍟"),
+ (0x2F981, "M", "䏕"),
+ (0x2F982, "M", "育"),
+ (0x2F983, "M", "脃"),
+ (0x2F984, "M", "䐋"),
+ (0x2F985, "M", "脾"),
+ (0x2F986, "M", "媵"),
+ (0x2F987, "M", "𦞧"),
+ (0x2F988, "M", "𦞵"),
+ (0x2F989, "M", "𣎓"),
+ (0x2F98A, "M", "𣎜"),
+ (0x2F98B, "M", "舁"),
+ (0x2F98C, "M", "舄"),
+ (0x2F98D, "M", "辞"),
+ (0x2F98E, "M", "䑫"),
+ (0x2F98F, "M", "芑"),
+ (0x2F990, "M", "芋"),
+ (0x2F991, "M", "芝"),
+ (0x2F992, "M", "劳"),
+ (0x2F993, "M", "花"),
+ (0x2F994, "M", "芳"),
+ (0x2F995, "M", "芽"),
+ (0x2F996, "M", "苦"),
+ (0x2F997, "M", "𦬼"),
+ (0x2F998, "M", "若"),
+ (0x2F999, "M", "茝"),
+ (0x2F99A, "M", "荣"),
+ (0x2F99B, "M", "莭"),
+ (0x2F99C, "M", "茣"),
+ (0x2F99D, "M", "莽"),
+ (0x2F99E, "M", "菧"),
+ (0x2F99F, "M", "著"),
+ (0x2F9A0, "M", "荓"),
+ (0x2F9A1, "M", "菊"),
+ (0x2F9A2, "M", "菌"),
+ (0x2F9A3, "M", "菜"),
+ (0x2F9A4, "M", "𦰶"),
+ (0x2F9A5, "M", "𦵫"),
+ (0x2F9A6, "M", "𦳕"),
+ (0x2F9A7, "M", "䔫"),
+ (0x2F9A8, "M", "蓱"),
+ (0x2F9A9, "M", "蓳"),
+ (0x2F9AA, "M", "蔖"),
+ (0x2F9AB, "M", "𧏊"),
+ (0x2F9AC, "M", "蕤"),
+ (0x2F9AD, "M", "𦼬"),
+ (0x2F9AE, "M", "䕝"),
+ (0x2F9AF, "M", "䕡"),
+ (0x2F9B0, "M", "𦾱"),
+ (0x2F9B1, "M", "𧃒"),
+ (0x2F9B2, "M", "䕫"),
+ (0x2F9B3, "M", "虐"),
+ (0x2F9B4, "M", "虜"),
+ (0x2F9B5, "M", "虧"),
+ (0x2F9B6, "M", "虩"),
+ (0x2F9B7, "M", "蚩"),
+ (0x2F9B8, "M", "蚈"),
+ (0x2F9B9, "M", "蜎"),
+ (0x2F9BA, "M", "蛢"),
+ (0x2F9BB, "M", "蝹"),
+ (0x2F9BC, "M", "蜨"),
+ (0x2F9BD, "M", "蝫"),
+ (0x2F9BE, "M", "螆"),
+ (0x2F9BF, "X"),
+ (0x2F9C0, "M", "蟡"),
+ (0x2F9C1, "M", "蠁"),
+ (0x2F9C2, "M", "䗹"),
+ (0x2F9C3, "M", "衠"),
+ (0x2F9C4, "M", "衣"),
+ (0x2F9C5, "M", "𧙧"),
+ (0x2F9C6, "M", "裗"),
+ (0x2F9C7, "M", "裞"),
+ (0x2F9C8, "M", "䘵"),
+ (0x2F9C9, "M", "裺"),
+ (0x2F9CA, "M", "㒻"),
+ (0x2F9CB, "M", "𧢮"),
+ (0x2F9CC, "M", "𧥦"),
+ (0x2F9CD, "M", "䚾"),
+ (0x2F9CE, "M", "䛇"),
+ (0x2F9CF, "M", "誠"),
+ (0x2F9D0, "M", "諭"),
+ (0x2F9D1, "M", "變"),
+ (0x2F9D2, "M", "豕"),
+ (0x2F9D3, "M", "𧲨"),
+ (0x2F9D4, "M", "貫"),
+ (0x2F9D5, "M", "賁"),
+ (0x2F9D6, "M", "贛"),
+ (0x2F9D7, "M", "起"),
+ ]
+
+
+def _seg_81() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]:
+ return [
+ (0x2F9D8, "M", "𧼯"),
+ (0x2F9D9, "M", "𠠄"),
+ (0x2F9DA, "M", "跋"),
+ (0x2F9DB, "M", "趼"),
+ (0x2F9DC, "M", "跰"),
+ (0x2F9DD, "M", "𠣞"),
+ (0x2F9DE, "M", "軔"),
+ (0x2F9DF, "M", "輸"),
+ (0x2F9E0, "M", "𨗒"),
+ (0x2F9E1, "M", "𨗭"),
+ (0x2F9E2, "M", "邔"),
+ (0x2F9E3, "M", "郱"),
+ (0x2F9E4, "M", "鄑"),
+ (0x2F9E5, "M", "𨜮"),
+ (0x2F9E6, "M", "鄛"),
+ (0x2F9E7, "M", "鈸"),
+ (0x2F9E8, "M", "鋗"),
+ (0x2F9E9, "M", "鋘"),
+ (0x2F9EA, "M", "鉼"),
+ (0x2F9EB, "M", "鏹"),
+ (0x2F9EC, "M", "鐕"),
+ (0x2F9ED, "M", "𨯺"),
+ (0x2F9EE, "M", "開"),
+ (0x2F9EF, "M", "䦕"),
+ (0x2F9F0, "M", "閷"),
+ (0x2F9F1, "M", "𨵷"),
+ (0x2F9F2, "M", "䧦"),
+ (0x2F9F3, "M", "雃"),
+ (0x2F9F4, "M", "嶲"),
+ (0x2F9F5, "M", "霣"),
+ (0x2F9F6, "M", "𩅅"),
+ (0x2F9F7, "M", "𩈚"),
+ (0x2F9F8, "M", "䩮"),
+ (0x2F9F9, "M", "䩶"),
+ (0x2F9FA, "M", "韠"),
+ (0x2F9FB, "M", "𩐊"),
+ (0x2F9FC, "M", "䪲"),
+ (0x2F9FD, "M", "𩒖"),
+ (0x2F9FE, "M", "頋"),
+ (0x2FA00, "M", "頩"),
+ (0x2FA01, "M", "𩖶"),
+ (0x2FA02, "M", "飢"),
+ (0x2FA03, "M", "䬳"),
+ (0x2FA04, "M", "餩"),
+ (0x2FA05, "M", "馧"),
+ (0x2FA06, "M", "駂"),
+ (0x2FA07, "M", "駾"),
+ (0x2FA08, "M", "䯎"),
+ (0x2FA09, "M", "𩬰"),
+ (0x2FA0A, "M", "鬒"),
+ (0x2FA0B, "M", "鱀"),
+ (0x2FA0C, "M", "鳽"),
+ (0x2FA0D, "M", "䳎"),
+ (0x2FA0E, "M", "䳭"),
+ (0x2FA0F, "M", "鵧"),
+ (0x2FA10, "M", "𪃎"),
+ (0x2FA11, "M", "䳸"),
+ (0x2FA12, "M", "𪄅"),
+ (0x2FA13, "M", "𪈎"),
+ (0x2FA14, "M", "𪊑"),
+ (0x2FA15, "M", "麻"),
+ (0x2FA16, "M", "䵖"),
+ (0x2FA17, "M", "黹"),
+ (0x2FA18, "M", "黾"),
+ (0x2FA19, "M", "鼅"),
+ (0x2FA1A, "M", "鼏"),
+ (0x2FA1B, "M", "鼖"),
+ (0x2FA1C, "M", "鼻"),
+ (0x2FA1D, "M", "𪘀"),
+ (0x2FA1E, "X"),
+ (0x30000, "V"),
+ (0x3134B, "X"),
+ (0x31350, "V"),
+ (0x323B0, "X"),
+ (0xE0100, "I"),
+ (0xE01F0, "X"),
+ ]
+
+
+uts46data = tuple(
+ _seg_0()
+ + _seg_1()
+ + _seg_2()
+ + _seg_3()
+ + _seg_4()
+ + _seg_5()
+ + _seg_6()
+ + _seg_7()
+ + _seg_8()
+ + _seg_9()
+ + _seg_10()
+ + _seg_11()
+ + _seg_12()
+ + _seg_13()
+ + _seg_14()
+ + _seg_15()
+ + _seg_16()
+ + _seg_17()
+ + _seg_18()
+ + _seg_19()
+ + _seg_20()
+ + _seg_21()
+ + _seg_22()
+ + _seg_23()
+ + _seg_24()
+ + _seg_25()
+ + _seg_26()
+ + _seg_27()
+ + _seg_28()
+ + _seg_29()
+ + _seg_30()
+ + _seg_31()
+ + _seg_32()
+ + _seg_33()
+ + _seg_34()
+ + _seg_35()
+ + _seg_36()
+ + _seg_37()
+ + _seg_38()
+ + _seg_39()
+ + _seg_40()
+ + _seg_41()
+ + _seg_42()
+ + _seg_43()
+ + _seg_44()
+ + _seg_45()
+ + _seg_46()
+ + _seg_47()
+ + _seg_48()
+ + _seg_49()
+ + _seg_50()
+ + _seg_51()
+ + _seg_52()
+ + _seg_53()
+ + _seg_54()
+ + _seg_55()
+ + _seg_56()
+ + _seg_57()
+ + _seg_58()
+ + _seg_59()
+ + _seg_60()
+ + _seg_61()
+ + _seg_62()
+ + _seg_63()
+ + _seg_64()
+ + _seg_65()
+ + _seg_66()
+ + _seg_67()
+ + _seg_68()
+ + _seg_69()
+ + _seg_70()
+ + _seg_71()
+ + _seg_72()
+ + _seg_73()
+ + _seg_74()
+ + _seg_75()
+ + _seg_76()
+ + _seg_77()
+ + _seg_78()
+ + _seg_79()
+ + _seg_80()
+ + _seg_81()
+) # type: Tuple[Union[Tuple[int, str], Tuple[int, str, str]], ...]
diff --git a/AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/AUTHORS.txt b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/AUTHORS.txt
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/AUTHORS.txt
rename to testcline/lib/python3.12/site-packages/pip-24.0.dist-info/AUTHORS.txt
diff --git a/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/LICENSE.txt b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/LICENSE.txt
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/LICENSE.txt
rename to testcline/lib/python3.12/site-packages/pip-24.0.dist-info/LICENSE.txt
diff --git a/AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/METADATA b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/METADATA
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/METADATA
rename to testcline/lib/python3.12/site-packages/pip-24.0.dist-info/METADATA
diff --git a/AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/RECORD b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/RECORD
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/RECORD
rename to testcline/lib/python3.12/site-packages/pip-24.0.dist-info/RECORD
index feb0f75..90ae0a5 100644
--- a/AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/RECORD
+++ b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/RECORD
@@ -1,6 +1,6 @@
-../../../bin/pip,sha256=Z1AGnr9T70_zK6ps4MVPcyK6vS8wjrvWMq8yPSsp7jI,248
-../../../bin/pip3,sha256=Z1AGnr9T70_zK6ps4MVPcyK6vS8wjrvWMq8yPSsp7jI,248
-../../../bin/pip3.12,sha256=Z1AGnr9T70_zK6ps4MVPcyK6vS8wjrvWMq8yPSsp7jI,248
+../../../bin/pip,sha256=bugCLkmB5v0ochqcVeP5uBb2DRThpsbyL1TCrItDOvc,250
+../../../bin/pip3,sha256=bugCLkmB5v0ochqcVeP5uBb2DRThpsbyL1TCrItDOvc,250
+../../../bin/pip3.12,sha256=bugCLkmB5v0ochqcVeP5uBb2DRThpsbyL1TCrItDOvc,250
pip-24.0.dist-info/AUTHORS.txt,sha256=SwXm4nkwRkmtnO1ZY-dLy7EPeoQNXMNLby5CN3GlNhY,10388
pip-24.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pip-24.0.dist-info/LICENSE.txt,sha256=Y0MApmnUmurmWxLGxIySTFGkzfPR_whtw0VtyLyqIQQ,1093
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__init__.py b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/REQUESTED
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__init__.py
rename to testcline/lib/python3.12/site-packages/pip-24.0.dist-info/REQUESTED
diff --git a/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/WHEEL
new file mode 100644
index 0000000..98c0d20
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.42.0)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/entry_points.txt b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/entry_points.txt
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip-24.0.dist-info/entry_points.txt
rename to testcline/lib/python3.12/site-packages/pip-24.0.dist-info/entry_points.txt
diff --git a/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/top_level.txt
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pip-24.0.dist-info/top_level.txt
@@ -0,0 +1 @@
+pip
diff --git a/AIagent/lib/python3.12/site-packages/pip/__init__.py b/testcline/lib/python3.12/site-packages/pip/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/__main__.py b/testcline/lib/python3.12/site-packages/pip/__main__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/__main__.py
rename to testcline/lib/python3.12/site-packages/pip/__main__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/__pip-runner__.py b/testcline/lib/python3.12/site-packages/pip/__pip-runner__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/__pip-runner__.py
rename to testcline/lib/python3.12/site-packages/pip/__pip-runner__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/__pycache__/__init__.cpython-312.pyc
similarity index 73%
rename from AIagent/lib/python3.12/site-packages/pip/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/__pycache__/__init__.cpython-312.pyc
index 094895b..5df6a33 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/__pycache__/__main__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/__pycache__/__main__.cpython-312.pyc
similarity index 76%
rename from AIagent/lib/python3.12/site-packages/pip/__pycache__/__main__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/__pycache__/__main__.cpython-312.pyc
index 982b9dd..e38e073 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/__pycache__/__main__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/__pycache__/__main__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc
similarity index 81%
rename from AIagent/lib/python3.12/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc
index 98b0d62..dac2678 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc
similarity index 76%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc
index 24dd249..30b4c81 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc
index 055572c..55fd4c3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc
index becf0a0..40a9fa3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc
index 8145f78..2362960 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc
index 1203856..0bbfab8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/main.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/main.cpython-312.pyc
similarity index 61%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/main.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/main.cpython-312.pyc
index 82e87e4..d87805f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/main.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/main.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc
similarity index 86%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc
index 5f46e17..5db0ace 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc
index e0a15be..2b03df0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc
index 08c7cf3..4998ef0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/build_env.py b/testcline/lib/python3.12/site-packages/pip/_internal/build_env.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/build_env.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/build_env.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cache.py b/testcline/lib/python3.12/site-packages/pip/_internal/cache.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cache.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cache.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..35dd603
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc
index 38ec3ea..dc2cb7a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc
index 93b382a..e0a51a3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc
index 77c9d88..4b3b11c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-312.pyc
new file mode 100644
index 0000000..7e6c58a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc
similarity index 88%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc
index b6cdca9..cb6f0cc 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc
index 5fb77f0..408249e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc
index 11124bc..8ab318d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc
index e4ce782..18cc9eb 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc
index ce83655..7624f94 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc
index 25cba9c..df55714 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-312.pyc
new file mode 100644
index 0000000..b654cde
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/autocompletion.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/autocompletion.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/autocompletion.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/autocompletion.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/base_command.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/base_command.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/base_command.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/base_command.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/cmdoptions.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/cmdoptions.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/cmdoptions.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/cmdoptions.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/command_context.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/command_context.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/command_context.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/command_context.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/main.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/main.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/main.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/main.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/main_parser.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/main_parser.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/main_parser.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/main_parser.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/parser.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/parser.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/parser.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/parser.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/req_command.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/req_command.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/req_command.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/req_command.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/spinners.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/spinners.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/spinners.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/spinners.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/cli/status_codes.py b/testcline/lib/python3.12/site-packages/pip/_internal/cli/status_codes.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/cli/status_codes.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/cli/status_codes.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc
similarity index 63%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc
index 5d3e75c..b9d0012 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc
index d07a090..d10e331 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc
similarity index 84%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc
index b839e0b..ed30700 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc
index 571105d..d93d2e2 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc
index 2215caf..d715066 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc
index 6207654..98c521f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc
similarity index 90%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc
index 1d01025..41c30f8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc
index 3b2db08..db868b6 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc
similarity index 90%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc
index 0c9e580..c33bc82 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc
index 733202c..49dcd77 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/index.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/index.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/index.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/index.cpython-312.pyc
index 11f6ae1..15d19a7 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/index.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/index.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc
index b350014..e7f6629 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc
index de45bff..50a4e00 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/list.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/list.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/list.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/list.cpython-312.pyc
index f049f34..83d454f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/list.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/list.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc
index 65ff0c9..a256602 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc
index 7995350..b037d0b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc
index 221b7df..d46925e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-312.pyc
index bb5d1f1..066e596 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/cache.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/cache.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/cache.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/cache.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/check.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/check.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/check.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/check.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/completion.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/completion.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/completion.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/completion.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/configuration.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/configuration.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/configuration.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/configuration.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/debug.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/debug.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/debug.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/debug.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/download.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/download.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/download.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/download.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/freeze.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/freeze.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/freeze.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/freeze.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/hash.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/hash.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/hash.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/hash.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/help.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/help.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/help.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/help.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/index.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/index.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/index.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/index.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/inspect.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/inspect.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/inspect.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/inspect.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/install.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/install.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/install.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/install.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/list.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/list.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/list.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/list.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/search.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/search.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/search.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/search.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/show.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/show.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/show.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/show.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/uninstall.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/uninstall.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/uninstall.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/uninstall.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/commands/wheel.py b/testcline/lib/python3.12/site-packages/pip/_internal/commands/wheel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/commands/wheel.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/commands/wheel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/configuration.py b/testcline/lib/python3.12/site-packages/pip/_internal/configuration.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/configuration.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/configuration.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/distributions/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/distributions/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/distributions/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..e829b94
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc
similarity index 86%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc
index f25f530..7f936be 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-312.pyc
new file mode 100644
index 0000000..d5e9fb7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc
similarity index 85%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc
index 166fdef..9404b2f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc
similarity index 70%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc
index ab810eb..dd44dd8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/distributions/base.py b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/base.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/distributions/base.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/distributions/base.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/distributions/installed.py b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/installed.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/distributions/installed.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/distributions/installed.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/distributions/sdist.py b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/sdist.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/distributions/sdist.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/distributions/sdist.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/distributions/wheel.py b/testcline/lib/python3.12/site-packages/pip/_internal/distributions/wheel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/distributions/wheel.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/distributions/wheel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/exceptions.py b/testcline/lib/python3.12/site-packages/pip/_internal/exceptions.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/exceptions.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/exceptions.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/index/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/index/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/index/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/index/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..4858389
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc
index 39aba50..7c26fbe 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc
index f2dfbda..4a293bf 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc
index 4bcf2c1..1f8b7ae 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/index/collector.py b/testcline/lib/python3.12/site-packages/pip/_internal/index/collector.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/index/collector.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/index/collector.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/index/package_finder.py b/testcline/lib/python3.12/site-packages/pip/_internal/index/package_finder.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/index/package_finder.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/index/package_finder.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/index/sources.py b/testcline/lib/python3.12/site-packages/pip/_internal/index/sources.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/index/sources.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/index/sources.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/locations/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/locations/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/locations/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc
index 78830ee..f37d809 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc
similarity index 90%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc
index cd7fe77..0b5cd6e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc
index a2524b8..460c59b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc
index c589876..c465577 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/_distutils.py b/testcline/lib/python3.12/site-packages/pip/_internal/locations/_distutils.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/locations/_distutils.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/locations/_distutils.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/_sysconfig.py b/testcline/lib/python3.12/site-packages/pip/_internal/locations/_sysconfig.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/locations/_sysconfig.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/locations/_sysconfig.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/locations/base.py b/testcline/lib/python3.12/site-packages/pip/_internal/locations/base.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/locations/base.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/locations/base.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/main.py b/testcline/lib/python3.12/site-packages/pip/_internal/main.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/main.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/main.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc
index 3995eca..a2ead4a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc
similarity index 86%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc
index 0883b96..99e7422 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc
index 33949bf..c616367 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc
index 2b655dc..e767d29 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/_json.py b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/_json.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/_json.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/_json.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/base.py b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/base.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/base.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/base.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..0e79e4b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc
index a23b58e..68059a6 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc
index 2603908..5604568 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc
index 2271844..5b7f3f6 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_compat.py b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_compat.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_compat.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_compat.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_dists.py b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_dists.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_dists.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_dists.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/metadata/pkg_resources.py b/testcline/lib/python3.12/site-packages/pip/_internal/metadata/pkg_resources.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/metadata/pkg_resources.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/metadata/pkg_resources.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..0e5d1e8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc
similarity index 83%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc
index 95104ad..842464e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc
index 067f707..6f2da38 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc
index 43e2e74..04ecbfa 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc
similarity index 82%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc
index bd01d8e..94adc15 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc
index 7a44823..9df547d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc
index ca06fa2..f7845ab 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc
similarity index 73%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc
index c5346a1..e5b4daa 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc
index 7fce973..42874c3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc
similarity index 82%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc
index a80e07b..f1ae8c1 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc
index c0a5f97..b5d55c0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc
index 795aef3..3adf810 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/candidate.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/candidate.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/candidate.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/candidate.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/direct_url.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/direct_url.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/direct_url.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/direct_url.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/format_control.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/format_control.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/format_control.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/format_control.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/index.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/index.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/index.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/index.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/installation_report.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/installation_report.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/installation_report.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/installation_report.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/link.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/link.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/link.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/link.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/scheme.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/scheme.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/scheme.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/scheme.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/search_scope.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/search_scope.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/search_scope.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/search_scope.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/selection_prefs.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/selection_prefs.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/selection_prefs.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/selection_prefs.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/target_python.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/target_python.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/target_python.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/target_python.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/models/wheel.py b/testcline/lib/python3.12/site-packages/pip/_internal/models/wheel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/models/wheel.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/models/wheel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/network/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..34a9ee4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc
index fff9b92..2ecc375 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc
index b3feaf6..13508a0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc
index b87e465..e43c56b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc
index baf1006..bdc4f88 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc
index f49a5ee..69d4c1e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc
similarity index 90%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc
index a3bd185..927812a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc
similarity index 88%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc
index 851b5cd..51a2e86 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/auth.py b/testcline/lib/python3.12/site-packages/pip/_internal/network/auth.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/auth.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/auth.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/cache.py b/testcline/lib/python3.12/site-packages/pip/_internal/network/cache.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/cache.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/cache.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/download.py b/testcline/lib/python3.12/site-packages/pip/_internal/network/download.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/download.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/download.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/lazy_wheel.py b/testcline/lib/python3.12/site-packages/pip/_internal/network/lazy_wheel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/lazy_wheel.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/lazy_wheel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/session.py b/testcline/lib/python3.12/site-packages/pip/_internal/network/session.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/session.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/session.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/utils.py b/testcline/lib/python3.12/site-packages/pip/_internal/network/utils.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/utils.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/utils.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/network/xmlrpc.py b/testcline/lib/python3.12/site-packages/pip/_internal/network/xmlrpc.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/network/xmlrpc.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/network/xmlrpc.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..c0effbd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc
index 2144a85..21e12f3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-312.pyc
index bf43eb0..bf3e2ab 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc
index 3dbcd40..a57f0b8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..9b5cb28
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc
index f8c626e..02a5f07 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc
similarity index 61%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc
index 36cf3f1..61b2ff2 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc
similarity index 84%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc
index 2e7e557..53cb05b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc
index 56a94e7..a49762a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc
similarity index 83%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc
index b9b1f2b..ca0159e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc
similarity index 85%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc
index b931c24..c048351 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc
index 5ac4136..780962e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/build_tracker.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/build_tracker.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/build_tracker.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/build_tracker.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/metadata.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/metadata.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/metadata.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/metadata.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_editable.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_editable.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_editable.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_editable.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_legacy.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_legacy.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_legacy.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_legacy.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/wheel.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/wheel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/wheel.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/wheel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_editable.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_editable.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_editable.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_editable.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_legacy.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_legacy.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_legacy.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_legacy.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/check.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/check.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/check.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/check.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/freeze.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/freeze.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/freeze.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/freeze.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/install/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/install/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..90e7645
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc
similarity index 84%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc
index 84f4d11..3c108de 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc
index f1e1e1e..d30c6bc 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/editable_legacy.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/install/editable_legacy.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/editable_legacy.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/install/editable_legacy.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/wheel.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/install/wheel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/install/wheel.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/install/wheel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/operations/prepare.py b/testcline/lib/python3.12/site-packages/pip/_internal/operations/prepare.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/operations/prepare.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/operations/prepare.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/pyproject.py b/testcline/lib/python3.12/site-packages/pip/_internal/pyproject.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/pyproject.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/pyproject.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/req/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc
index 62ae48c..96824f7 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc
index d6289f6..2c6031f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc
index 986d504..bdf7f06 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc
index 08e8a56..34d1f6b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc
index 38edfd1..aedba2c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc
index bc64300..ae15334 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/constructors.py b/testcline/lib/python3.12/site-packages/pip/_internal/req/constructors.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/constructors.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/constructors.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/req_file.py b/testcline/lib/python3.12/site-packages/pip/_internal/req/req_file.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/req_file.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/req_file.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/req_install.py b/testcline/lib/python3.12/site-packages/pip/_internal/req/req_install.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/req_install.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/req_install.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/req_set.py b/testcline/lib/python3.12/site-packages/pip/_internal/req/req_set.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/req_set.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/req_set.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/req/req_uninstall.py b/testcline/lib/python3.12/site-packages/pip/_internal/req/req_uninstall.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/req/req_uninstall.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/req/req_uninstall.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..e34282a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc
similarity index 64%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc
index 3fd5847..2437a4b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/base.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/base.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/base.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/base.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..cf1df01
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc
index a1e5db5..fe92eb6 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/legacy/resolver.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/legacy/resolver.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/legacy/resolver.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/legacy/resolver.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..974ab7a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc
index fec992a..5728a2c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc
index 1d96bb0..e07ef17 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc
index 17c6890..9648c1f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc
index 6534644..ca791fa 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc
index feaa870..4b8c226 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc
index 604511d..a654447 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc
similarity index 86%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc
index 2c7da21..f8fa6f0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc
index 20033c6..31fc5fb 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/base.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/base.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/base.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/base.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/provider.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/provider.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/provider.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/provider.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/reporter.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/reporter.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/reporter.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/reporter.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/requirements.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/requirements.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/requirements.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/requirements.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/resolver.py b/testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/resolver.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/resolver.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/resolver.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/self_outdated_check.py b/testcline/lib/python3.12/site-packages/pip/_internal/self_outdated_check.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/self_outdated_check.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/self_outdated_check.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..5dcd2f8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc
index 8934584..757b8db 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc
similarity index 86%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc
index 4d6f9c3..773daff 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc
index 9982d7b..aa1f25c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc
similarity index 79%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc
index f611a03..0534407 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc
index 9a50967..e24a269 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-312.pyc
new file mode 100644
index 0000000..3110fe1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc
similarity index 86%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc
index cab44ef..2e0109b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc
index 6370e71..686aeb7 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc
similarity index 82%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc
index 6883dab..a38bffb 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-312.pyc
index bd9275a..6bac8d4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc
index b3d1175..3745e55 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc
index e3ff2bd..2618434 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc
similarity index 79%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc
index 69c1d97..1f22a6e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc
index 510235c..8e34355 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc
index d34ad60..45e5ddb 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc
index 90bd4e7..17d80b5 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc
index 2eb65c5..8ed044e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/models.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/models.cpython-312.pyc
new file mode 100644
index 0000000..16baae2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/models.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc
similarity index 86%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc
index 6328bb1..eb5d9c5 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc
similarity index 68%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc
index cfc46f8..77edf49 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc
index ae158c7..bf2164b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc
index d7718a0..14434df 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc
index 925e21e..0e9e6f0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc
index f947211..17c3c7c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc
index 38bd5e0..a5ebe2c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc
similarity index 85%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc
index 89ffabd..265abdd 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/_jaraco_text.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/_jaraco_text.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/_jaraco_text.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/_jaraco_text.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/_log.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/_log.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/_log.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/_log.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/appdirs.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/appdirs.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/appdirs.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/appdirs.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/compat.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/compat.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/compat.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/compat.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/compatibility_tags.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/compatibility_tags.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/compatibility_tags.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/compatibility_tags.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/datetime.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/datetime.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/datetime.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/datetime.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/deprecation.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/deprecation.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/deprecation.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/deprecation.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/direct_url_helpers.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/direct_url_helpers.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/direct_url_helpers.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/direct_url_helpers.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/egg_link.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/egg_link.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/egg_link.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/egg_link.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/encoding.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/encoding.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/encoding.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/encoding.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/entrypoints.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/entrypoints.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/entrypoints.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/entrypoints.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/filesystem.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/filesystem.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/filesystem.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/filesystem.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/filetypes.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/filetypes.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/filetypes.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/filetypes.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/glibc.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/glibc.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/glibc.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/glibc.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/hashes.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/hashes.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/hashes.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/hashes.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/logging.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/logging.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/logging.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/logging.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/misc.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/misc.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/misc.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/misc.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/models.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/models.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/models.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/models.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/packaging.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/packaging.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/packaging.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/packaging.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/setuptools_build.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/setuptools_build.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/setuptools_build.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/setuptools_build.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/subprocess.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/subprocess.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/subprocess.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/subprocess.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/temp_dir.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/temp_dir.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/temp_dir.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/temp_dir.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/unpacking.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/unpacking.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/unpacking.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/unpacking.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/urls.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/urls.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/urls.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/urls.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/virtualenv.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/virtualenv.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/virtualenv.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/virtualenv.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/utils/wheel.py b/testcline/lib/python3.12/site-packages/pip/_internal/utils/wheel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/utils/wheel.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/utils/wheel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__init__.py b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc
similarity index 60%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc
index c2199e3..ae8e1eb 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc
index 92b1afc..f07313c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc
index 9b15ebc..17c7cbe 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc
index 924a20c..b4fbe9d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc
index 159f7f0..efeb41c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc
index e59ff0f..c1377bc 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/bazaar.py b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/bazaar.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/bazaar.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/bazaar.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/git.py b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/git.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/git.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/git.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/mercurial.py b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/mercurial.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/mercurial.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/mercurial.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/subversion.py b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/subversion.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/subversion.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/subversion.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/vcs/versioncontrol.py b/testcline/lib/python3.12/site-packages/pip/_internal/vcs/versioncontrol.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/vcs/versioncontrol.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/vcs/versioncontrol.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_internal/wheel_builder.py b/testcline/lib/python3.12/site-packages/pip/_internal/wheel_builder.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_internal/wheel_builder.py
rename to testcline/lib/python3.12/site-packages/pip/_internal/wheel_builder.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc
index fe96800..39f095e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/__pycache__/six.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/__pycache__/six.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/__pycache__/six.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/__pycache__/six.cpython-312.pyc
index 831b98f..d2cc4a1 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/__pycache__/six.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/__pycache__/six.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc
index e3dbec6..56d2334 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc
similarity index 74%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc
index 4518990..4eb413a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc
index 955c18e..dcd9907 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc
index c23eb99..179fb23 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc
similarity index 79%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc
index c886586..8cee84a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc
index bf6bac1..e628213 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc
index 90dee85..1e9cc54 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc
index f6a2fef..a3c342e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc
index 56513e2..fb25462 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc
similarity index 65%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc
index 1dad301..5444747 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/_cmd.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/_cmd.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/_cmd.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/_cmd.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/adapter.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/adapter.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/adapter.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/adapter.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/cache.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/cache.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/cache.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/cache.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..1ba36a6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc
index f5287fe..2a2eadc 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc
similarity index 78%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc
index 54cf3f9..61e6c7c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/controller.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/controller.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/controller.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/controller.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/filewrapper.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/filewrapper.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/filewrapper.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/filewrapper.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/heuristics.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/heuristics.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/heuristics.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/heuristics.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/serialize.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/serialize.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/serialize.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/serialize.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/wrapper.py b/testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/wrapper.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/cachecontrol/wrapper.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/cachecontrol/wrapper.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/__main__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__main__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/__main__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__main__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..fb5b289
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc
similarity index 52%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc
index 39ee5c0..b54f72d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc
similarity index 90%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc
index 6c1fc3f..22231e0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/cacert.pem b/testcline/lib/python3.12/site-packages/pip/_vendor/certifi/cacert.pem
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/cacert.pem
rename to testcline/lib/python3.12/site-packages/pip/_vendor/certifi/cacert.pem
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/core.py b/testcline/lib/python3.12/site-packages/pip/_vendor/certifi/core.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/certifi/core.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/certifi/core.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-312.pyc
similarity index 71%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-312.pyc
index 9f2df4b..ef5983d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-312.pyc
index aff2399..5d3e1f9 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-312.pyc
similarity index 80%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-312.pyc
index f3248e2..41656a2 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-312.pyc
index a1873d5..faf5e73 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-312.pyc
similarity index 56%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-312.pyc
index f3c74bc..bb58824 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-312.pyc
similarity index 73%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-312.pyc
index be23244..be4caf0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-312.pyc
index a1a74c9..7635ba9 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachinedict.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachinedict.cpython-312.pyc
similarity index 76%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachinedict.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachinedict.cpython-312.pyc
index de15656..dad8369 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachinedict.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachinedict.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-312.pyc
similarity index 80%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-312.pyc
index 6947927..dc41b7c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-312.pyc
index 8decbcb..65a2baf 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-312.pyc
index e56a122..eec5e95 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-312.pyc
index f38c0be..b0744bc 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-312.pyc
index 909edd6..ce0b5ec 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-312.pyc
index 3f2785e..a779aea 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-312.pyc
similarity index 80%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-312.pyc
index 4e2fdf4..20b7bb8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-312.pyc
index 04f9051..e5be1a4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-312.pyc
similarity index 80%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-312.pyc
index f317694..070a741 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-312.pyc
index 9b570ad..bba7142 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-312.pyc
similarity index 80%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-312.pyc
index 07fe37c..6cb10e0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-312.pyc
index 26a0e50..0a2ebf3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-312.pyc
index 620c180..7a3c769 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabfreq.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabfreq.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabfreq.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabfreq.cpython-312.pyc
index be5080f..ef8d288 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabfreq.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabfreq.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabprober.cpython-312.pyc
similarity index 80%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabprober.cpython-312.pyc
index 21ec74a..1fdd31c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-312.pyc
index 0daa4e5..c3a38b5 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-312.pyc
index 4567341..c20659c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-312.pyc
index bc36323..4d9c63a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-312.pyc
index 39533f6..ba60eb5 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-312.pyc
index 9881062..4a6d101 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-312.pyc
index 1143907..58ac7f2 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-312.pyc
index 1807bae..2d0e9d6 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-312.pyc
index 6b969be..f2c8ec7 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-312.pyc
index dc44f5f..2767c57 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/macromanprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/macromanprober.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/macromanprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/macromanprober.cpython-312.pyc
index 3b8a1a1..5351a8a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/macromanprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/macromanprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-312.pyc
similarity index 76%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-312.pyc
index a31fa83..0c7d159 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-312.pyc
similarity index 81%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-312.pyc
index 6cb5e9c..642c447 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-312.pyc
index 93b0e4a..8eaa294 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/resultdict.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/resultdict.cpython-312.pyc
similarity index 72%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/resultdict.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/resultdict.cpython-312.pyc
index 5f72599..813e9f8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/resultdict.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/resultdict.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-312.pyc
index dc6a7a5..48a9ee4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-312.pyc
index 51ddf45..8d955c7 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-312.pyc
index 9909feb..c2fee81 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-312.pyc
index e9d8732..01e78d8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf1632prober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf1632prober.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf1632prober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf1632prober.cpython-312.pyc
index 29ae61c..8332d2d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf1632prober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf1632prober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-312.pyc
index 4f2bf62..4d80348 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-312.pyc
similarity index 53%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-312.pyc
index ec20231..a0f0c42 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/big5freq.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/big5freq.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/big5freq.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/big5freq.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/big5prober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/big5prober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/big5prober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/big5prober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/chardistribution.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/chardistribution.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/chardistribution.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/chardistribution.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/charsetgroupprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/charsetgroupprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/charsetgroupprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/charsetgroupprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/charsetprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/charsetprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/charsetprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/charsetprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..ed8df70
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-312.pyc
index b9f017d..d50e119 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/cli/chardetect.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cli/chardetect.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/cli/chardetect.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cli/chardetect.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/codingstatemachine.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/codingstatemachine.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/codingstatemachine.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/codingstatemachine.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/codingstatemachinedict.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/codingstatemachinedict.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/codingstatemachinedict.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/codingstatemachinedict.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/cp949prober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cp949prober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/cp949prober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/cp949prober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/enums.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/enums.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/enums.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/enums.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/escprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/escprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/escprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/escprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/escsm.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/escsm.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/escsm.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/escsm.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/eucjpprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/eucjpprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/eucjpprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/eucjpprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/euckrfreq.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/euckrfreq.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/euckrfreq.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/euckrfreq.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/euckrprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/euckrprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/euckrprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/euckrprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/euctwfreq.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/euctwfreq.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/euctwfreq.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/euctwfreq.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/euctwprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/euctwprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/euctwprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/euctwprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/gb2312freq.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/gb2312freq.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/gb2312freq.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/gb2312freq.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/gb2312prober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/gb2312prober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/gb2312prober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/gb2312prober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/hebrewprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/hebrewprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/hebrewprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/hebrewprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/jisfreq.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/jisfreq.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/jisfreq.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/jisfreq.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/johabfreq.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/johabfreq.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/johabfreq.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/johabfreq.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/johabprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/johabprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/johabprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/johabprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/jpcntx.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/jpcntx.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/jpcntx.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/jpcntx.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langbulgarianmodel.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langbulgarianmodel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langbulgarianmodel.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langbulgarianmodel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langgreekmodel.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langgreekmodel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langgreekmodel.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langgreekmodel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langhebrewmodel.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langhebrewmodel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langhebrewmodel.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langhebrewmodel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langhungarianmodel.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langhungarianmodel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langhungarianmodel.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langhungarianmodel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langrussianmodel.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langrussianmodel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langrussianmodel.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langrussianmodel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langthaimodel.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langthaimodel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langthaimodel.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langthaimodel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langturkishmodel.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langturkishmodel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/langturkishmodel.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/langturkishmodel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/latin1prober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/latin1prober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/latin1prober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/latin1prober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/macromanprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/macromanprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/macromanprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/macromanprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/mbcharsetprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/mbcharsetprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/mbcharsetprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/mbcharsetprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/mbcsgroupprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/mbcsgroupprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/mbcsgroupprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/mbcsgroupprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/mbcssm.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/mbcssm.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/mbcssm.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/mbcssm.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..ede3905
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-312.pyc
index 4a078c1..63dcd55 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/languages.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/languages.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/languages.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/languages.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/resultdict.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/resultdict.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/resultdict.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/resultdict.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/sbcharsetprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/sbcharsetprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/sbcharsetprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/sbcharsetprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/sbcsgroupprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/sbcsgroupprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/sbcsgroupprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/sbcsgroupprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/sjisprober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/sjisprober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/sjisprober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/sjisprober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/universaldetector.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/universaldetector.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/universaldetector.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/universaldetector.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/utf1632prober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/utf1632prober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/utf1632prober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/utf1632prober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/utf8prober.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/utf8prober.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/utf8prober.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/utf8prober.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/version.py b/testcline/lib/python3.12/site-packages/pip/_vendor/chardet/version.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/chardet/version.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/chardet/version.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-312.pyc
similarity index 58%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-312.pyc
index 5a9c1aa..4517c32 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-312.pyc
index a3d63df..89a2de1 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-312.pyc
index f0d7eb6..cc620b1 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-312.pyc
similarity index 81%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-312.pyc
index c7c2008..16c9074 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-312.pyc
index 1da509a..a93f8c4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-312.pyc
index f526a75..dbbfcf3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/ansi.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/ansi.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/ansi.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/ansi.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/ansitowin32.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/ansitowin32.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/ansitowin32.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/ansitowin32.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/initialise.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/initialise.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/initialise.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/initialise.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..04dc733
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansi_test.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansi_test.cpython-312.pyc
similarity index 90%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansi_test.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansi_test.cpython-312.pyc
index d936704..c121c14 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansi_test.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansi_test.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc
index dea72d8..849f146 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/initialise_test.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/initialise_test.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/initialise_test.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/initialise_test.cpython-312.pyc
index 21e77ca..d719afa 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/initialise_test.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/initialise_test.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/isatty_test.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/isatty_test.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/isatty_test.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/isatty_test.cpython-312.pyc
index f775951..fe22437 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/isatty_test.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/isatty_test.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/utils.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/utils.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/utils.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/utils.cpython-312.pyc
index 090f9bb..3c01faa 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/utils.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/utils.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/winterm_test.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/winterm_test.cpython-312.pyc
similarity index 83%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/winterm_test.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/winterm_test.cpython-312.pyc
index 0f77708..41b86c4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/winterm_test.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/winterm_test.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/ansi_test.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/ansi_test.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/ansi_test.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/ansi_test.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/ansitowin32_test.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/ansitowin32_test.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/ansitowin32_test.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/ansitowin32_test.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/initialise_test.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/initialise_test.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/initialise_test.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/initialise_test.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/isatty_test.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/isatty_test.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/isatty_test.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/isatty_test.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/utils.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/utils.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/utils.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/utils.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/winterm_test.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/winterm_test.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/tests/winterm_test.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/tests/winterm_test.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/win32.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/win32.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/win32.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/win32.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/winterm.py b/testcline/lib/python3.12/site-packages/pip/_vendor/colorama/winterm.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/colorama/winterm.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/colorama/winterm.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc
similarity index 71%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc
index 4ad1bc3..e0ad87a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc
index 8257c48..5fec762 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc
index fcf737b..b688be9 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc
index be657ca..2554f27 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc
index 1c5662d..9b03024 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc
index b1d1413..1bf8939 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc
index 9e11909..be7c1ef 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc
index aab09bc..f59bf10 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc
index 2bacbb4..aaaaedf 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc
index d1a1db4..f82867b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc
index 948c6c3..6239e18 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc
index 406f6a1..6aa63e3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc
index 1014f02..3baf550 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/compat.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/compat.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/compat.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/compat.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/database.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/database.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/database.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/database.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/index.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/index.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/index.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/index.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/locators.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/locators.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/locators.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/locators.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/manifest.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/manifest.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/manifest.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/manifest.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/markers.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/markers.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/markers.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/markers.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/metadata.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/metadata.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/metadata.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/metadata.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/resources.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/resources.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/resources.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/resources.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/scripts.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/scripts.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/scripts.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/scripts.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/util.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/util.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/util.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/util.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/version.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/version.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/version.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/version.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/wheel.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distlib/wheel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distlib/wheel.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distlib/wheel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distro/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distro/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distro/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distro/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distro/__main__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distro/__main__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distro/__main__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distro/__main__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc
similarity index 71%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc
index 6879ea8..1f8c0df 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc
new file mode 100644
index 0000000..8fd262d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc
index 1b94bda..478f441 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/distro/distro.py b/testcline/lib/python3.12/site-packages/pip/_vendor/distro/distro.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/distro/distro.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/distro/distro.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc
similarity index 70%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc
index a04af86..9dec9ee 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-312.pyc
index b03b2af..9b4fbf1 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-312.pyc
similarity index 65%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-312.pyc
index b0352c8..adf7ecf 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc
index 030a996..7e0c2af 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc
index 89f6d2f..d1b4f93 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc
similarity index 85%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc
index 08562da..0ac52f1 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-312.pyc
new file mode 100644
index 0000000..c612868
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc
index 3d662a8..29ae200 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/codec.py b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/codec.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/codec.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/codec.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/compat.py b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/compat.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/compat.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/compat.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/core.py b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/core.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/core.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/core.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/idnadata.py b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/idnadata.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/idnadata.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/idnadata.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/intranges.py b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/intranges.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/intranges.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/intranges.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/package_data.py b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/package_data.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/package_data.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/package_data.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/idna/uts46data.py b/testcline/lib/python3.12/site-packages/pip/_vendor/idna/uts46data.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/idna/uts46data.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/idna/uts46data.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc
similarity index 86%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc
index ab8d904..494b8b0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc
similarity index 88%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc
index c1b54d3..6a8e2fa 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc
index 329ac0f..54559e7 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc
index 4d3e102..30e9350 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/exceptions.py b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/exceptions.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/exceptions.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/exceptions.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/ext.py b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/ext.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/ext.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/ext.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/fallback.py b/testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/fallback.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/msgpack/fallback.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/msgpack/fallback.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__about__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__about__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__about__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__about__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-312.pyc
similarity index 62%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-312.pyc
index 422fdda..3880e34 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc
similarity index 54%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc
index 2465865..f38cb33 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc
index 3e6e9f6..18cb992 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc
index f96c58c..eb48705 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc
index f7e139a..8641f53 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc
index 40d94a2..dd8bc5c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc
index 30a2e14..5bd6f59 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc
index b64e845..3df8b3c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc
index 1dd680a..8c21856 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc
index 68ac3ff..a791f39 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc
index e19dfc5..23db4e0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/_manylinux.py b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/_manylinux.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/_manylinux.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/_manylinux.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/_musllinux.py b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/_musllinux.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/_musllinux.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/_musllinux.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/_structures.py b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/_structures.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/_structures.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/_structures.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/markers.py b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/markers.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/markers.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/markers.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/requirements.py b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/requirements.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/requirements.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/requirements.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/specifiers.py b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/specifiers.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/specifiers.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/specifiers.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/tags.py b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/tags.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/tags.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/tags.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/utils.py b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/utils.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/utils.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/utils.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/version.py b/testcline/lib/python3.12/site-packages/pip/_vendor/packaging/version.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/packaging/version.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/packaging/version.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc
index d472805..1b8d4a2 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__main__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__main__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__main__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__main__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc
index 8e54cd7..be19f66 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc
index 6f8838c..74e5ef4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc
index 0f64792..1bdb12e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc
index eb0aba7..12b5e61 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc
index 760aaed..e598068 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc
index 1cd5c33..0983ebd 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc
new file mode 100644
index 0000000..56fdb09
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc
similarity index 83%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc
index 57925a8..6f726ff 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/android.py b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/android.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/android.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/android.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/api.py b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/api.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/api.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/api.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/macos.py b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/macos.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/macos.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/macos.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/unix.py b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/unix.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/unix.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/unix.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/version.py b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/version.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/version.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/version.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/windows.py b/testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/windows.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/platformdirs/windows.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/platformdirs/windows.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__main__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__main__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__main__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__main__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc
index de0f09b..aa4e9ad 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc
similarity index 56%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc
index 663c4f7..8e0c610 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc
index 0b75f2c..2ca2efc 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-312.pyc
similarity index 67%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-312.pyc
index 4ed42e8..27f8d97 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc
index 972c033..3c73ab8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc
index 5144b4c..5398dc5 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc
index 205d334..26e6a37 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc
similarity index 79%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc
index 2b3750c..9005695 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc
similarity index 83%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc
index 501e903..f0c37ff 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc
index cafb41c..3c4e765 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc
index e2c055e..e4e3e3e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc
index e938670..7690e8e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc
index 983df48..75137f0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc
index 458a830..1999f8e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc
index e8e89cf..e9233c5 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc
index d1327d3..1e806e3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/cmdline.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/cmdline.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/cmdline.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/cmdline.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/console.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/console.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/console.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/console.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/filter.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/filter.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/filter.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/filter.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc
index c4e94dd..53b3cab 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatter.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatter.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatter.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatter.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc
index e711381..848b130 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc
index f220763..626d210 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc
index 68a5342..f77ebc4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc
index 833a58a..06f404d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc
index ef3407e..a4479c3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc
index 490e60f..f3415cc 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc
index 405ceb0..34edb7e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc
index 9e2a6b5..1929485 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc
index 8ec6dd3..302147f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc
index fd9bab9..a9055a8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc
similarity index 83%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc
index 518eba4..757279c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc
index dc85268..52de999 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc
index 72e45ec..4a74564 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc
index 00f5a61..3c64fad 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/_mapping.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/_mapping.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/_mapping.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/_mapping.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/bbcode.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/bbcode.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/bbcode.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/bbcode.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/groff.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/groff.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/groff.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/groff.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/html.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/html.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/html.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/html.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/img.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/img.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/img.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/img.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/irc.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/irc.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/irc.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/irc.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/latex.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/latex.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/latex.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/latex.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/other.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/other.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/other.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/other.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/rtf.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/rtf.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/rtf.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/rtf.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/svg.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/svg.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/svg.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/svg.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal256.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal256.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal256.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal256.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexer.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexer.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexer.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexer.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc
index 9e34ccb..effc0cb 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc
index b2831c1..e111db9 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc
index fa81f9c..b80374e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/_mapping.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/_mapping.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/_mapping.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/_mapping.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/python.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/python.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/python.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/python.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/modeline.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/modeline.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/modeline.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/modeline.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/plugin.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/plugin.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/plugin.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/plugin.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/regexopt.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/regexopt.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/regexopt.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/regexopt.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/scanner.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/scanner.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/scanner.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/scanner.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/sphinxext.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/sphinxext.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/sphinxext.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/sphinxext.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/style.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/style.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/style.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/style.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc
index 7aae829..f03b367 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/token.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/token.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/token.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/token.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/unistring.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/unistring.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/unistring.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/unistring.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/util.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pygments/util.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pygments/util.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pygments/util.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-312.pyc
index 81f2113..e116ee0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-312.pyc
index d769363..7cf1af6 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-312.pyc
index 0d0eaf5..ad97410 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-312.pyc
index 1d598b0..231a315 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-312.pyc
index 1af90ce..133f6d3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-312.pyc
index c6232ee..020c4b7 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-312.pyc
index 4515a0c..8de4d7f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-312.pyc
index cad0d71..32bcbdd 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-312.pyc
index 1a9821b..8fd174d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-312.pyc
index 59cdc76..22c5c9d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/actions.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/actions.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/actions.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/actions.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/common.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/common.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/common.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/common.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/core.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/core.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/core.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/core.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-312.pyc
index c4343c7..920a8ff 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/exceptions.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/exceptions.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/exceptions.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/exceptions.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/helpers.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/helpers.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/helpers.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/helpers.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/results.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/results.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/results.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/results.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/testing.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/testing.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/testing.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/testing.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/unicode.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/unicode.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/unicode.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/unicode.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/util.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/util.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyparsing/util.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyparsing/util.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc
similarity index 57%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc
index ab9789a..5314857 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc
new file mode 100644
index 0000000..0ae4c7e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc
index aa5631d..c084134 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_compat.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_compat.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_compat.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_compat.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc
similarity index 61%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc
index 1cf1de1..b3842e4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc
index 5f3caa1..ae7c8c1 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py b/testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc
similarity index 83%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc
index 574e128..1d6f26b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc
similarity index 65%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc
index c240c92..46e46d6 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc
new file mode 100644
index 0000000..52a87fa
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc
index 0d410ec..36b23ae 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc
index d510f11..6cea3e7 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc
index f6607af..0bb677d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc
similarity index 68%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc
index a825edf..2061ff0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc
similarity index 82%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc
index d54b49e..8649e01 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc
index f16fbf1..0b5a404 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc
index b59f422..7d404c1 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc
index 4181539..5973835 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc
new file mode 100644
index 0000000..8662935
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc
index 666fae3..55deef8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc
similarity index 70%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc
index a7523bf..44818b0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc
index 42ea1bc..1cc2f64 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc
index 52f5afc..2792e1f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc
index 9e8735c..7320ce4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc
index 7f07076..964bc2f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__version__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/__version__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__version__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/__version__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/_internal_utils.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/_internal_utils.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/_internal_utils.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/_internal_utils.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/adapters.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/adapters.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/adapters.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/adapters.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/api.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/api.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/api.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/api.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/auth.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/auth.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/auth.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/auth.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/certs.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/certs.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/certs.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/certs.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/compat.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/compat.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/compat.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/compat.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/cookies.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/cookies.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/cookies.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/cookies.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/exceptions.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/exceptions.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/exceptions.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/exceptions.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/help.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/help.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/help.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/help.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/hooks.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/hooks.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/hooks.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/hooks.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/models.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/models.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/models.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/models.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/packages.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/packages.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/packages.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/packages.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/sessions.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/sessions.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/sessions.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/sessions.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/status_codes.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/status_codes.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/status_codes.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/status_codes.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/structures.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/structures.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/structures.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/structures.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/utils.py b/testcline/lib/python3.12/site-packages/pip/_vendor/requests/utils.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/utils.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/requests/utils.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc
similarity index 60%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc
index 25e4eaa..db73c47 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc
index 917075a..7d3830f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc
index baed0a9..396ca1c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc
index 2855a1b..c777191 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc
index 0189eb2..cb5d408 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..2193fc5
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc
new file mode 100644
index 0000000..ae7ccab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/providers.py b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/providers.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/providers.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/providers.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/reporters.py b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/reporters.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/reporters.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/reporters.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/structs.py b/testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/structs.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/resolvelib/structs.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/resolvelib/structs.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__main__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__main__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__main__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__main__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc
index 1ce100e..8602d0e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc
index 4693f52..29e8462 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc
index 2da5436..4a55d37 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc
index 28982a6..efe2685 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc
index e259f85..dd4e878 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc
index e1fc562..8f128bf 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc
new file mode 100644
index 0000000..0def186
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc
similarity index 74%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc
index 9ed2272..c2d5e52 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc
index d4c9747..0a4c88f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc
index 8b0cc5f..da63b5f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc
index ad1b464..3242a54 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc
similarity index 60%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc
index 098b1b0..5053384 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc
index 5767914..8f89633 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc
similarity index 68%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc
index ef0d00b..3a377da 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc
index 4e1ab6a..eb59f6e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc
index 87df75c..17a1c5d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc
similarity index 60%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc
index 63bd14c..5d41b9c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc
similarity index 77%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc
index 0dc4aac..9b5a7e9 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc
index 679ab3b..c529a1c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc
similarity index 70%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc
index b478436..dccb7c0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc
similarity index 75%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc
index 5c1554c..0cca2c2 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc
index 5006de3..9043b17 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc
similarity index 82%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc
index b50d99d..174015c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc
index 3ba3b03..8f0d332 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc
index 2a36de1..c0252d4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc
index 4da74e1..c5df372 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc
index 9ecfc25..e0fe5df 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc
index 9a9a022..15798b1 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc
index 9f603f2..0a6e2a2 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc
similarity index 77%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc
index 0b2c358..f372fa6 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc
index 9c87adf..17c96ed 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc
index 128a952..6e29847 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc
similarity index 88%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc
index d0a3efd..d429816 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc
similarity index 86%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc
index 717ace2..bf005ef 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc
similarity index 82%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc
index 88eafe0..5ec504d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc
index b54da36..a211a6d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc
index 3cdcef7..ed3cde6 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc
index 8022333..53f3c98 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc
similarity index 88%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc
index b612f82..0240e6b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc
similarity index 78%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc
index 49d2563..33bfbd9 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc
similarity index 74%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc
index 1d1f335..6ea1315 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc
index 7003500..2133bbb 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc
index 4493173..2d2dc5b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc
similarity index 88%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc
index 454c77b..6203b12 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc
index 1cb09c9..e456e75 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc
index 2ec3b5e..1100ffa 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc
index 91822d5..9479882 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc
index a7e4f09..59592ea 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc
index 18bc24d..bcf0f8d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc
index 063f811..2602a18 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc
index 9ed3ce0..f749883 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc
index a5a605e..2bb8919 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc
index e0fa3c0..b88fd0c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc
index e656126..c7f2e93 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc
index 368cb87..bb8ade8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc
index dccf650..4f71b4f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc
index 15d10fb..9533258 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc
index aa7a6d3..5e50a23 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc
similarity index 88%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc
index 6b83a00..2b79353 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc
similarity index 57%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc
index 87c2feb..8c5ad0d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc
similarity index 78%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc
index 56217fb..cc5897b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc
index 1b1acbd..bf447fc 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc
index 811518d..183b466 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc
index e8fb0a2..ceaed37 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc
index ec88be9..2250db5 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc
index 4e6725e..e3c41da 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc
index 790c903..4b7852f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc
index 6851aa2..49059f2 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc
similarity index 88%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc
index c44c227..2c8098e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc
index 9a733d0..3ee4fcf 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc
index fd72f11..6ae4b5a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc
index 63f7a3e..dc4c138 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc
index 913897a..5716844 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc
index 86144bd..629a5a7 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc
new file mode 100644
index 0000000..1a32d46
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc
index 88e7b86..486f7d9 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc
index f4f7c69..86a7223 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_cell_widths.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_cell_widths.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_cell_widths.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_cell_widths.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_codes.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_codes.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_codes.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_codes.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_replace.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_replace.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_replace.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_replace.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_export_format.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_export_format.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_export_format.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_export_format.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_extension.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_extension.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_extension.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_extension.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_fileno.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_fileno.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_fileno.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_fileno.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_inspect.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_inspect.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_inspect.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_inspect.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_log_render.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_log_render.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_log_render.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_log_render.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_loop.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_loop.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_loop.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_loop.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_null_file.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_null_file.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_null_file.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_null_file.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_palettes.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_palettes.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_palettes.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_palettes.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_pick.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_pick.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_pick.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_pick.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_spinners.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_spinners.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_spinners.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_spinners.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_stack.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_stack.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_stack.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_stack.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_timer.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_timer.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_timer.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_timer.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_win32_console.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_win32_console.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_win32_console.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_win32_console.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_windows.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_windows.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_windows.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_windows.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_windows_renderer.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_windows_renderer.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_windows_renderer.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_windows_renderer.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_wrap.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/_wrap.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/_wrap.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/_wrap.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/abc.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/abc.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/abc.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/abc.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/align.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/align.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/align.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/align.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/bar.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/bar.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/bar.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/bar.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/box.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/box.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/box.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/box.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/cells.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/cells.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/cells.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/cells.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/color.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/color.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/color.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/color.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/color_triplet.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/color_triplet.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/color_triplet.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/color_triplet.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/columns.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/columns.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/columns.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/columns.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/console.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/console.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/console.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/console.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/constrain.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/constrain.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/constrain.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/constrain.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/containers.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/containers.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/containers.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/containers.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/control.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/control.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/control.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/control.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/default_styles.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/default_styles.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/default_styles.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/default_styles.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/diagnose.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/diagnose.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/diagnose.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/diagnose.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/emoji.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/emoji.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/emoji.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/emoji.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/errors.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/errors.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/errors.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/errors.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/file_proxy.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/file_proxy.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/file_proxy.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/file_proxy.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/filesize.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/filesize.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/filesize.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/filesize.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/highlighter.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/highlighter.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/highlighter.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/highlighter.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/json.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/json.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/json.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/json.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/jupyter.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/jupyter.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/jupyter.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/jupyter.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/layout.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/layout.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/layout.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/layout.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/live.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/live.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/live.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/live.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/live_render.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/live_render.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/live_render.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/live_render.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/logging.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/logging.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/logging.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/logging.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/markup.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/markup.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/markup.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/markup.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/measure.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/measure.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/measure.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/measure.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/padding.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/padding.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/padding.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/padding.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/pager.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/pager.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/pager.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/pager.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/palette.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/palette.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/palette.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/palette.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/panel.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/panel.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/panel.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/panel.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/pretty.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/pretty.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/pretty.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/pretty.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/progress.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/progress.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/progress.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/progress.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/progress_bar.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/progress_bar.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/progress_bar.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/progress_bar.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/prompt.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/prompt.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/prompt.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/prompt.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/protocol.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/protocol.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/protocol.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/protocol.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/region.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/region.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/region.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/region.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/repr.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/repr.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/repr.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/repr.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/rule.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/rule.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/rule.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/rule.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/scope.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/scope.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/scope.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/scope.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/screen.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/screen.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/screen.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/screen.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/segment.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/segment.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/segment.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/segment.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/spinner.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/spinner.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/spinner.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/spinner.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/status.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/status.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/status.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/status.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/style.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/style.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/style.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/style.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/styled.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/styled.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/styled.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/styled.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/syntax.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/syntax.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/syntax.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/syntax.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/table.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/table.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/table.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/table.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/terminal_theme.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/terminal_theme.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/terminal_theme.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/terminal_theme.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/text.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/text.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/text.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/text.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/theme.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/theme.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/theme.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/theme.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/themes.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/themes.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/themes.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/themes.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/traceback.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/traceback.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/traceback.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/traceback.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/rich/tree.py b/testcline/lib/python3.12/site-packages/pip/_vendor/rich/tree.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/rich/tree.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/rich/tree.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/six.py b/testcline/lib/python3.12/site-packages/pip/_vendor/six.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/six.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/six.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-312.pyc
index a5c2435..855fea8 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-312.pyc
index 2ace3ce..dbfb7d4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-312.pyc
similarity index 88%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-312.pyc
index 86fd9ac..b40fde6 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-312.pyc
similarity index 88%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-312.pyc
index ea6b8af..71bf827 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-312.pyc
similarity index 86%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-312.pyc
index 6fb1a07..89da824 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-312.pyc
similarity index 90%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-312.pyc
index 0aa68e4..79c2db7 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-312.pyc
similarity index 62%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-312.pyc
index c767b58..f17b507 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-312.pyc
index 7a08860..995d6fb 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-312.pyc
index a651624..d10b91b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-312.pyc
index e7855f9..5f93e9f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-312.pyc
index bf62793..b7296d9 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/_asyncio.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/_asyncio.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/_asyncio.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/_asyncio.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/_utils.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/_utils.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/_utils.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/_utils.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/after.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/after.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/after.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/after.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/before.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/before.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/before.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/before.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/before_sleep.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/before_sleep.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/before_sleep.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/before_sleep.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/nap.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/nap.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/nap.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/nap.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/retry.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/retry.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/retry.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/retry.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/stop.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/stop.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/stop.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/stop.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/tornadoweb.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/tornadoweb.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/tornadoweb.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/tornadoweb.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/wait.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/wait.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tenacity/wait.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tenacity/wait.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__init__.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..8844be4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc
index c894b1b..2053226 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc
similarity index 90%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc
index ca82314..9bafabb 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc
new file mode 100644
index 0000000..b01df0a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/_parser.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/_parser.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/_parser.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tomli/_parser.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/_re.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/_re.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/_re.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tomli/_re.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/_types.py b/testcline/lib/python3.12/site-packages/pip/_vendor/tomli/_types.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/tomli/_types.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/tomli/_types.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc
similarity index 58%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc
index c44c0c5..da0ccfa 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc
index 95b3feb..7d944db 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc
index 7a18f45..680876a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc
index 87b8f32..28d1532 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc
similarity index 70%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc
index 3bd8699..858fe44 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc
index 92bf3df..ccef6d7 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/_api.py b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/_api.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/_api.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/_api.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/_macos.py b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/_macos.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/_macos.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/_macos.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/_openssl.py b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/_openssl.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/_openssl.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/_openssl.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/_ssl_constants.py b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/_ssl_constants.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/_ssl_constants.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/_ssl_constants.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/_windows.py b/testcline/lib/python3.12/site-packages/pip/_vendor/truststore/_windows.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/truststore/_windows.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/truststore/_windows.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/typing_extensions.py b/testcline/lib/python3.12/site-packages/pip/_vendor/typing_extensions.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/typing_extensions.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/typing_extensions.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc
index 0471447..2b83a60 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc
index aae07cf..6e49b26 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc
new file mode 100644
index 0000000..2dbb667
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc
index db30794..58c73e0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc
index 7821f1a..8f7a7fb 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc
similarity index 93%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc
index b5a320e..cdd1881 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc
index d26d135..2336ace 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc
index 0237639..486d06f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc
index e3613f6..edcc39a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc
index dd71ffe..4d0c655 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc
index 7eb0789..80cb4f9 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/_collections.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/_collections.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/_collections.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/_collections.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/_version.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/_version.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/_version.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/_version.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/connection.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/connection.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/connection.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/connection.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/connectionpool.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/connectionpool.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/connectionpool.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/connectionpool.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..20ab4c7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc
similarity index 78%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc
index 5f26529..9d80ff2 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc
index 27b607e..c3825a0 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc
index 9f7398e..b935667 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc
index 4345cff..808cc27 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc
index 9be48c0..142c445 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc
similarity index 94%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc
index 7ee49ef..b4b174a 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..fe9ef4d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc
index a7b37ae..ffdbdef 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc
index 2d0cad8..a3d4e06 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/appengine.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/appengine.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/appengine.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/appengine.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/securetransport.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/securetransport.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/securetransport.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/securetransport.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/socks.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/socks.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/socks.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/socks.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/exceptions.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/exceptions.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/exceptions.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/exceptions.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/fields.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/fields.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/fields.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/fields.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/filepost.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/filepost.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/filepost.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/filepost.py
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..f5d2092
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc
similarity index 99%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc
index 046d8bd..26191a3 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..e35b9eb
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc
similarity index 79%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc
index 7ac1e70..fccdf0e 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc
similarity index 92%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc
index b3d5b3b..21b5216 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/six.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/six.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/six.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/six.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/poolmanager.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/poolmanager.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/poolmanager.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/poolmanager.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/request.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/request.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/request.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/request.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/response.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/response.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/response.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/response.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc
similarity index 77%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc
index 47125c7..813f8ef 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc
index d696cd1..2509ae6 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc
similarity index 68%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc
index 508cbaf..3a71096 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc
similarity index 80%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc
index cf64ee9..72b747f 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc
index 01c0ad6..8d1c17d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc
similarity index 89%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc
index c513fd5..39ba3e9 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc
similarity index 98%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc
index 68efc1e..f3d9fc4 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc
index 7a882d1..96d8b69 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc
similarity index 86%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc
index 0840947..1010d21 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc
index 25437a4..e866538 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc
index 25a8847..4045e4d 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc
similarity index 97%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc
index 7c228df..86e1348 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc
similarity index 88%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc
index 5699be3..88a3f42 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/connection.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/connection.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/connection.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/connection.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/proxy.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/proxy.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/proxy.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/proxy.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/queue.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/queue.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/queue.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/queue.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/request.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/request.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/request.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/request.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/response.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/response.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/response.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/response.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/retry.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/retry.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/retry.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/retry.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssltransport.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssltransport.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssltransport.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssltransport.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/timeout.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/timeout.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/timeout.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/timeout.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/url.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/url.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/url.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/url.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/wait.py b/testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/wait.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/urllib3/util/wait.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/urllib3/util/wait.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/vendor.txt b/testcline/lib/python3.12/site-packages/pip/_vendor/vendor.txt
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/vendor.txt
rename to testcline/lib/python3.12/site-packages/pip/_vendor/vendor.txt
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__init__.py b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__init__.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__init__.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__init__.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-312.pyc
similarity index 95%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-312.pyc
index 173c15b..a79269c 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-312.pyc
similarity index 96%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-312.pyc
index 16e385d..29dc03b 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-312.pyc
similarity index 73%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-312.pyc
index 013ad4a..63605fc 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-312.pyc
similarity index 91%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-312.pyc
index 3ce938f..9c8fc41 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-312.pyc
similarity index 85%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-312.pyc
index 7911a08..06345bb 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/labels.py b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/labels.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/labels.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/labels.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/mklabels.py b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/mklabels.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/mklabels.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/mklabels.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/tests.py b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/tests.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/tests.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/tests.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/x_user_defined.py b/testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/x_user_defined.py
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/webencodings/x_user_defined.py
rename to testcline/lib/python3.12/site-packages/pip/_vendor/webencodings/x_user_defined.py
diff --git a/AIagent/lib/python3.12/site-packages/pip/py.typed b/testcline/lib/python3.12/site-packages/pip/py.typed
similarity index 100%
rename from AIagent/lib/python3.12/site-packages/pip/py.typed
rename to testcline/lib/python3.12/site-packages/pip/py.typed
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/__init__.py b/testcline/lib/python3.12/site-packages/pkg_resources/__init__.py
new file mode 100644
index 0000000..8a2fbfa
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/__init__.py
@@ -0,0 +1,3714 @@
+"""
+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.
+
+This module is deprecated. Users are directed to :mod:`importlib.resources`,
+:mod:`importlib.metadata` and :pypi:`packaging` instead.
+"""
+
+from __future__ import annotations
+
+import sys
+
+if sys.version_info < (3, 9): # noqa: UP036 # Check for unsupported versions
+ raise RuntimeError("Python 3.9 or later is required")
+
+import _imp
+import collections
+import email.parser
+import errno
+import functools
+import importlib
+import importlib.abc
+import importlib.machinery
+import inspect
+import io
+import ntpath
+import operator
+import os
+import pkgutil
+import platform
+import plistlib
+import posixpath
+import re
+import stat
+import tempfile
+import textwrap
+import time
+import types
+import warnings
+import zipfile
+import zipimport
+from collections.abc import Iterable, Iterator, Mapping, MutableSequence
+from pkgutil import get_importer
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ BinaryIO,
+ Callable,
+ Literal,
+ NamedTuple,
+ NoReturn,
+ Protocol,
+ TypeVar,
+ Union,
+ overload,
+)
+
+sys.path.extend(((vendor_path := os.path.join(os.path.dirname(os.path.dirname(__file__)), 'setuptools', '_vendor')) not in sys.path) * [vendor_path]) # fmt: skip
+# workaround for #4476
+sys.modules.pop('backports', None)
+
+# capture these to bypass sandboxing
+from os import open as os_open, utime # isort: skip
+from os.path import isdir, split # isort: skip
+
+try:
+ from os import mkdir, rename, unlink
+
+ WRITE_SUPPORT = True
+except ImportError:
+ # no write support, probably under GAE
+ WRITE_SUPPORT = False
+
+import packaging.markers
+import packaging.requirements
+import packaging.specifiers
+import packaging.utils
+import packaging.version
+from jaraco.text import drop_comment, join_continuation, yield_lines
+from platformdirs import user_cache_dir as _user_cache_dir
+
+if TYPE_CHECKING:
+ from _typeshed import BytesPath, StrOrBytesPath, StrPath
+ from _typeshed.importlib import LoaderProtocol
+ from typing_extensions import Self, TypeAlias
+
+warnings.warn(
+ "pkg_resources is deprecated as an API. "
+ "See https://setuptools.pypa.io/en/latest/pkg_resources.html",
+ DeprecationWarning,
+ stacklevel=2,
+)
+
+_T = TypeVar("_T")
+_DistributionT = TypeVar("_DistributionT", bound="Distribution")
+# Type aliases
+_NestedStr: TypeAlias = Union[str, Iterable[Union[str, Iterable["_NestedStr"]]]]
+_StrictInstallerType: TypeAlias = Callable[["Requirement"], "_DistributionT"]
+_InstallerType: TypeAlias = Callable[["Requirement"], Union["Distribution", None]]
+_PkgReqType: TypeAlias = Union[str, "Requirement"]
+_EPDistType: TypeAlias = Union["Distribution", _PkgReqType]
+_MetadataType: TypeAlias = Union["IResourceProvider", None]
+_ResolvedEntryPoint: TypeAlias = Any # Can be any attribute in the module
+_ResourceStream: TypeAlias = Any # TODO / Incomplete: A readable file-like object
+# Any object works, but let's indicate we expect something like a module (optionally has __loader__ or __file__)
+_ModuleLike: TypeAlias = Union[object, types.ModuleType]
+# Any: Should be _ModuleLike but we end up with issues where _ModuleLike doesn't have _ZipLoaderModule's __loader__
+_ProviderFactoryType: TypeAlias = Callable[[Any], "IResourceProvider"]
+_DistFinderType: TypeAlias = Callable[[_T, str, bool], Iterable["Distribution"]]
+_NSHandlerType: TypeAlias = Callable[[_T, str, str, types.ModuleType], Union[str, None]]
+_AdapterT = TypeVar(
+ "_AdapterT", _DistFinderType[Any], _ProviderFactoryType, _NSHandlerType[Any]
+)
+
+
+class _ZipLoaderModule(Protocol):
+ __loader__: zipimport.zipimporter
+
+
+_PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.I)
+
+
+class PEP440Warning(RuntimeWarning):
+ """
+ Used when there is an issue with a version or specifier not complying with
+ PEP 440.
+ """
+
+
+parse_version = packaging.version.Version
+
+_state_vars: dict[str, str] = {}
+
+
+def _declare_state(vartype: str, varname: str, initial_value: _T) -> _T:
+ _state_vars[varname] = vartype
+ return initial_value
+
+
+def __getstate__() -> dict[str, Any]:
+ state = {}
+ g = globals()
+ for k, v in _state_vars.items():
+ state[k] = g['_sget_' + v](g[k])
+ return state
+
+
+def __setstate__(state: dict[str, Any]) -> dict[str, Any]:
+ 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) -> None:
+ ob.clear()
+ ob.update(state)
+
+
+def _sget_object(val):
+ return val.__getstate__()
+
+
+def _sset_object(key, ob, state) -> None:
+ 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 macOS that would be required to *use* extensions produced by
+ distutils. But what we want when checking compatibility is to know the
+ version of macOS that we are *running*. To allow usage of packages that
+ explicitly require a newer version of macOS, 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:
+ major_minor = '.'.join(_macos_vers()[:2])
+ build = m.group(3)
+ plat = f'macosx-{major_minor}-{build}'
+ except ValueError:
+ # not macOS
+ 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) -> str:
+ 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) -> Distribution:
+ return self.args[0]
+
+ @property
+ def req(self) -> Requirement:
+ return self.args[1]
+
+ def report(self):
+ return self._template.format(**locals())
+
+ def with_context(
+ self, required_by: set[Distribution | str]
+ ) -> Self | ContextualVersionConflict:
+ """
+ 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) -> set[str]:
+ 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) -> Requirement:
+ return self.args[0]
+
+ @property
+ def requirers(self) -> set[str] | None:
+ 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) -> str:
+ return self.report()
+
+
+class UnknownExtra(ResolutionError):
+ """Distribution doesn't have an "extra feature" of the given name"""
+
+
+_provider_factories: dict[type[_ModuleLike], _ProviderFactoryType] = {}
+
+PY_MAJOR = f'{sys.version_info.major}.{sys.version_info.minor}'
+EGG_DIST = 3
+BINARY_DIST = 2
+SOURCE_DIST = 1
+CHECKOUT_DIST = 0
+DEVELOP_DIST = -1
+
+
+def register_loader_type(
+ loader_type: type[_ModuleLike], provider_factory: _ProviderFactoryType
+) -> None:
+ """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
+
+
+@overload
+def get_provider(moduleOrReq: str) -> IResourceProvider: ...
+@overload
+def get_provider(moduleOrReq: Requirement) -> Distribution: ...
+def get_provider(moduleOrReq: str | Requirement) -> IResourceProvider | Distribution:
+ """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)
+
+
+@functools.cache
+def _macos_vers():
+ version = platform.mac_ver()[0]
+ # fallback for MacPorts
+ if version == '':
+ plist = '/System/Library/CoreServices/SystemVersion.plist'
+ if os.path.exists(plist):
+ with open(plist, 'rb') as fh:
+ plist_content = plistlib.load(fh)
+ if 'ProductVersion' in plist_content:
+ version = plist_content['ProductVersion']
+ return version.split('.')
+
+
+def _macos_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 macOS.
+ """
+ from sysconfig import get_platform
+
+ plat = get_platform()
+ if sys.platform == "darwin" and not plat.startswith('macosx-'):
+ try:
+ version = _macos_vers()
+ machine = _macos_arch(os.uname()[4].replace(" ", "_"))
+ return f"macosx-{version[0]}.{version[1]}-{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: str | None, required: str | None) -> bool:
+ """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
+
+ # macOS 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 macOS designation.
+ provDarwin = darwinVersionString.match(provided)
+ if provDarwin:
+ dversion = int(provDarwin.group(1))
+ macosversion = f"{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 macOS 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
+
+
+@overload
+def get_distribution(dist: _DistributionT) -> _DistributionT: ...
+@overload
+def get_distribution(dist: _PkgReqType) -> Distribution: ...
+def get_distribution(dist: Distribution | _PkgReqType) -> Distribution:
+ """Return a current distribution object for a Requirement or string"""
+ if isinstance(dist, str):
+ dist = Requirement.parse(dist)
+ if isinstance(dist, Requirement):
+ dist = get_provider(dist)
+ if not isinstance(dist, Distribution):
+ raise TypeError("Expected str, Requirement, or Distribution", dist)
+ return dist
+
+
+def load_entry_point(dist: _EPDistType, group: str, name: str) -> _ResolvedEntryPoint:
+ """Return `name` entry point of `group` for `dist` or raise ImportError"""
+ return get_distribution(dist).load_entry_point(group, name)
+
+
+@overload
+def get_entry_map(
+ dist: _EPDistType, group: None = None
+) -> dict[str, dict[str, EntryPoint]]: ...
+@overload
+def get_entry_map(dist: _EPDistType, group: str) -> dict[str, EntryPoint]: ...
+def get_entry_map(dist: _EPDistType, group: str | None = 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: _EPDistType, group: str, name: str) -> EntryPoint | None:
+ """Return the EntryPoint object for `group`+`name`, or ``None``"""
+ return get_distribution(dist).get_entry_info(group, name)
+
+
+class IMetadataProvider(Protocol):
+ def has_metadata(self, name: str) -> bool:
+ """Does the package's distribution contain the named metadata?"""
+ ...
+
+ def get_metadata(self, name: str) -> str:
+ """The named metadata resource as a string"""
+ ...
+
+ def get_metadata_lines(self, name: str) -> Iterator[str]:
+ """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(self, name: str) -> bool:
+ """Is the named metadata a directory? (like ``os.path.isdir()``)"""
+ ...
+
+ def metadata_listdir(self, name: str) -> list[str]:
+ """List of metadata names in the directory (like ``os.listdir()``)"""
+ ...
+
+ def run_script(self, script_name: str, namespace: dict[str, Any]) -> None:
+ """Execute the named script in the supplied namespace dictionary"""
+ ...
+
+
+class IResourceProvider(IMetadataProvider, Protocol):
+ """An object that provides access to package resources"""
+
+ def get_resource_filename(
+ self, manager: ResourceManager, resource_name: str
+ ) -> str:
+ """Return a true filesystem path for `resource_name`
+
+ `manager` must be a ``ResourceManager``"""
+ ...
+
+ def get_resource_stream(
+ self, manager: ResourceManager, resource_name: str
+ ) -> _ResourceStream:
+ """Return a readable file-like object for `resource_name`
+
+ `manager` must be a ``ResourceManager``"""
+ ...
+
+ def get_resource_string(
+ self, manager: ResourceManager, resource_name: str
+ ) -> bytes:
+ """Return the contents of `resource_name` as :obj:`bytes`
+
+ `manager` must be a ``ResourceManager``"""
+ ...
+
+ def has_resource(self, resource_name: str) -> bool:
+ """Does the package contain the named resource?"""
+ ...
+
+ def resource_isdir(self, resource_name: str) -> bool:
+ """Is the named resource a directory? (like ``os.path.isdir()``)"""
+ ...
+
+ def resource_listdir(self, resource_name: str) -> list[str]:
+ """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: Iterable[str] | None = None) -> None:
+ """Create working set from list of path entries (default=sys.path)"""
+ self.entries: list[str] = []
+ self.entry_keys: dict[str | None, list[str]] = {}
+ self.by_key: dict[str, Distribution] = {}
+ self.normalized_to_canonical_keys: dict[str, str] = {}
+ self.callbacks: list[Callable[[Distribution], object]] = []
+
+ 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: str) -> None:
+ """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: Distribution) -> bool:
+ """True if `dist` is the active distribution for its project"""
+ return self.by_key.get(dist.key) == dist
+
+ def find(self, req: Requirement) -> Distribution | None:
+ """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: Distribution | None = None
+
+ candidates = (
+ req.key,
+ self.normalized_to_canonical_keys.get(req.key),
+ safe_name(req.key).replace(".", "-"),
+ )
+
+ for candidate in filter(None, candidates):
+ dist = self.by_key.get(candidate)
+ if dist:
+ req.key = candidate
+ break
+
+ 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: str, name: str | None = None
+ ) -> Iterator[EntryPoint]:
+ """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: str, script_name: str) -> None:
+ """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) -> Iterator[Distribution]:
+ """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 = set()
+ 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.add(key)
+ yield self.by_key[key]
+
+ def add(
+ self,
+ dist: Distribution,
+ entry: str | None = None,
+ insert: bool = True,
+ replace: bool = False,
+ ) -> None:
+ """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
+ normalized_name = packaging.utils.canonicalize_name(dist.key)
+ self.normalized_to_canonical_keys[normalized_name] = dist.key
+ if dist.key not in keys:
+ keys.append(dist.key)
+ if dist.key not in keys2:
+ keys2.append(dist.key)
+ self._added_new(dist)
+
+ @overload
+ def resolve(
+ self,
+ requirements: Iterable[Requirement],
+ env: Environment | None,
+ installer: _StrictInstallerType[_DistributionT],
+ replace_conflicting: bool = False,
+ extras: tuple[str, ...] | None = None,
+ ) -> list[_DistributionT]: ...
+ @overload
+ def resolve(
+ self,
+ requirements: Iterable[Requirement],
+ env: Environment | None = None,
+ *,
+ installer: _StrictInstallerType[_DistributionT],
+ replace_conflicting: bool = False,
+ extras: tuple[str, ...] | None = None,
+ ) -> list[_DistributionT]: ...
+ @overload
+ def resolve(
+ self,
+ requirements: Iterable[Requirement],
+ env: Environment | None = None,
+ installer: _InstallerType | None = None,
+ replace_conflicting: bool = False,
+ extras: tuple[str, ...] | None = None,
+ ) -> list[Distribution]: ...
+ def resolve(
+ self,
+ requirements: Iterable[Requirement],
+ env: Environment | None = None,
+ installer: _InstallerType | None | _StrictInstallerType[_DistributionT] = None,
+ replace_conflicting: bool = False,
+ extras: tuple[str, ...] | None = None,
+ ) -> list[Distribution] | list[_DistributionT]:
+ """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 = set()
+ # key -> dist
+ best: dict[str, Distribution] = {}
+ to_activate: list[Distribution] = []
+
+ req_extras = _ReqExtras()
+
+ # Mapping of requirement to set of distributions that required it;
+ # useful for reporting info about conflicts.
+ required_by = collections.defaultdict[Requirement, set[str]](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 = self._resolve_dist(
+ req, best, replace_conflicting, env, installer, required_by, to_activate
+ )
+
+ # 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.add(req)
+
+ # return list of distros to activate
+ return to_activate
+
+ def _resolve_dist(
+ self, req, best, replace_conflicting, env, installer, required_by, to_activate
+ ) -> Distribution:
+ 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)
+ return dist
+
+ @overload
+ def find_plugins(
+ self,
+ plugin_env: Environment,
+ full_env: Environment | None,
+ installer: _StrictInstallerType[_DistributionT],
+ fallback: bool = True,
+ ) -> tuple[list[_DistributionT], dict[Distribution, Exception]]: ...
+ @overload
+ def find_plugins(
+ self,
+ plugin_env: Environment,
+ full_env: Environment | None = None,
+ *,
+ installer: _StrictInstallerType[_DistributionT],
+ fallback: bool = True,
+ ) -> tuple[list[_DistributionT], dict[Distribution, Exception]]: ...
+ @overload
+ def find_plugins(
+ self,
+ plugin_env: Environment,
+ full_env: Environment | None = None,
+ installer: _InstallerType | None = None,
+ fallback: bool = True,
+ ) -> tuple[list[Distribution], dict[Distribution, Exception]]: ...
+ def find_plugins(
+ self,
+ plugin_env: Environment,
+ full_env: Environment | None = None,
+ installer: _InstallerType | None | _StrictInstallerType[_DistributionT] = None,
+ fallback: bool = True,
+ ) -> tuple[
+ list[Distribution] | list[_DistributionT],
+ dict[Distribution, Exception],
+ ]:
+ """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: dict[Distribution, Exception] = {}
+ distributions: dict[Distribution, Exception | None] = {}
+
+ 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
+
+ sorted_distributions = list(distributions)
+ sorted_distributions.sort()
+
+ return sorted_distributions, error_info
+
+ def require(self, *requirements: _NestedStr) -> list[Distribution]:
+ """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: Callable[[Distribution], object], existing: bool = True
+ ) -> None:
+ """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) -> None:
+ for callback in self.callbacks:
+ callback(dist)
+
+ def __getstate__(
+ self,
+ ) -> tuple[
+ list[str],
+ dict[str | None, list[str]],
+ dict[str, Distribution],
+ dict[str, str],
+ list[Callable[[Distribution], object]],
+ ]:
+ return (
+ self.entries[:],
+ self.entry_keys.copy(),
+ self.by_key.copy(),
+ self.normalized_to_canonical_keys.copy(),
+ self.callbacks[:],
+ )
+
+ def __setstate__(self, e_k_b_n_c) -> None:
+ entries, keys, by_key, normalized_to_canonical_keys, callbacks = e_k_b_n_c
+ self.entries = entries[:]
+ self.entry_keys = keys.copy()
+ self.by_key = by_key.copy()
+ self.normalized_to_canonical_keys = normalized_to_canonical_keys.copy()
+ self.callbacks = callbacks[:]
+
+
+class _ReqExtras(dict["Requirement", tuple[str, ...]]):
+ """
+ Map each requirement to the extras that demanded it.
+ """
+
+ def markers_pass(self, req: Requirement, extras: tuple[str, ...] | None = 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.
+ """
+ return not req.marker or any(
+ req.marker.evaluate({'extra': extra})
+ for extra in self.get(req, ()) + (extras or ("",))
+ )
+
+
+class Environment:
+ """Searchable snapshot of distributions on a search path"""
+
+ def __init__(
+ self,
+ search_path: Iterable[str] | None = None,
+ platform: str | None = get_supported_platform(),
+ python: str | None = PY_MAJOR,
+ ) -> None:
+ """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: dict[str, list[Distribution]] = {}
+ self.platform = platform
+ self.python = python
+ self.scan(search_path)
+
+ def can_add(self, dist: Distribution) -> bool:
+ """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: Distribution) -> None:
+ """Remove `dist` from the environment"""
+ self._distmap[dist.key].remove(dist)
+
+ def scan(self, search_path: Iterable[str] | None = None) -> 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: str) -> list[Distribution]:
+ """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: Distribution) -> None:
+ """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)
+
+ @overload
+ def best_match(
+ self,
+ req: Requirement,
+ working_set: WorkingSet,
+ installer: _StrictInstallerType[_DistributionT],
+ replace_conflicting: bool = False,
+ ) -> _DistributionT: ...
+ @overload
+ def best_match(
+ self,
+ req: Requirement,
+ working_set: WorkingSet,
+ installer: _InstallerType | None = None,
+ replace_conflicting: bool = False,
+ ) -> Distribution | None: ...
+ def best_match(
+ self,
+ req: Requirement,
+ working_set: WorkingSet,
+ installer: _InstallerType | None | _StrictInstallerType[_DistributionT] = None,
+ replace_conflicting: bool = False,
+ ) -> Distribution | None:
+ """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)
+
+ @overload
+ def obtain(
+ self,
+ requirement: Requirement,
+ installer: _StrictInstallerType[_DistributionT],
+ ) -> _DistributionT: ...
+ @overload
+ def obtain(
+ self,
+ requirement: Requirement,
+ installer: Callable[[Requirement], None] | None = None,
+ ) -> None: ...
+ @overload
+ def obtain(
+ self,
+ requirement: Requirement,
+ installer: _InstallerType | None = None,
+ ) -> Distribution | None: ...
+ def obtain(
+ self,
+ requirement: Requirement,
+ installer: Callable[[Requirement], None]
+ | _InstallerType
+ | None
+ | _StrictInstallerType[_DistributionT] = None,
+ ) -> Distribution | 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."""
+ return installer(requirement) if installer else None
+
+ def __iter__(self) -> Iterator[str]:
+ """Yield the unique project names of the available distributions"""
+ for key in self._distmap.keys():
+ if self[key]:
+ yield key
+
+ def __iadd__(self, other: Distribution | Environment) -> Self:
+ """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(f"Can't add {other!r} to environment")
+ return self
+
+ def __add__(self, other: Distribution | Environment) -> Self:
+ """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
+ """
+
+ manager: ResourceManager
+ cache_path: str
+ original_error: BaseException | None
+
+
+class ResourceManager:
+ """Manage resource extraction and packages"""
+
+ extraction_path: str | None = None
+
+ def __init__(self) -> None:
+ # acts like a set
+ self.cached_files: dict[str, Literal[True]] = {}
+
+ def resource_exists(
+ self, package_or_requirement: _PkgReqType, resource_name: str
+ ) -> bool:
+ """Does the named resource exist?"""
+ return get_provider(package_or_requirement).has_resource(resource_name)
+
+ def resource_isdir(
+ self, package_or_requirement: _PkgReqType, resource_name: str
+ ) -> bool:
+ """Is the named resource an existing directory?"""
+ return get_provider(package_or_requirement).resource_isdir(resource_name)
+
+ def resource_filename(
+ self, package_or_requirement: _PkgReqType, resource_name: str
+ ) -> str:
+ """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: _PkgReqType, resource_name: str
+ ) -> _ResourceStream:
+ """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: _PkgReqType, resource_name: str
+ ) -> bytes:
+ """Return specified resource as :obj:`bytes`"""
+ return get_provider(package_or_requirement).get_resource_string(
+ self, resource_name
+ )
+
+ def resource_listdir(
+ self, package_or_requirement: _PkgReqType, resource_name: str
+ ) -> list[str]:
+ """List the contents of the named resource directory"""
+ return get_provider(package_or_requirement).resource_listdir(resource_name)
+
+ def extraction_error(self) -> NoReturn:
+ """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: str, names: Iterable[StrPath] = ()) -> str:
+ """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] = True
+ return target_path
+
+ @staticmethod
+ def _warn_unsafe_extraction_path(path) -> None:
+ """
+ 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 = (
+ "Extraction path is writable by group/others "
+ "and vulnerable to attack when "
+ "used with get_resource_filename ({path}). "
+ "Consider a more secure "
+ "location (set with .set_extraction_path or the "
+ "PYTHON_EGG_CACHE environment variable)."
+ ).format(**locals())
+ warnings.warn(msg, UserWarning)
+
+ def postprocess(self, tempname: StrOrBytesPath, filename: StrOrBytesPath) -> None:
+ """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: str) -> None:
+ """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: bool = False) -> list[str]:
+ """
+ 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
+ return []
+
+
+def get_default_cache() -> str:
+ """
+ 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 _user_cache_dir(appname='Python-Eggs')
+
+
+def safe_name(name: str) -> str:
+ """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: str) -> str:
+ """
+ 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 _forgiving_version(version) -> str:
+ """Fallback when ``safe_version`` is not safe enough
+ >>> parse_version(_forgiving_version('0.23ubuntu1'))
+
+ >>> parse_version(_forgiving_version('0.23-'))
+
+ >>> parse_version(_forgiving_version('0.-_'))
+
+ >>> parse_version(_forgiving_version('42.+?1'))
+
+ >>> parse_version(_forgiving_version('hello world'))
+
+ """
+ version = version.replace(' ', '.')
+ match = _PEP440_FALLBACK.search(version)
+ if match:
+ safe = match["safe"]
+ rest = version[len(safe) :]
+ else:
+ safe = "0"
+ rest = version
+ local = f"sanitized.{_safe_segment(rest)}".strip(".")
+ return f"{safe}.dev0+{local}"
+
+
+def _safe_segment(segment):
+ """Convert an arbitrary string into a safe segment"""
+ segment = re.sub('[^A-Za-z0-9.]+', '-', segment)
+ segment = re.sub('-[^A-Za-z0-9]+', '-', segment)
+ return re.sub(r'\.[^A-Za-z0-9]+', '.', segment).strip(".-")
+
+
+def safe_extra(extra: str) -> str:
+ """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: str) -> str:
+ """Convert a project or version name to its filename-escaped form
+
+ Any '-' characters are currently replaced with '_'.
+ """
+ return name.replace('-', '_')
+
+
+def invalid_marker(text: str) -> SyntaxError | Literal[False]:
+ """
+ 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: str, extra: str | None = None) -> bool:
+ """
+ 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) from e
+
+
+class NullProvider:
+ """Try to implement resources and metadata for arbitrary PEP 302 loaders"""
+
+ egg_name: str | None = None
+ egg_info: str | None = None
+ loader: LoaderProtocol | None = None
+
+ def __init__(self, module: _ModuleLike) -> None:
+ self.loader = getattr(module, '__loader__', None)
+ self.module_path = os.path.dirname(getattr(module, '__file__', ''))
+
+ def get_resource_filename(
+ self, manager: ResourceManager, resource_name: str
+ ) -> str:
+ return self._fn(self.module_path, resource_name)
+
+ def get_resource_stream(
+ self, manager: ResourceManager, resource_name: str
+ ) -> BinaryIO:
+ return io.BytesIO(self.get_resource_string(manager, resource_name))
+
+ def get_resource_string(
+ self, manager: ResourceManager, resource_name: str
+ ) -> bytes:
+ return self._get(self._fn(self.module_path, resource_name))
+
+ def has_resource(self, resource_name: str) -> bool:
+ 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: str) -> bool:
+ if not self.egg_info:
+ return False
+
+ path = self._get_metadata_path(name)
+ return self._has(path)
+
+ def get_metadata(self, name: str) -> str:
+ if not self.egg_info:
+ return ""
+ path = self._get_metadata_path(name)
+ value = self._get(path)
+ 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 += f' in {name} file at path: {path}'
+ raise
+
+ def get_metadata_lines(self, name: str) -> Iterator[str]:
+ return yield_lines(self.get_metadata(name))
+
+ def resource_isdir(self, resource_name: str) -> bool:
+ return self._isdir(self._fn(self.module_path, resource_name))
+
+ def metadata_isdir(self, name: str) -> bool:
+ return bool(self.egg_info and self._isdir(self._fn(self.egg_info, name)))
+
+ def resource_listdir(self, resource_name: str) -> list[str]:
+ return self._listdir(self._fn(self.module_path, resource_name))
+
+ def metadata_listdir(self, name: str) -> list[str]:
+ if self.egg_info:
+ return self._listdir(self._fn(self.egg_info, name))
+ return []
+
+ def run_script(self, script_name: str, namespace: dict[str, Any]) -> None:
+ 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 = _read_utf8_with_fallback(script_filename)
+ 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) -> bool:
+ raise NotImplementedError(
+ "Can't perform this operation for unregistered loader type"
+ )
+
+ def _isdir(self, path) -> bool:
+ raise NotImplementedError(
+ "Can't perform this operation for unregistered loader type"
+ )
+
+ def _listdir(self, path) -> list[str]:
+ raise NotImplementedError(
+ "Can't perform this operation for unregistered loader type"
+ )
+
+ def _fn(self, base: str | None, resource_name: str):
+ if base is None:
+ raise TypeError(
+ "`base` parameter in `_fn` is `None`. Either override this method or check the parameter first."
+ )
+ 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) -> None:
+ """
+ Validate the resource paths according to the docs.
+ https://setuptools.pypa.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)
+ or path.startswith("\\")
+ )
+ if not invalid:
+ return
+
+ msg = "Use of .. or absolute path in a resource path is not allowed."
+
+ # Aggressively disallow Windows absolute paths
+ if (path.startswith("\\") or ntpath.isabs(path)) and not posixpath.isabs(path):
+ raise ValueError(msg)
+
+ # for compatibility, warn; in future
+ # raise ValueError(msg)
+ issue_warning(
+ msg[:-1] + " and will raise exceptions in a future release.",
+ DeprecationWarning,
+ )
+
+ def _get(self, path) -> bytes:
+ if hasattr(self.loader, 'get_data') and self.loader:
+ # Already checked get_data exists
+ return self.loader.get_data(path) # type: ignore[attr-defined]
+ raise NotImplementedError(
+ "Can't perform this operation for loaders without 'get_data()'"
+ )
+
+
+register_loader_type(object, NullProvider)
+
+
+def _parents(path):
+ """
+ yield all parents of path including path
+ """
+ last = None
+ while path != last:
+ yield path
+ last = path
+ path, _ = os.path.split(path)
+
+
+class EggProvider(NullProvider):
+ """Provider based on a virtual filesystem"""
+
+ def __init__(self, module: _ModuleLike) -> None:
+ super().__init__(module)
+ self._setup_prefix()
+
+ def _setup_prefix(self):
+ # Assume that metadata may be nested inside a "basket"
+ # of multiple eggs and use module_path instead of .archive.
+ eggs = filter(_is_egg_path, _parents(self.module_path))
+ egg = next(eggs, None)
+ egg and self._set_egg(egg)
+
+ def _set_egg(self, path: str) -> None:
+ self.egg_name = os.path.basename(path)
+ self.egg_info = os.path.join(path, 'EGG-INFO')
+ self.egg_root = path
+
+
+class DefaultProvider(EggProvider):
+ """Provides access to package resources in the filesystem"""
+
+ def _has(self, path) -> bool:
+ return os.path.exists(path)
+
+ def _isdir(self, path) -> bool:
+ return os.path.isdir(path)
+
+ def _listdir(self, path):
+ return os.listdir(path)
+
+ def get_resource_stream(
+ self, manager: object, resource_name: str
+ ) -> io.BufferedReader:
+ return open(self._fn(self.module_path, resource_name), 'rb')
+
+ def _get(self, path) -> bytes:
+ with open(path, 'rb') as stream:
+ return stream.read()
+
+ @classmethod
+ def _register(cls) -> None:
+ 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"""
+
+ # A special case, we don't want all Providers inheriting from NullProvider to have a potentially None module_path
+ module_path: str | None = None # type: ignore[assignment]
+
+ _isdir = _has = lambda self, path: False
+
+ def _get(self, path) -> bytes:
+ return b''
+
+ def _listdir(self, path):
+ return []
+
+ def __init__(self) -> None:
+ pass
+
+
+empty_provider = EmptyProvider()
+
+
+class ZipManifests(dict[str, "MemoizedZipManifests.manifest_mod"]):
+ """
+ zip manifest builder
+ """
+
+ # `path` could be `StrPath | IO[bytes]` but that violates the LSP for `MemoizedZipManifests.load`
+ @classmethod
+ def build(cls, path: str) -> dict[str, zipfile.ZipInfo]:
+ """
+ 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.
+ """
+
+ class manifest_mod(NamedTuple):
+ manifest: dict[str, zipfile.ZipInfo]
+ mtime: float
+
+ def load(self, path: str) -> dict[str, zipfile.ZipInfo]: # type: ignore[override] # ZipManifests.load is a classmethod
+ """
+ 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: list[str] | None = None
+ _zip_manifests = MemoizedZipManifests()
+ # ZipProvider's loader should always be a zipimporter or equivalent
+ loader: zipimport.zipimporter
+
+ def __init__(self, module: _ZipLoaderModule) -> None:
+ super().__init__(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(f"{fspath} is not a subpath of {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(f"{fspath} is not a subpath of {self.egg_root}")
+
+ @property
+ def zipinfo(self):
+ return self._zip_manifests.load(self.loader.archive)
+
+ def get_resource_filename(
+ self, manager: ResourceManager, resource_name: str
+ ) -> str:
+ 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
+
+ # FIXME: 'ZipProvider._extract_resource' is too complex (12)
+ def _extract_resource(self, manager: ResourceManager, zip_path) -> str: # noqa: C901
+ 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 OSError(
+ '"os.rename" and "os.unlink" are not supported on this platform'
+ )
+ try:
+ if not self.egg_name:
+ raise OSError(
+ '"egg_name" is empty. This likely means no egg could be found from the "module_path".'
+ )
+ 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 OSError:
+ 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 OSError:
+ # 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) -> bool:
+ zip_path = self._zipinfo_name(fspath)
+ return zip_path in self.zipinfo or zip_path in self._index()
+
+ def _isdir(self, fspath) -> bool:
+ 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: str):
+ return self._zipinfo_name(self._fn(self.egg_root, resource_name))
+
+ def _resource_to_zip(self, resource_name: str):
+ 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: StrPath) -> None:
+ self.path = path
+
+ def _get_metadata_path(self, name):
+ return self.path
+
+ def has_metadata(self, name: str) -> bool:
+ return name == 'PKG-INFO' and os.path.isfile(self.path)
+
+ def get_metadata(self, name: str) -> str:
+ if name != 'PKG-INFO':
+ raise KeyError("No metadata except PKG-INFO is available")
+
+ with 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) -> None:
+ replacement_char = '�'
+ 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: str) -> Iterator[str]:
+ 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: str, egg_info: str) -> None:
+ self.module_path = path
+ self.egg_info = egg_info
+
+
+class EggMetadata(ZipProvider):
+ """Metadata provider for .egg files"""
+
+ def __init__(self, importer: zipimport.zipimporter) -> None:
+ """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()
+
+
+_distribution_finders: dict[type, _DistFinderType[Any]] = _declare_state(
+ 'dict', '_distribution_finders', {}
+)
+
+
+def register_finder(
+ importer_type: type[_T], distribution_finder: _DistFinderType[_T]
+) -> None:
+ """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: str, only: bool = False) -> Iterable[Distribution]:
+ """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: zipimport.zipimporter, path_item: str, only: bool = False
+) -> Iterator[Distribution]:
+ """
+ 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)
+ yield from dists
+ elif subitem.lower().endswith(('.dist-info', '.egg-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: object | None, path_item: str | None, only: bool | None = False
+):
+ return ()
+
+
+register_finder(object, find_nothing)
+
+
+def find_on_path(importer: object | None, 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 = (os.path.join(path_item, child) for child in safe_listdir(path_item))
+
+ # scan for .egg and .egg-info in directory
+ for entry in sorted(entries):
+ fullpath = os.path.join(path_item, entry)
+ factory = dist_factory(path_item, entry, only)
+ yield from factory(fullpath)
+
+
+def dist_factory(path_item, entry, only):
+ """Return a dist_factory for the given entry."""
+ lower = entry.lower()
+ is_egg_info = lower.endswith('.egg-info')
+ is_dist_info = lower.endswith('.dist-info') and os.path.isdir(
+ os.path.join(path_item, entry)
+ )
+ is_meta = is_egg_info or is_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) -> Literal[False]:
+ return False
+
+ def __call__(self, fullpath: object):
+ return iter(())
+
+
+def safe_listdir(path: StrOrBytesPath):
+ """
+ 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
+ if e.errno not in (errno.ENOTDIR, errno.EACCES, errno.ENOENT):
+ raise
+ return ()
+
+
+def distributions_from_metadata(path: str):
+ root = os.path.dirname(path)
+ if os.path.isdir(path):
+ if len(os.listdir(path)) == 0:
+ # empty metadata dir; skip
+ return
+ metadata: _MetadataType = 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
+ """
+ for line in _read_utf8_with_fallback(path).splitlines():
+ 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, ())
+
+
+if hasattr(pkgutil, 'ImpImporter'):
+ register_finder(pkgutil.ImpImporter, find_on_path)
+
+register_finder(importlib.machinery.FileFinder, find_on_path)
+
+_namespace_handlers: dict[type, _NSHandlerType[Any]] = _declare_state(
+ 'dict', '_namespace_handlers', {}
+)
+_namespace_packages: dict[str | None, list[str]] = _declare_state(
+ 'dict', '_namespace_packages', {}
+)
+
+
+def register_namespace_handler(
+ importer_type: type[_T], namespace_handler: _NSHandlerType[_T]
+) -> None:
+ """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
+
+ # use find_spec (PEP 451) and fall-back to find_module (PEP 302)
+ try:
+ spec = importer.find_spec(packageName)
+ except AttributeError:
+ # capture warnings due to #1111
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ loader = importer.find_module(packageName)
+ else:
+ loader = spec.loader if spec else None
+
+ 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)
+ importlib.import_module(packageName)
+ _rebuild_mod_path(path, packageName, module)
+ return subpath
+
+
+def _rebuild_mod_path(orig_path, package_name, module: types.ModuleType) -> None:
+ """
+ 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: str) -> None:
+ """Declare that package 'packageName' is a namespace package"""
+
+ msg = (
+ f"Deprecated call to `pkg_resources.declare_namespace({packageName!r})`.\n"
+ "Implementing implicit namespace packages (as specified in PEP 420) "
+ "is preferred to `pkg_resources.declare_namespace`. "
+ "See https://setuptools.pypa.io/en/latest/references/"
+ "keywords.html#keyword-namespace-packages"
+ )
+ warnings.warn(msg, DeprecationWarning, stacklevel=2)
+
+ _imp.acquire_lock()
+ try:
+ if packageName in _namespace_packages:
+ return
+
+ path: MutableSequence[str] = 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 as e:
+ raise TypeError("Not a package:", parent) from e
+
+ # 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: str, parent: str | None = None) -> 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: object,
+ path_item: StrPath,
+ packageName: str,
+ module: types.ModuleType,
+):
+ """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
+
+
+if hasattr(pkgutil, 'ImpImporter'):
+ register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
+
+register_namespace_handler(zipimport.zipimporter, file_ns_handler)
+register_namespace_handler(importlib.machinery.FileFinder, file_ns_handler)
+
+
+def null_ns_handler(
+ importer: object,
+ path_item: str | None,
+ packageName: str | None,
+ module: _ModuleLike | None,
+) -> None:
+ return None
+
+
+register_namespace_handler(object, null_ns_handler)
+
+
+@overload
+def normalize_path(filename: StrPath) -> str: ...
+@overload
+def normalize_path(filename: BytesPath) -> bytes: ...
+def normalize_path(filename: StrOrBytesPath) -> str | bytes:
+ """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: StrOrBytesPath): # 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
+
+
+if TYPE_CHECKING:
+ # https://github.com/python/mypy/issues/16261
+ # https://github.com/python/typeshed/issues/6347
+ @overload
+ def _normalize_cached(filename: StrPath) -> str: ...
+ @overload
+ def _normalize_cached(filename: BytesPath) -> bytes: ...
+ def _normalize_cached(filename: StrOrBytesPath) -> str | bytes: ...
+
+else:
+
+ @functools.cache
+ def _normalize_cached(filename):
+ return normalize_path(filename)
+
+
+def _is_egg_path(path):
+ """
+ Determine if given path appears to be an egg.
+ """
+ return _is_zip_egg(path) or _is_unpacked_egg(path)
+
+
+def _is_zip_egg(path):
+ return (
+ path.lower().endswith('.egg')
+ and os.path.isfile(path)
+ and zipfile.is_zipfile(path)
+ )
+
+
+def _is_unpacked_egg(path):
+ """
+ Determine if given path appears to be an unpacked egg.
+ """
+ return path.lower().endswith('.egg') and os.path.isfile(
+ os.path.join(path, 'EGG-INFO', 'PKG-INFO')
+ )
+
+
+def _set_parent_ns(packageName) -> None:
+ parts = packageName.split('.')
+ name = parts.pop()
+ if parts:
+ parent = '.'.join(parts)
+ setattr(sys.modules[parent], name, sys.modules[packageName])
+
+
+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: str,
+ module_name: str,
+ attrs: Iterable[str] = (),
+ extras: Iterable[str] = (),
+ dist: Distribution | None = None,
+ ) -> 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) -> str:
+ s = f"{self.name} = {self.module_name}"
+ if self.attrs:
+ s += ':' + '.'.join(self.attrs)
+ if self.extras:
+ extras = ','.join(self.extras)
+ s += f' [{extras}]'
+ return s
+
+ def __repr__(self) -> str:
+ return f"EntryPoint.parse({str(self)!r})"
+
+ @overload
+ def load(
+ self,
+ require: Literal[True] = True,
+ env: Environment | None = None,
+ installer: _InstallerType | None = None,
+ ) -> _ResolvedEntryPoint: ...
+ @overload
+ def load(
+ self,
+ require: Literal[False],
+ *args: Any,
+ **kwargs: Any,
+ ) -> _ResolvedEntryPoint: ...
+ def load(
+ self,
+ require: bool = True,
+ *args: Environment | _InstallerType | None,
+ **kwargs: Environment | _InstallerType | None,
+ ) -> _ResolvedEntryPoint:
+ """
+ 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:
+ # We could pass `env` and `installer` directly,
+ # but keeping `*args` and `**kwargs` for backwards compatibility
+ self.require(*args, **kwargs) # type: ignore[arg-type]
+ return self.resolve()
+
+ def resolve(self) -> _ResolvedEntryPoint:
+ """
+ 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)) from exc
+
+ def require(
+ self,
+ env: Environment | None = None,
+ installer: _InstallerType | None = None,
+ ) -> None:
+ if not self.dist:
+ error_cls = UnknownExtra if self.extras else AttributeError
+ raise error_cls("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: str, dist: Distribution | None = None) -> Self:
+ """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: str,
+ lines: _NestedStr,
+ dist: Distribution | None = None,
+ ) -> dict[str, Self]:
+ """Parse an entry point group"""
+ if not MODULE(group):
+ raise ValueError("Invalid group name", group)
+ this: dict[str, Self] = {}
+ 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: str | Iterable[str] | dict[str, str | Iterable[str]],
+ dist: Distribution | None = None,
+ ) -> dict[str, dict[str, Self]]:
+ """Parse a map of entry point groups"""
+ _data: Iterable[tuple[str | None, str | Iterable[str]]]
+ if isinstance(data, dict):
+ _data = data.items()
+ else:
+ _data = split_sections(data)
+ maps: dict[str, dict[str, Self]] = {}
+ 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 _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: str | None = None,
+ metadata: _MetadataType = None,
+ project_name: str | None = None,
+ version: str | None = None,
+ py_version: str | None = PY_MAJOR,
+ platform: str | None = None,
+ precedence: int = EGG_DIST,
+ ) -> None:
+ 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: str,
+ basename: StrPath,
+ metadata: _MetadataType = None,
+ **kw: int, # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility
+ ) -> Distribution:
+ 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._forgiving_parsed_version,
+ self.precedence,
+ self.key,
+ self.location,
+ self.py_version or '',
+ self.platform or '',
+ )
+
+ def __hash__(self) -> int:
+ return hash(self.hashcmp)
+
+ def __lt__(self, other: Distribution) -> bool:
+ return self.hashcmp < other.hashcmp
+
+ def __le__(self, other: Distribution) -> bool:
+ return self.hashcmp <= other.hashcmp
+
+ def __gt__(self, other: Distribution) -> bool:
+ return self.hashcmp > other.hashcmp
+
+ def __ge__(self, other: Distribution) -> bool:
+ return self.hashcmp >= other.hashcmp
+
+ def __eq__(self, other: object) -> bool:
+ 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: object) -> bool:
+ 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"):
+ try:
+ self._parsed_version = parse_version(self.version)
+ except packaging.version.InvalidVersion as ex:
+ info = f"(package: {self.project_name})"
+ if hasattr(ex, "add_note"):
+ ex.add_note(info) # PEP 678
+ raise
+ raise packaging.version.InvalidVersion(f"{str(ex)} {info}") from None
+
+ return self._parsed_version
+
+ @property
+ def _forgiving_parsed_version(self):
+ try:
+ return self.parsed_version
+ except packaging.version.InvalidVersion as ex:
+ self._parsed_version = parse_version(_forgiving_version(self.version))
+
+ notes = "\n".join(getattr(ex, "__notes__", [])) # PEP 678
+ msg = f"""!!\n\n
+ *************************************************************************
+ {str(ex)}\n{notes}
+
+ This is a long overdue deprecation.
+ For the time being, `pkg_resources` will use `{self._parsed_version}`
+ as a replacement to avoid breaking existing environments,
+ but no future compatibility is guaranteed.
+
+ If you maintain package {self.project_name} you should implement
+ the relevant changes to adequate the project to PEP 440 immediately.
+ *************************************************************************
+ \n\n!!
+ """
+ warnings.warn(msg, DeprecationWarning)
+
+ return self._parsed_version
+
+ @property
+ def version(self):
+ try:
+ return self._version
+ except AttributeError as e:
+ version = self._get_version()
+ if version is None:
+ path = self._get_metadata_path_for_display(self.PKG_INFO)
+ msg = f"Missing 'Version:' header and/or {self.PKG_INFO} file at path: {path}"
+ raise ValueError(msg, self) from e
+
+ 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: dict[str | None, list[Requirement]],
+ ) -> dict[str | None, list[Requirement]]:
+ """
+ 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: str | None = 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: Iterable[str] = ()) -> list[Requirement]:
+ """List of Requirements needed for this distro if `extras` are used"""
+ dm = self._dep_map
+ deps: list[Requirement] = []
+ deps.extend(dm.get(None, ()))
+ for ext in extras:
+ try:
+ deps.extend(dm[safe_extra(ext)])
+ except KeyError as e:
+ raise UnknownExtra(f"{self} has no such extra feature {ext!r}") from e
+ 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):
+ yield from self.get_metadata_lines(name)
+
+ def _get_version(self):
+ lines = self._get_metadata(self.PKG_INFO)
+ return _version_from_file(lines)
+
+ def activate(self, path: list[str] | None = None, replace: bool = False) -> None:
+ """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 and self.location is not None:
+ 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 = f"{to_filename(self.project_name)}-{to_filename(self.version)}-py{self.py_version or PY_MAJOR}"
+
+ if self.platform:
+ filename += '-' + self.platform
+ return filename
+
+ def __repr__(self) -> str:
+ if self.location:
+ return f"{self} ({self.location})"
+ else:
+ return str(self)
+
+ def __str__(self) -> str:
+ try:
+ version = getattr(self, 'version', None)
+ except ValueError:
+ version = None
+ version = version or "[unknown version]"
+ return f"{self.project_name} {version}"
+
+ def __getattr__(self, attr: str):
+ """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().__dir__())
+ | set(attr for attr in self._provider.__dir__() if not attr.startswith('_'))
+ )
+
+ @classmethod
+ def from_filename(
+ cls,
+ filename: StrPath,
+ metadata: _MetadataType = None,
+ **kw: int, # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility
+ ) -> Distribution:
+ 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 = f"{self.project_name}=={self.parsed_version}"
+ else:
+ spec = f"{self.project_name}==={self.parsed_version}"
+
+ return Requirement.parse(spec)
+
+ def load_entry_point(self, group: str, name: str) -> _ResolvedEntryPoint:
+ """Return the `name` entry point of `group` or raise ImportError"""
+ ep = self.get_entry_info(group, name)
+ if ep is None:
+ raise ImportError(f"Entry point {(group, name)!r} not found")
+ return ep.load()
+
+ @overload
+ def get_entry_map(self, group: None = None) -> dict[str, dict[str, EntryPoint]]: ...
+ @overload
+ def get_entry_map(self, group: str) -> dict[str, EntryPoint]: ...
+ def get_entry_map(self, group: str | None = None):
+ """Return the entry point map for `group`, or the full entry map"""
+ if not hasattr(self, "_ep_map"):
+ self._ep_map = EntryPoint.parse_map(
+ self._get_metadata('entry_points.txt'), self
+ )
+ if group is not None:
+ return self._ep_map.get(group, {})
+ return self._ep_map
+
+ def get_entry_info(self, group: str, name: str) -> EntryPoint | None:
+ """Return the EntryPoint object for `group`+`name`, or ``None``"""
+ return self.get_entry_map(group).get(name)
+
+ # FIXME: 'Distribution.insert_on' is too complex (13)
+ def insert_on( # noqa: C901
+ self,
+ path: list[str],
+ loc=None,
+ replace: bool = False,
+ ) -> None:
+ """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(
+ f"Module {modname} was already imported from {fn}, "
+ f"but {self.location} is being added to sys.path",
+ )
+
+ def has_version(self) -> bool:
+ try:
+ self.version
+ except ValueError:
+ issue_warning("Unbuilt egg for " + repr(self))
+ return False
+ except SystemError:
+ # TODO: remove this except clause when python/cpython#103632 is fixed.
+ return False
+ return True
+
+ def clone(self, **kw: str | int | IResourceProvider | None) -> Self:
+ """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)
+ # Unsafely unpacking. But keeping **kw for backwards and subclassing compatibility
+ return self.__class__(**kw) # type:ignore[arg-type]
+
+ @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) -> dict[str | None, list[Requirement]]:
+ """Recompute this distribution's dependencies."""
+ self.__dep_map: dict[str | None, list[Requirement]] = {None: []}
+
+ reqs: list[Requirement] = []
+ # 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 = types.MappingProxyType(dict.fromkeys(reqs_for_extra(None)))
+ self.__dep_map[None].extend(common)
+
+ for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []:
+ s_extra = safe_extra(extra.strip())
+ self.__dep_map[s_extra] = [
+ r for r in reqs_for_extra(extra) if r not in common
+ ]
+
+ return self.__dep_map
+
+
+_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)
+
+
+def parse_requirements(strs: _NestedStr) -> map[Requirement]:
+ """
+ Yield ``Requirement`` objects for each specification in `strs`.
+
+ `strs` must be a string, or a (possibly-nested) iterable thereof.
+ """
+ return map(Requirement, join_continuation(map(drop_comment, yield_lines(strs))))
+
+
+class RequirementParseError(packaging.requirements.InvalidRequirement):
+ "Compatibility wrapper for InvalidRequirement"
+
+
+class Requirement(packaging.requirements.Requirement):
+ # prefer variable length tuple to set (as found in
+ # packaging.requirements.Requirement)
+ extras: tuple[str, ...] # type: ignore[assignment]
+
+ def __init__(self, requirement_string: str) -> None:
+ """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!"""
+ super().__init__(requirement_string)
+ 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: object) -> bool:
+ return isinstance(other, Requirement) and self.hashCmp == other.hashCmp
+
+ def __ne__(self, other: object) -> bool:
+ return not self == other
+
+ def __contains__(
+ self, item: Distribution | packaging.specifiers.UnparsedVersion
+ ) -> bool:
+ if isinstance(item, Distribution):
+ if item.key != self.key:
+ return False
+
+ version = item.version
+ else:
+ version = item
+
+ # 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(
+ version,
+ prereleases=True,
+ )
+
+ def __hash__(self) -> int:
+ return self.__hash
+
+ def __repr__(self) -> str:
+ return f"Requirement.parse({str(self)!r})"
+
+ @staticmethod
+ def parse(s: str | Iterable[str]) -> Requirement:
+ (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: Mapping[type, _AdapterT], ob: object) -> _AdapterT:
+ """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]
+ # _find_adapter would previously return None, and immediately be called.
+ # So we're raising a TypeError to keep backward compatibility if anyone depended on that behaviour.
+ raise TypeError(f"Could not find adapter for {registry} and {ob}")
+
+
+def ensure_directory(path: StrOrBytesPath) -> None:
+ """Ensure that the parent directory of `path` exists"""
+ dirname = os.path.dirname(path)
+ os.makedirs(dirname, exist_ok=True)
+
+
+def _bypass_ensure_directory(path) -> None:
+ """Sandbox-bypassing version of ensure_directory()"""
+ if not WRITE_SUPPORT:
+ raise OSError('"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: _NestedStr) -> Iterator[tuple[str | None, list[str]]]:
+ """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: list[str] = []
+ 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)
+
+
+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.
+ """
+
+
+# Ported from ``setuptools`` to avoid introducing an import inter-dependency:
+_LOCALE_ENCODING = "locale" if sys.version_info >= (3, 10) else None
+
+
+# This must go before calls to `_call_aside`. See https://github.com/pypa/setuptools/pull/4422
+def _read_utf8_with_fallback(file: str, fallback_encoding=_LOCALE_ENCODING) -> str:
+ """See setuptools.unicode_utils._read_utf8_with_fallback"""
+ try:
+ with open(file, "r", encoding="utf-8") as f:
+ return f.read()
+ except UnicodeDecodeError: # pragma: no cover
+ msg = f"""\
+ ********************************************************************************
+ `encoding="utf-8"` fails with {file!r}, trying `encoding={fallback_encoding!r}`.
+
+ This fallback behaviour is considered **deprecated** and future versions of
+ `setuptools/pkg_resources` may not implement it.
+
+ Please encode {file!r} with "utf-8" to ensure future builds will succeed.
+
+ If this file was produced by `setuptools` itself, cleaning up the cached files
+ and re-building/re-installing the package with a newer version of `setuptools`
+ (e.g. by updating `build-system.requires` in its `pyproject.toml`)
+ might solve the problem.
+ ********************************************************************************
+ """
+ # TODO: Add a deadline?
+ # See comment in setuptools.unicode_utils._Utf8EncodingNeeded
+ warnings.warn(msg, PkgResourcesDeprecationWarning, stacklevel=2)
+ with open(file, "r", encoding=fallback_encoding) as f:
+ return f.read()
+
+
+# from jaraco.functools 1.3
+def _call_aside(f, *args, **kwargs):
+ f(*args, **kwargs)
+ return f
+
+
+@_call_aside
+def _initialize(g=globals()) -> None:
+ "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() -> None:
+ """
+ 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 = _declare_state('object', 'working_set', WorkingSet._build_master())
+
+ 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())
+
+
+if TYPE_CHECKING:
+ # All of these are set by the @_call_aside methods above
+ __resource_manager = ResourceManager() # Won't exist at runtime
+ resource_exists = __resource_manager.resource_exists
+ resource_isdir = __resource_manager.resource_isdir
+ resource_filename = __resource_manager.resource_filename
+ resource_stream = __resource_manager.resource_stream
+ resource_string = __resource_manager.resource_string
+ resource_listdir = __resource_manager.resource_listdir
+ set_extraction_path = __resource_manager.set_extraction_path
+ cleanup_resources = __resource_manager.cleanup_resources
+
+ working_set = WorkingSet()
+ require = working_set.require
+ iter_entry_points = working_set.iter_entry_points
+ add_activation_listener = working_set.subscribe
+ run_script = working_set.run_script
+ run_main = run_script
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pkg_resources/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..97f0f72
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pkg_resources/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/api_tests.txt b/testcline/lib/python3.12/site-packages/pkg_resources/api_tests.txt
new file mode 100644
index 0000000..d72b85a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/api_tests.txt
@@ -0,0 +1,424 @@
+Pluggable Distributions of Python Software
+==========================================
+
+Distributions
+-------------
+
+A "Distribution" is a collection of files that represent a "Release" of a
+"Project" as of a particular point in time, denoted by a
+"Version"::
+
+ >>> import sys, pkg_resources
+ >>> from pkg_resources import Distribution
+ >>> Distribution(project_name="Foo", version="1.2")
+ Foo 1.2
+
+Distributions have a location, which can be a filename, URL, or really anything
+else you care to use::
+
+ >>> dist = Distribution(
+ ... location="http://example.com/something",
+ ... project_name="Bar", version="0.9"
+ ... )
+
+ >>> dist
+ Bar 0.9 (http://example.com/something)
+
+
+Distributions have various introspectable attributes::
+
+ >>> dist.location
+ 'http://example.com/something'
+
+ >>> dist.project_name
+ 'Bar'
+
+ >>> dist.version
+ '0.9'
+
+ >>> dist.py_version == '{}.{}'.format(*sys.version_info)
+ True
+
+ >>> print(dist.platform)
+ None
+
+Including various computed attributes::
+
+ >>> from pkg_resources import parse_version
+ >>> dist.parsed_version == parse_version(dist.version)
+ True
+
+ >>> dist.key # case-insensitive form of the project name
+ 'bar'
+
+Distributions are compared (and hashed) by version first::
+
+ >>> Distribution(version='1.0') == Distribution(version='1.0')
+ True
+ >>> Distribution(version='1.0') == Distribution(version='1.1')
+ False
+ >>> Distribution(version='1.0') < Distribution(version='1.1')
+ True
+
+but also by project name (case-insensitive), platform, Python version,
+location, etc.::
+
+ >>> Distribution(project_name="Foo",version="1.0") == \
+ ... Distribution(project_name="Foo",version="1.0")
+ True
+
+ >>> Distribution(project_name="Foo",version="1.0") == \
+ ... Distribution(project_name="foo",version="1.0")
+ True
+
+ >>> Distribution(project_name="Foo",version="1.0") == \
+ ... Distribution(project_name="Foo",version="1.1")
+ False
+
+ >>> Distribution(project_name="Foo",py_version="2.3",version="1.0") == \
+ ... Distribution(project_name="Foo",py_version="2.4",version="1.0")
+ False
+
+ >>> Distribution(location="spam",version="1.0") == \
+ ... Distribution(location="spam",version="1.0")
+ True
+
+ >>> Distribution(location="spam",version="1.0") == \
+ ... Distribution(location="baz",version="1.0")
+ False
+
+
+
+Hash and compare distribution by prio/plat
+
+Get version from metadata
+provider capabilities
+egg_name()
+as_requirement()
+from_location, from_filename (w/path normalization)
+
+Releases may have zero or more "Requirements", which indicate
+what releases of another project the release requires in order to
+function. A Requirement names the other project, expresses some criteria
+as to what releases of that project are acceptable, and lists any "Extras"
+that the requiring release may need from that project. (An Extra is an
+optional feature of a Release, that can only be used if its additional
+Requirements are satisfied.)
+
+
+
+The Working Set
+---------------
+
+A collection of active distributions is called a Working Set. Note that a
+Working Set can contain any importable distribution, not just pluggable ones.
+For example, the Python standard library is an importable distribution that
+will usually be part of the Working Set, even though it is not pluggable.
+Similarly, when you are doing development work on a project, the files you are
+editing are also a Distribution. (And, with a little attention to the
+directory names used, and including some additional metadata, such a
+"development distribution" can be made pluggable as well.)
+
+ >>> from pkg_resources import WorkingSet
+
+A working set's entries are the sys.path entries that correspond to the active
+distributions. By default, the working set's entries are the items on
+``sys.path``::
+
+ >>> ws = WorkingSet()
+ >>> ws.entries == sys.path
+ True
+
+But you can also create an empty working set explicitly, and add distributions
+to it::
+
+ >>> ws = WorkingSet([])
+ >>> ws.add(dist)
+ >>> ws.entries
+ ['http://example.com/something']
+ >>> dist in ws
+ True
+ >>> Distribution('foo',version="") in ws
+ False
+
+And you can iterate over its distributions::
+
+ >>> list(ws)
+ [Bar 0.9 (http://example.com/something)]
+
+Adding the same distribution more than once is a no-op::
+
+ >>> ws.add(dist)
+ >>> list(ws)
+ [Bar 0.9 (http://example.com/something)]
+
+For that matter, adding multiple distributions for the same project also does
+nothing, because a working set can only hold one active distribution per
+project -- the first one added to it::
+
+ >>> ws.add(
+ ... Distribution(
+ ... 'http://example.com/something', project_name="Bar",
+ ... version="7.2"
+ ... )
+ ... )
+ >>> list(ws)
+ [Bar 0.9 (http://example.com/something)]
+
+You can append a path entry to a working set using ``add_entry()``::
+
+ >>> ws.entries
+ ['http://example.com/something']
+ >>> ws.add_entry(pkg_resources.__file__)
+ >>> ws.entries
+ ['http://example.com/something', '...pkg_resources...']
+
+Multiple additions result in multiple entries, even if the entry is already in
+the working set (because ``sys.path`` can contain the same entry more than
+once)::
+
+ >>> ws.add_entry(pkg_resources.__file__)
+ >>> ws.entries
+ ['...example.com...', '...pkg_resources...', '...pkg_resources...']
+
+And you can specify the path entry a distribution was found under, using the
+optional second parameter to ``add()``::
+
+ >>> ws = WorkingSet([])
+ >>> ws.add(dist,"foo")
+ >>> ws.entries
+ ['foo']
+
+But even if a distribution is found under multiple path entries, it still only
+shows up once when iterating the working set:
+
+ >>> ws.add_entry(ws.entries[0])
+ >>> list(ws)
+ [Bar 0.9 (http://example.com/something)]
+
+You can ask a WorkingSet to ``find()`` a distribution matching a requirement::
+
+ >>> from pkg_resources import Requirement
+ >>> print(ws.find(Requirement.parse("Foo==1.0"))) # no match, return None
+ None
+
+ >>> ws.find(Requirement.parse("Bar==0.9")) # match, return distribution
+ Bar 0.9 (http://example.com/something)
+
+Note that asking for a conflicting version of a distribution already in a
+working set triggers a ``pkg_resources.VersionConflict`` error:
+
+ >>> try:
+ ... ws.find(Requirement.parse("Bar==1.0"))
+ ... except pkg_resources.VersionConflict as exc:
+ ... print(str(exc))
+ ... else:
+ ... raise AssertionError("VersionConflict was not raised")
+ (Bar 0.9 (http://example.com/something), Requirement.parse('Bar==1.0'))
+
+You can subscribe a callback function to receive notifications whenever a new
+distribution is added to a working set. The callback is immediately invoked
+once for each existing distribution in the working set, and then is called
+again for new distributions added thereafter::
+
+ >>> def added(dist): print("Added %s" % dist)
+ >>> ws.subscribe(added)
+ Added Bar 0.9
+ >>> foo12 = Distribution(project_name="Foo", version="1.2", location="f12")
+ >>> ws.add(foo12)
+ Added Foo 1.2
+
+Note, however, that only the first distribution added for a given project name
+will trigger a callback, even during the initial ``subscribe()`` callback::
+
+ >>> foo14 = Distribution(project_name="Foo", version="1.4", location="f14")
+ >>> ws.add(foo14) # no callback, because Foo 1.2 is already active
+
+ >>> ws = WorkingSet([])
+ >>> ws.add(foo12)
+ >>> ws.add(foo14)
+ >>> ws.subscribe(added)
+ Added Foo 1.2
+
+And adding a callback more than once has no effect, either::
+
+ >>> ws.subscribe(added) # no callbacks
+
+ # and no double-callbacks on subsequent additions, either
+ >>> just_a_test = Distribution(project_name="JustATest", version="0.99")
+ >>> ws.add(just_a_test)
+ Added JustATest 0.99
+
+
+Finding Plugins
+---------------
+
+``WorkingSet`` objects can be used to figure out what plugins in an
+``Environment`` can be loaded without any resolution errors::
+
+ >>> from pkg_resources import Environment
+
+ >>> plugins = Environment([]) # normally, a list of plugin directories
+ >>> plugins.add(foo12)
+ >>> plugins.add(foo14)
+ >>> plugins.add(just_a_test)
+
+In the simplest case, we just get the newest version of each distribution in
+the plugin environment::
+
+ >>> ws = WorkingSet([])
+ >>> ws.find_plugins(plugins)
+ ([JustATest 0.99, Foo 1.4 (f14)], {})
+
+But if there's a problem with a version conflict or missing requirements, the
+method falls back to older versions, and the error info dict will contain an
+exception instance for each unloadable plugin::
+
+ >>> ws.add(foo12) # this will conflict with Foo 1.4
+ >>> ws.find_plugins(plugins)
+ ([JustATest 0.99, Foo 1.2 (f12)], {Foo 1.4 (f14): VersionConflict(...)})
+
+But if you disallow fallbacks, the failed plugin will be skipped instead of
+trying older versions::
+
+ >>> ws.find_plugins(plugins, fallback=False)
+ ([JustATest 0.99], {Foo 1.4 (f14): VersionConflict(...)})
+
+
+
+Platform Compatibility Rules
+----------------------------
+
+On the Mac, there are potential compatibility issues for modules compiled
+on newer versions of macOS than what the user is running. Additionally,
+macOS will soon have two platforms to contend with: Intel and PowerPC.
+
+Basic equality works as on other platforms::
+
+ >>> from pkg_resources import compatible_platforms as cp
+ >>> reqd = 'macosx-10.4-ppc'
+ >>> cp(reqd, reqd)
+ True
+ >>> cp("win32", reqd)
+ False
+
+Distributions made on other machine types are not compatible::
+
+ >>> cp("macosx-10.4-i386", reqd)
+ False
+
+Distributions made on earlier versions of the OS are compatible, as
+long as they are from the same top-level version. The patchlevel version
+number does not matter::
+
+ >>> cp("macosx-10.4-ppc", reqd)
+ True
+ >>> cp("macosx-10.3-ppc", reqd)
+ True
+ >>> cp("macosx-10.5-ppc", reqd)
+ False
+ >>> cp("macosx-9.5-ppc", reqd)
+ False
+
+Backwards compatibility for packages made via earlier versions of
+setuptools is provided as well::
+
+ >>> cp("darwin-8.2.0-Power_Macintosh", reqd)
+ True
+ >>> cp("darwin-7.2.0-Power_Macintosh", reqd)
+ True
+ >>> cp("darwin-8.2.0-Power_Macintosh", "macosx-10.3-ppc")
+ False
+
+
+Environment Markers
+-------------------
+
+ >>> from pkg_resources import invalid_marker as im, evaluate_marker as em
+ >>> import os
+
+ >>> print(im("sys_platform"))
+ Expected marker operator, one of <=, <, !=, ==, >=, >, ~=, ===, in, not in
+ sys_platform
+ ^
+
+ >>> print(im("sys_platform=="))
+ Expected a marker variable or quoted string
+ sys_platform==
+ ^
+
+ >>> print(im("sys_platform=='win32'"))
+ False
+
+ >>> print(im("sys=='x'"))
+ Expected a marker variable or quoted string
+ sys=='x'
+ ^
+
+ >>> print(im("(extra)"))
+ Expected marker operator, one of <=, <, !=, ==, >=, >, ~=, ===, in, not in
+ (extra)
+ ^
+
+ >>> print(im("(extra"))
+ Expected marker operator, one of <=, <, !=, ==, >=, >, ~=, ===, in, not in
+ (extra
+ ^
+
+ >>> print(im("os.open('foo')=='y'"))
+ Expected a marker variable or quoted string
+ os.open('foo')=='y'
+ ^
+
+ >>> print(im("'x'=='y' and os.open('foo')=='y'")) # no short-circuit!
+ Expected a marker variable or quoted string
+ 'x'=='y' and os.open('foo')=='y'
+ ^
+
+ >>> print(im("'x'=='x' or os.open('foo')=='y'")) # no short-circuit!
+ Expected a marker variable or quoted string
+ 'x'=='x' or os.open('foo')=='y'
+ ^
+
+ >>> print(im("r'x'=='x'"))
+ Expected a marker variable or quoted string
+ r'x'=='x'
+ ^
+
+ >>> print(im("'''x'''=='x'"))
+ Expected marker operator, one of <=, <, !=, ==, >=, >, ~=, ===, in, not in
+ '''x'''=='x'
+ ^
+
+ >>> print(im('"""x"""=="x"'))
+ Expected marker operator, one of <=, <, !=, ==, >=, >, ~=, ===, in, not in
+ """x"""=="x"
+ ^
+
+ >>> print(im(r"x\n=='x'"))
+ Expected a marker variable or quoted string
+ x\n=='x'
+ ^
+
+ >>> print(im("os.open=='y'"))
+ Expected a marker variable or quoted string
+ os.open=='y'
+ ^
+
+ >>> em("sys_platform=='win32'") == (sys.platform=='win32')
+ True
+
+ >>> em("python_version >= '2.7'")
+ True
+
+ >>> em("python_version > '2.6'")
+ True
+
+ >>> im("implementation_name=='cpython'")
+ False
+
+ >>> im("platform_python_implementation=='CPython'")
+ False
+
+ >>> im("implementation_version=='3.5.1'")
+ False
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/py.typed b/testcline/lib/python3.12/site-packages/pkg_resources/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/__init__.py b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..e3bd852
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_find_distributions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_find_distributions.cpython-312.pyc
new file mode 100644
index 0000000..f78309b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_find_distributions.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_integration_zope_interface.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_integration_zope_interface.cpython-312.pyc
new file mode 100644
index 0000000..f43a404
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_integration_zope_interface.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_markers.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_markers.cpython-312.pyc
new file mode 100644
index 0000000..c53f2cf
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_markers.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_pkg_resources.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_pkg_resources.cpython-312.pyc
new file mode 100644
index 0000000..0281cce
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_pkg_resources.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_resources.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_resources.cpython-312.pyc
new file mode 100644
index 0000000..0344056
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_resources.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_working_set.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_working_set.cpython-312.pyc
new file mode 100644
index 0000000..939ade9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pkg_resources/tests/__pycache__/test_working_set.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package-source/__pycache__/setup.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package-source/__pycache__/setup.cpython-312.pyc
new file mode 100644
index 0000000..45591c3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package-source/__pycache__/setup.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package-source/setup.cfg b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package-source/setup.cfg
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package-source/setup.py b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package-source/setup.py
new file mode 100644
index 0000000..ce90806
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package-source/setup.py
@@ -0,0 +1,7 @@
+import setuptools
+
+setuptools.setup(
+ name="my-test-package",
+ version="1.0",
+ zip_safe=True,
+)
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package-zip/my-test-package.zip b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package-zip/my-test-package.zip
new file mode 100644
index 0000000..81f9a01
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package-zip/my-test-package.zip differ
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/PKG-INFO b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/PKG-INFO
new file mode 100644
index 0000000..7328e3f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/PKG-INFO
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: my-test-package
+Version: 1.0
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: UNKNOWN
+Author-email: UNKNOWN
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/SOURCES.txt b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/SOURCES.txt
new file mode 100644
index 0000000..3c4ee16
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/SOURCES.txt
@@ -0,0 +1,7 @@
+setup.cfg
+setup.py
+my_test_package.egg-info/PKG-INFO
+my_test_package.egg-info/SOURCES.txt
+my_test_package.egg-info/dependency_links.txt
+my_test_package.egg-info/top_level.txt
+my_test_package.egg-info/zip-safe
\ No newline at end of file
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/dependency_links.txt b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/top_level.txt b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/top_level.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/top_level.txt
@@ -0,0 +1 @@
+
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/zip-safe b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/zip-safe
@@ -0,0 +1 @@
+
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_zipped-egg/my_test_package-1.0-py3.7.egg b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_zipped-egg/my_test_package-1.0-py3.7.egg
new file mode 100644
index 0000000..5115b89
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pkg_resources/tests/data/my-test-package_zipped-egg/my_test_package-1.0-py3.7.egg differ
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_find_distributions.py b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_find_distributions.py
new file mode 100644
index 0000000..301b36d
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_find_distributions.py
@@ -0,0 +1,56 @@
+import shutil
+from pathlib import Path
+
+import pytest
+
+import pkg_resources
+
+TESTS_DATA_DIR = Path(__file__).parent / 'data'
+
+
+class TestFindDistributions:
+ @pytest.fixture
+ def target_dir(self, tmpdir):
+ target_dir = tmpdir.mkdir('target')
+ # place a .egg named directory in the target that is not an egg:
+ target_dir.mkdir('not.an.egg')
+ return target_dir
+
+ def test_non_egg_dir_named_egg(self, target_dir):
+ dists = pkg_resources.find_distributions(str(target_dir))
+ assert not list(dists)
+
+ def test_standalone_egg_directory(self, target_dir):
+ shutil.copytree(
+ TESTS_DATA_DIR / 'my-test-package_unpacked-egg',
+ target_dir,
+ dirs_exist_ok=True,
+ )
+ dists = pkg_resources.find_distributions(str(target_dir))
+ assert [dist.project_name for dist in dists] == ['my-test-package']
+ dists = pkg_resources.find_distributions(str(target_dir), only=True)
+ assert not list(dists)
+
+ def test_zipped_egg(self, target_dir):
+ shutil.copytree(
+ TESTS_DATA_DIR / 'my-test-package_zipped-egg',
+ target_dir,
+ dirs_exist_ok=True,
+ )
+ dists = pkg_resources.find_distributions(str(target_dir))
+ assert [dist.project_name for dist in dists] == ['my-test-package']
+ dists = pkg_resources.find_distributions(str(target_dir), only=True)
+ assert not list(dists)
+
+ def test_zipped_sdist_one_level_removed(self, target_dir):
+ shutil.copytree(
+ TESTS_DATA_DIR / 'my-test-package-zip', target_dir, dirs_exist_ok=True
+ )
+ dists = pkg_resources.find_distributions(
+ str(target_dir / "my-test-package.zip")
+ )
+ assert [dist.project_name for dist in dists] == ['my-test-package']
+ dists = pkg_resources.find_distributions(
+ str(target_dir / "my-test-package.zip"), only=True
+ )
+ assert not list(dists)
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_integration_zope_interface.py b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_integration_zope_interface.py
new file mode 100644
index 0000000..4e37c34
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_integration_zope_interface.py
@@ -0,0 +1,54 @@
+import platform
+from inspect import cleandoc
+
+import jaraco.path
+import pytest
+
+pytestmark = pytest.mark.integration
+
+
+# For the sake of simplicity this test uses fixtures defined in
+# `setuptools.test.fixtures`,
+# and it also exercise conditions considered deprecated...
+# So if needed this test can be deleted.
+@pytest.mark.skipif(
+ platform.system() != "Linux",
+ reason="only demonstrated to fail on Linux in #4399",
+)
+def test_interop_pkg_resources_iter_entry_points(tmp_path, venv):
+ """
+ Importing pkg_resources.iter_entry_points on console_scripts
+ seems to cause trouble with zope-interface, when deprecates installation method
+ is used. See #4399.
+ """
+ project = {
+ "pkg": {
+ "foo.py": cleandoc(
+ """
+ from pkg_resources import iter_entry_points
+
+ def bar():
+ print("Print me if you can")
+ """
+ ),
+ "setup.py": cleandoc(
+ """
+ from setuptools import setup, find_packages
+
+ setup(
+ install_requires=["zope-interface==6.4.post2"],
+ entry_points={
+ "console_scripts": [
+ "foo=foo:bar",
+ ],
+ },
+ )
+ """
+ ),
+ }
+ }
+ jaraco.path.build(project, prefix=tmp_path)
+ cmd = ["pip", "install", "-e", ".", "--no-use-pep517"]
+ venv.run(cmd, cwd=tmp_path / "pkg") # Needs this version of pkg_resources installed
+ out = venv.run(["foo"])
+ assert "Print me if you can" in out
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_markers.py b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_markers.py
new file mode 100644
index 0000000..9306d5b
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_markers.py
@@ -0,0 +1,8 @@
+from unittest import mock
+
+from pkg_resources import evaluate_marker
+
+
+@mock.patch('platform.python_version', return_value='2.7.10')
+def test_ordering(python_version_mock):
+ assert evaluate_marker("python_full_version > '2.7.3'") is True
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_pkg_resources.py b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_pkg_resources.py
new file mode 100644
index 0000000..cfc9b16
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_pkg_resources.py
@@ -0,0 +1,485 @@
+from __future__ import annotations
+
+import builtins
+import datetime
+import inspect
+import os
+import plistlib
+import stat
+import subprocess
+import sys
+import tempfile
+import zipfile
+from unittest import mock
+
+import pytest
+
+import pkg_resources
+from pkg_resources import DistInfoDistribution, Distribution, EggInfoDistribution
+
+import distutils.command.install_egg_info
+import distutils.dist
+
+
+class EggRemover(str):
+ def __call__(self):
+ if self in sys.path:
+ sys.path.remove(self)
+ if os.path.exists(self):
+ os.remove(self)
+
+
+class TestZipProvider:
+ finalizers: list[EggRemover] = []
+
+ ref_time = datetime.datetime(2013, 5, 12, 13, 25, 0)
+ "A reference time for a file modification"
+
+ @classmethod
+ def setup_class(cls):
+ "create a zip egg and add it to sys.path"
+ egg = tempfile.NamedTemporaryFile(suffix='.egg', delete=False)
+ zip_egg = zipfile.ZipFile(egg, 'w')
+ zip_info = zipfile.ZipInfo()
+ zip_info.filename = 'mod.py'
+ zip_info.date_time = cls.ref_time.timetuple()
+ zip_egg.writestr(zip_info, 'x = 3\n')
+ zip_info = zipfile.ZipInfo()
+ zip_info.filename = 'data.dat'
+ zip_info.date_time = cls.ref_time.timetuple()
+ zip_egg.writestr(zip_info, 'hello, world!')
+ zip_info = zipfile.ZipInfo()
+ zip_info.filename = 'subdir/mod2.py'
+ zip_info.date_time = cls.ref_time.timetuple()
+ zip_egg.writestr(zip_info, 'x = 6\n')
+ zip_info = zipfile.ZipInfo()
+ zip_info.filename = 'subdir/data2.dat'
+ zip_info.date_time = cls.ref_time.timetuple()
+ zip_egg.writestr(zip_info, 'goodbye, world!')
+ zip_egg.close()
+ egg.close()
+
+ sys.path.append(egg.name)
+ subdir = os.path.join(egg.name, 'subdir')
+ sys.path.append(subdir)
+ cls.finalizers.append(EggRemover(subdir))
+ cls.finalizers.append(EggRemover(egg.name))
+
+ @classmethod
+ def teardown_class(cls):
+ for finalizer in cls.finalizers:
+ finalizer()
+
+ def test_resource_listdir(self):
+ import mod # pyright: ignore[reportMissingImports] # Temporary package for test
+
+ zp = pkg_resources.ZipProvider(mod)
+
+ expected_root = ['data.dat', 'mod.py', 'subdir']
+ assert sorted(zp.resource_listdir('')) == expected_root
+
+ expected_subdir = ['data2.dat', 'mod2.py']
+ assert sorted(zp.resource_listdir('subdir')) == expected_subdir
+ assert sorted(zp.resource_listdir('subdir/')) == expected_subdir
+
+ assert zp.resource_listdir('nonexistent') == []
+ assert zp.resource_listdir('nonexistent/') == []
+
+ import mod2 # pyright: ignore[reportMissingImports] # Temporary package for test
+
+ zp2 = pkg_resources.ZipProvider(mod2)
+
+ assert sorted(zp2.resource_listdir('')) == expected_subdir
+
+ assert zp2.resource_listdir('subdir') == []
+ assert zp2.resource_listdir('subdir/') == []
+
+ def test_resource_filename_rewrites_on_change(self):
+ """
+ If a previous call to get_resource_filename has saved the file, but
+ the file has been subsequently mutated with different file of the
+ same size and modification time, it should not be overwritten on a
+ subsequent call to get_resource_filename.
+ """
+ import mod # pyright: ignore[reportMissingImports] # Temporary package for test
+
+ manager = pkg_resources.ResourceManager()
+ zp = pkg_resources.ZipProvider(mod)
+ filename = zp.get_resource_filename(manager, 'data.dat')
+ actual = datetime.datetime.fromtimestamp(os.stat(filename).st_mtime)
+ assert actual == self.ref_time
+ f = open(filename, 'w', encoding="utf-8")
+ f.write('hello, world?')
+ f.close()
+ ts = self.ref_time.timestamp()
+ os.utime(filename, (ts, ts))
+ filename = zp.get_resource_filename(manager, 'data.dat')
+ with open(filename, encoding="utf-8") as f:
+ assert f.read() == 'hello, world!'
+ manager.cleanup_resources()
+
+
+class TestResourceManager:
+ def test_get_cache_path(self):
+ mgr = pkg_resources.ResourceManager()
+ path = mgr.get_cache_path('foo')
+ type_ = str(type(path))
+ message = "Unexpected type from get_cache_path: " + type_
+ assert isinstance(path, str), message
+
+ def test_get_cache_path_race(self, tmpdir):
+ # Patch to os.path.isdir to create a race condition
+ def patched_isdir(dirname, unpatched_isdir=pkg_resources.isdir):
+ patched_isdir.dirnames.append(dirname)
+
+ was_dir = unpatched_isdir(dirname)
+ if not was_dir:
+ os.makedirs(dirname)
+ return was_dir
+
+ patched_isdir.dirnames = []
+
+ # Get a cache path with a "race condition"
+ mgr = pkg_resources.ResourceManager()
+ mgr.set_extraction_path(str(tmpdir))
+
+ archive_name = os.sep.join(('foo', 'bar', 'baz'))
+ with mock.patch.object(pkg_resources, 'isdir', new=patched_isdir):
+ mgr.get_cache_path(archive_name)
+
+ # Because this test relies on the implementation details of this
+ # function, these assertions are a sentinel to ensure that the
+ # test suite will not fail silently if the implementation changes.
+ called_dirnames = patched_isdir.dirnames
+ assert len(called_dirnames) == 2
+ assert called_dirnames[0].split(os.sep)[-2:] == ['foo', 'bar']
+ assert called_dirnames[1].split(os.sep)[-1:] == ['foo']
+
+ """
+ Tests to ensure that pkg_resources runs independently from setuptools.
+ """
+
+ def test_setuptools_not_imported(self):
+ """
+ In a separate Python environment, import pkg_resources and assert
+ that action doesn't cause setuptools to be imported.
+ """
+ lines = (
+ 'import pkg_resources',
+ 'import sys',
+ ('assert "setuptools" not in sys.modules, "setuptools was imported"'),
+ )
+ cmd = [sys.executable, '-c', '; '.join(lines)]
+ subprocess.check_call(cmd)
+
+
+def make_test_distribution(metadata_path, metadata):
+ """
+ Make a test Distribution object, and return it.
+
+ :param metadata_path: the path to the metadata file that should be
+ created. This should be inside a distribution directory that should
+ also be created. For example, an argument value might end with
+ ".dist-info/METADATA".
+ :param metadata: the desired contents of the metadata file, as bytes.
+ """
+ dist_dir = os.path.dirname(metadata_path)
+ os.mkdir(dist_dir)
+ with open(metadata_path, 'wb') as f:
+ f.write(metadata)
+ dists = list(pkg_resources.distributions_from_metadata(dist_dir))
+ (dist,) = dists
+
+ return dist
+
+
+def test_get_metadata__bad_utf8(tmpdir):
+ """
+ Test a metadata file with bytes that can't be decoded as utf-8.
+ """
+ filename = 'METADATA'
+ # Convert the tmpdir LocalPath object to a string before joining.
+ metadata_path = os.path.join(str(tmpdir), 'foo.dist-info', filename)
+ # Encode a non-ascii string with the wrong encoding (not utf-8).
+ metadata = 'née'.encode('iso-8859-1')
+ dist = make_test_distribution(metadata_path, metadata=metadata)
+
+ with pytest.raises(UnicodeDecodeError) as excinfo:
+ dist.get_metadata(filename)
+
+ exc = excinfo.value
+ actual = str(exc)
+ expected = (
+ # The error message starts with "'utf-8' codec ..." However, the
+ # spelling of "utf-8" can vary (e.g. "utf8") so we don't include it
+ "codec can't decode byte 0xe9 in position 1: "
+ 'invalid continuation byte in METADATA file at path: '
+ )
+ assert expected in actual, f'actual: {actual}'
+ assert actual.endswith(metadata_path), f'actual: {actual}'
+
+
+def make_distribution_no_version(tmpdir, basename):
+ """
+ Create a distribution directory with no file containing the version.
+ """
+ dist_dir = tmpdir / basename
+ dist_dir.ensure_dir()
+ # Make the directory non-empty so distributions_from_metadata()
+ # will detect it and yield it.
+ dist_dir.join('temp.txt').ensure()
+
+ dists = list(pkg_resources.distributions_from_metadata(dist_dir))
+ assert len(dists) == 1
+ (dist,) = dists
+
+ return dist, dist_dir
+
+
+@pytest.mark.parametrize(
+ ("suffix", "expected_filename", "expected_dist_type"),
+ [
+ ('egg-info', 'PKG-INFO', EggInfoDistribution),
+ ('dist-info', 'METADATA', DistInfoDistribution),
+ ],
+)
+@pytest.mark.xfail(
+ sys.version_info[:2] == (3, 12) and sys.version_info.releaselevel != 'final',
+ reason="https://github.com/python/cpython/issues/103632",
+)
+def test_distribution_version_missing(
+ tmpdir, suffix, expected_filename, expected_dist_type
+):
+ """
+ Test Distribution.version when the "Version" header is missing.
+ """
+ basename = f'foo.{suffix}'
+ dist, dist_dir = make_distribution_no_version(tmpdir, basename)
+
+ expected_text = (
+ f"Missing 'Version:' header and/or {expected_filename} file at path: "
+ )
+ metadata_path = os.path.join(dist_dir, expected_filename)
+
+ # Now check the exception raised when the "version" attribute is accessed.
+ with pytest.raises(ValueError) as excinfo:
+ dist.version
+
+ err = str(excinfo.value)
+ # Include a string expression after the assert so the full strings
+ # will be visible for inspection on failure.
+ assert expected_text in err, str((expected_text, err))
+
+ # Also check the args passed to the ValueError.
+ msg, dist = excinfo.value.args
+ assert expected_text in msg
+ # Check that the message portion contains the path.
+ assert metadata_path in msg, str((metadata_path, msg))
+ assert type(dist) is expected_dist_type
+
+
+@pytest.mark.xfail(
+ sys.version_info[:2] == (3, 12) and sys.version_info.releaselevel != 'final',
+ reason="https://github.com/python/cpython/issues/103632",
+)
+def test_distribution_version_missing_undetected_path():
+ """
+ Test Distribution.version when the "Version" header is missing and
+ the path can't be detected.
+ """
+ # Create a Distribution object with no metadata argument, which results
+ # in an empty metadata provider.
+ dist = Distribution('/foo')
+ with pytest.raises(ValueError) as excinfo:
+ dist.version
+
+ msg, dist = excinfo.value.args
+ expected = (
+ "Missing 'Version:' header and/or PKG-INFO file at path: [could not detect]"
+ )
+ assert msg == expected
+
+
+@pytest.mark.parametrize('only', [False, True])
+def test_dist_info_is_not_dir(tmp_path, only):
+ """Test path containing a file with dist-info extension."""
+ dist_info = tmp_path / 'foobar.dist-info'
+ dist_info.touch()
+ assert not pkg_resources.dist_factory(str(tmp_path), str(dist_info), only)
+
+
+def test_macos_vers_fallback(monkeypatch, tmp_path):
+ """Regression test for pkg_resources._macos_vers"""
+ orig_open = builtins.open
+
+ # Pretend we need to use the plist file
+ monkeypatch.setattr('platform.mac_ver', mock.Mock(return_value=('', (), '')))
+
+ # Create fake content for the fake plist file
+ with open(tmp_path / 'fake.plist', 'wb') as fake_file:
+ plistlib.dump({"ProductVersion": "11.4"}, fake_file)
+
+ # Pretend the fake file exists
+ monkeypatch.setattr('os.path.exists', mock.Mock(return_value=True))
+
+ def fake_open(file, *args, **kwargs):
+ return orig_open(tmp_path / 'fake.plist', *args, **kwargs)
+
+ # Ensure that the _macos_vers works correctly
+ with mock.patch('builtins.open', mock.Mock(side_effect=fake_open)) as m:
+ pkg_resources._macos_vers.cache_clear()
+ assert pkg_resources._macos_vers() == ["11", "4"]
+ pkg_resources._macos_vers.cache_clear()
+
+ m.assert_called()
+
+
+class TestDeepVersionLookupDistutils:
+ @pytest.fixture
+ def env(self, tmpdir):
+ """
+ Create a package environment, similar to a virtualenv,
+ in which packages are installed.
+ """
+
+ class Environment(str):
+ pass
+
+ env = Environment(tmpdir)
+ tmpdir.chmod(stat.S_IRWXU)
+ subs = 'home', 'lib', 'scripts', 'data', 'egg-base'
+ env.paths = dict((dirname, str(tmpdir / dirname)) for dirname in subs)
+ list(map(os.mkdir, env.paths.values()))
+ return env
+
+ def create_foo_pkg(self, env, version):
+ """
+ Create a foo package installed (distutils-style) to env.paths['lib']
+ as version.
+ """
+ ld = "This package has unicode metadata! ❄"
+ attrs = dict(name='foo', version=version, long_description=ld)
+ dist = distutils.dist.Distribution(attrs)
+ iei_cmd = distutils.command.install_egg_info.install_egg_info(dist)
+ iei_cmd.initialize_options()
+ iei_cmd.install_dir = env.paths['lib']
+ iei_cmd.finalize_options()
+ iei_cmd.run()
+
+ def test_version_resolved_from_egg_info(self, env):
+ version = '1.11.0.dev0+2329eae'
+ self.create_foo_pkg(env, version)
+
+ # this requirement parsing will raise a VersionConflict unless the
+ # .egg-info file is parsed (see #419 on BitBucket)
+ req = pkg_resources.Requirement.parse('foo>=1.9')
+ dist = pkg_resources.WorkingSet([env.paths['lib']]).find(req)
+ assert dist.version == version
+
+ @pytest.mark.parametrize(
+ ("unnormalized", "normalized"),
+ [
+ ('foo', 'foo'),
+ ('foo/', 'foo'),
+ ('foo/bar', 'foo/bar'),
+ ('foo/bar/', 'foo/bar'),
+ ],
+ )
+ def test_normalize_path_trailing_sep(self, unnormalized, normalized):
+ """Ensure the trailing slash is cleaned for path comparison.
+
+ See pypa/setuptools#1519.
+ """
+ result_from_unnormalized = pkg_resources.normalize_path(unnormalized)
+ result_from_normalized = pkg_resources.normalize_path(normalized)
+ assert result_from_unnormalized == result_from_normalized
+
+ @pytest.mark.skipif(
+ os.path.normcase('A') != os.path.normcase('a'),
+ reason='Testing case-insensitive filesystems.',
+ )
+ @pytest.mark.parametrize(
+ ("unnormalized", "normalized"),
+ [
+ ('MiXeD/CasE', 'mixed/case'),
+ ],
+ )
+ def test_normalize_path_normcase(self, unnormalized, normalized):
+ """Ensure mixed case is normalized on case-insensitive filesystems."""
+ result_from_unnormalized = pkg_resources.normalize_path(unnormalized)
+ result_from_normalized = pkg_resources.normalize_path(normalized)
+ assert result_from_unnormalized == result_from_normalized
+
+ @pytest.mark.skipif(
+ os.path.sep != '\\',
+ reason='Testing systems using backslashes as path separators.',
+ )
+ @pytest.mark.parametrize(
+ ("unnormalized", "expected"),
+ [
+ ('forward/slash', 'forward\\slash'),
+ ('forward/slash/', 'forward\\slash'),
+ ('backward\\slash\\', 'backward\\slash'),
+ ],
+ )
+ def test_normalize_path_backslash_sep(self, unnormalized, expected):
+ """Ensure path seps are cleaned on backslash path sep systems."""
+ result = pkg_resources.normalize_path(unnormalized)
+ assert result.endswith(expected)
+
+
+class TestWorkdirRequire:
+ def fake_site_packages(self, tmp_path, monkeypatch, dist_files):
+ site_packages = tmp_path / "site-packages"
+ site_packages.mkdir()
+ for file, content in self.FILES.items():
+ path = site_packages / file
+ path.parent.mkdir(exist_ok=True, parents=True)
+ path.write_text(inspect.cleandoc(content), encoding="utf-8")
+
+ monkeypatch.setattr(sys, "path", [site_packages])
+ return os.fspath(site_packages)
+
+ FILES = {
+ "pkg1_mod-1.2.3.dist-info/METADATA": """
+ Metadata-Version: 2.4
+ Name: pkg1.mod
+ Version: 1.2.3
+ """,
+ "pkg2.mod-0.42.dist-info/METADATA": """
+ Metadata-Version: 2.1
+ Name: pkg2.mod
+ Version: 0.42
+ """,
+ "pkg3_mod.egg-info/PKG-INFO": """
+ Name: pkg3.mod
+ Version: 1.2.3.4
+ """,
+ "pkg4.mod.egg-info/PKG-INFO": """
+ Name: pkg4.mod
+ Version: 0.42.1
+ """,
+ }
+
+ @pytest.mark.parametrize(
+ ("version", "requirement"),
+ [
+ ("1.2.3", "pkg1.mod>=1"),
+ ("0.42", "pkg2.mod>=0.4"),
+ ("1.2.3.4", "pkg3.mod<=2"),
+ ("0.42.1", "pkg4.mod>0.2,<1"),
+ ],
+ )
+ def test_require_non_normalised_name(
+ self, tmp_path, monkeypatch, version, requirement
+ ):
+ # https://github.com/pypa/setuptools/issues/4853
+ site_packages = self.fake_site_packages(tmp_path, monkeypatch, self.FILES)
+ ws = pkg_resources.WorkingSet([site_packages])
+
+ for req in [requirement, requirement.replace(".", "-")]:
+ [dist] = ws.require(req)
+ assert dist.version == version
+ assert os.path.samefile(
+ os.path.commonpath([dist.location, site_packages]), site_packages
+ )
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_resources.py b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_resources.py
new file mode 100644
index 0000000..70436c0
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_resources.py
@@ -0,0 +1,869 @@
+import itertools
+import os
+import platform
+import string
+import sys
+
+import pytest
+from packaging.specifiers import SpecifierSet
+
+import pkg_resources
+from pkg_resources import (
+ Distribution,
+ EntryPoint,
+ Requirement,
+ VersionConflict,
+ WorkingSet,
+ parse_requirements,
+ parse_version,
+ safe_name,
+ safe_version,
+)
+
+
+# from Python 3.6 docs. Available from itertools on Python 3.10
+def pairwise(iterable):
+ "s -> (s0,s1), (s1,s2), (s2, s3), ..."
+ a, b = itertools.tee(iterable)
+ next(b, None)
+ return zip(a, b)
+
+
+class Metadata(pkg_resources.EmptyProvider):
+ """Mock object to return metadata as if from an on-disk distribution"""
+
+ def __init__(self, *pairs) -> None:
+ self.metadata = dict(pairs)
+
+ def has_metadata(self, name) -> bool:
+ return name in self.metadata
+
+ def get_metadata(self, name):
+ return self.metadata[name]
+
+ def get_metadata_lines(self, name):
+ return pkg_resources.yield_lines(self.get_metadata(name))
+
+
+dist_from_fn = pkg_resources.Distribution.from_filename
+
+
+class TestDistro:
+ def testCollection(self):
+ # empty path should produce no distributions
+ ad = pkg_resources.Environment([], platform=None, python=None)
+ assert list(ad) == []
+ assert ad['FooPkg'] == []
+ ad.add(dist_from_fn("FooPkg-1.3_1.egg"))
+ ad.add(dist_from_fn("FooPkg-1.4-py2.4-win32.egg"))
+ ad.add(dist_from_fn("FooPkg-1.2-py2.4.egg"))
+
+ # Name is in there now
+ assert ad['FooPkg']
+ # But only 1 package
+ assert list(ad) == ['foopkg']
+
+ # Distributions sort by version
+ expected = ['1.4', '1.3-1', '1.2']
+ assert [dist.version for dist in ad['FooPkg']] == expected
+
+ # Removing a distribution leaves sequence alone
+ ad.remove(ad['FooPkg'][1])
+ assert [dist.version for dist in ad['FooPkg']] == ['1.4', '1.2']
+
+ # And inserting adds them in order
+ ad.add(dist_from_fn("FooPkg-1.9.egg"))
+ assert [dist.version for dist in ad['FooPkg']] == ['1.9', '1.4', '1.2']
+
+ ws = WorkingSet([])
+ foo12 = dist_from_fn("FooPkg-1.2-py2.4.egg")
+ foo14 = dist_from_fn("FooPkg-1.4-py2.4-win32.egg")
+ (req,) = parse_requirements("FooPkg>=1.3")
+
+ # Nominal case: no distros on path, should yield all applicable
+ assert ad.best_match(req, ws).version == '1.9'
+ # If a matching distro is already installed, should return only that
+ ws.add(foo14)
+ assert ad.best_match(req, ws).version == '1.4'
+
+ # If the first matching distro is unsuitable, it's a version conflict
+ ws = WorkingSet([])
+ ws.add(foo12)
+ ws.add(foo14)
+ with pytest.raises(VersionConflict):
+ ad.best_match(req, ws)
+
+ # If more than one match on the path, the first one takes precedence
+ ws = WorkingSet([])
+ ws.add(foo14)
+ ws.add(foo12)
+ ws.add(foo14)
+ assert ad.best_match(req, ws).version == '1.4'
+
+ def checkFooPkg(self, d):
+ assert d.project_name == "FooPkg"
+ assert d.key == "foopkg"
+ assert d.version == "1.3.post1"
+ assert d.py_version == "2.4"
+ assert d.platform == "win32"
+ assert d.parsed_version == parse_version("1.3-1")
+
+ def testDistroBasics(self):
+ d = Distribution(
+ "/some/path",
+ project_name="FooPkg",
+ version="1.3-1",
+ py_version="2.4",
+ platform="win32",
+ )
+ self.checkFooPkg(d)
+
+ d = Distribution("/some/path")
+ assert d.py_version == f'{sys.version_info.major}.{sys.version_info.minor}'
+ assert d.platform is None
+
+ def testDistroParse(self):
+ d = dist_from_fn("FooPkg-1.3.post1-py2.4-win32.egg")
+ self.checkFooPkg(d)
+ d = dist_from_fn("FooPkg-1.3.post1-py2.4-win32.egg-info")
+ self.checkFooPkg(d)
+
+ def testDistroMetadata(self):
+ d = Distribution(
+ "/some/path",
+ project_name="FooPkg",
+ py_version="2.4",
+ platform="win32",
+ metadata=Metadata(('PKG-INFO', "Metadata-Version: 1.0\nVersion: 1.3-1\n")),
+ )
+ self.checkFooPkg(d)
+
+ def distRequires(self, txt):
+ return Distribution("/foo", metadata=Metadata(('depends.txt', txt)))
+
+ def checkRequires(self, dist, txt, extras=()):
+ assert list(dist.requires(extras)) == list(parse_requirements(txt))
+
+ def testDistroDependsSimple(self):
+ for v in "Twisted>=1.5", "Twisted>=1.5\nZConfig>=2.0":
+ self.checkRequires(self.distRequires(v), v)
+
+ needs_object_dir = pytest.mark.skipif(
+ not hasattr(object, '__dir__'),
+ reason='object.__dir__ necessary for self.__dir__ implementation',
+ )
+
+ def test_distribution_dir(self):
+ d = pkg_resources.Distribution()
+ dir(d)
+
+ @needs_object_dir
+ def test_distribution_dir_includes_provider_dir(self):
+ d = pkg_resources.Distribution()
+ before = d.__dir__()
+ assert 'test_attr' not in before
+ d._provider.test_attr = None
+ after = d.__dir__()
+ assert len(after) == len(before) + 1
+ assert 'test_attr' in after
+
+ @needs_object_dir
+ def test_distribution_dir_ignores_provider_dir_leading_underscore(self):
+ d = pkg_resources.Distribution()
+ before = d.__dir__()
+ assert '_test_attr' not in before
+ d._provider._test_attr = None
+ after = d.__dir__()
+ assert len(after) == len(before)
+ assert '_test_attr' not in after
+
+ def testResolve(self):
+ ad = pkg_resources.Environment([])
+ ws = WorkingSet([])
+ # Resolving no requirements -> nothing to install
+ assert list(ws.resolve([], ad)) == []
+ # Request something not in the collection -> DistributionNotFound
+ with pytest.raises(pkg_resources.DistributionNotFound):
+ ws.resolve(parse_requirements("Foo"), ad)
+
+ Foo = Distribution.from_filename(
+ "/foo_dir/Foo-1.2.egg",
+ metadata=Metadata(('depends.txt', "[bar]\nBaz>=2.0")),
+ )
+ ad.add(Foo)
+ ad.add(Distribution.from_filename("Foo-0.9.egg"))
+
+ # Request thing(s) that are available -> list to activate
+ for i in range(3):
+ targets = list(ws.resolve(parse_requirements("Foo"), ad))
+ assert targets == [Foo]
+ list(map(ws.add, targets))
+ with pytest.raises(VersionConflict):
+ ws.resolve(parse_requirements("Foo==0.9"), ad)
+ ws = WorkingSet([]) # reset
+
+ # Request an extra that causes an unresolved dependency for "Baz"
+ with pytest.raises(pkg_resources.DistributionNotFound):
+ ws.resolve(parse_requirements("Foo[bar]"), ad)
+ Baz = Distribution.from_filename(
+ "/foo_dir/Baz-2.1.egg", metadata=Metadata(('depends.txt', "Foo"))
+ )
+ ad.add(Baz)
+
+ # Activation list now includes resolved dependency
+ assert list(ws.resolve(parse_requirements("Foo[bar]"), ad)) == [Foo, Baz]
+ # Requests for conflicting versions produce VersionConflict
+ with pytest.raises(VersionConflict) as vc:
+ ws.resolve(parse_requirements("Foo==1.2\nFoo!=1.2"), ad)
+
+ msg = 'Foo 0.9 is installed but Foo==1.2 is required'
+ assert vc.value.report() == msg
+
+ def test_environment_marker_evaluation_negative(self):
+ """Environment markers are evaluated at resolution time."""
+ ad = pkg_resources.Environment([])
+ ws = WorkingSet([])
+ res = ws.resolve(parse_requirements("Foo;python_version<'2'"), ad)
+ assert list(res) == []
+
+ def test_environment_marker_evaluation_positive(self):
+ ad = pkg_resources.Environment([])
+ ws = WorkingSet([])
+ Foo = Distribution.from_filename("/foo_dir/Foo-1.2.dist-info")
+ ad.add(Foo)
+ res = ws.resolve(parse_requirements("Foo;python_version>='2'"), ad)
+ assert list(res) == [Foo]
+
+ def test_environment_marker_evaluation_called(self):
+ """
+ If one package foo requires bar without any extras,
+ markers should pass for bar without extras.
+ """
+ (parent_req,) = parse_requirements("foo")
+ (req,) = parse_requirements("bar;python_version>='2'")
+ req_extras = pkg_resources._ReqExtras({req: parent_req.extras})
+ assert req_extras.markers_pass(req)
+
+ (parent_req,) = parse_requirements("foo[]")
+ (req,) = parse_requirements("bar;python_version>='2'")
+ req_extras = pkg_resources._ReqExtras({req: parent_req.extras})
+ assert req_extras.markers_pass(req)
+
+ def test_marker_evaluation_with_extras(self):
+ """Extras are also evaluated as markers at resolution time."""
+ ad = pkg_resources.Environment([])
+ ws = WorkingSet([])
+ Foo = Distribution.from_filename(
+ "/foo_dir/Foo-1.2.dist-info",
+ metadata=Metadata((
+ "METADATA",
+ "Provides-Extra: baz\nRequires-Dist: quux; extra=='baz'",
+ )),
+ )
+ ad.add(Foo)
+ assert list(ws.resolve(parse_requirements("Foo"), ad)) == [Foo]
+ quux = Distribution.from_filename("/foo_dir/quux-1.0.dist-info")
+ ad.add(quux)
+ res = list(ws.resolve(parse_requirements("Foo[baz]"), ad))
+ assert res == [Foo, quux]
+
+ def test_marker_evaluation_with_extras_normlized(self):
+ """Extras are also evaluated as markers at resolution time."""
+ ad = pkg_resources.Environment([])
+ ws = WorkingSet([])
+ Foo = Distribution.from_filename(
+ "/foo_dir/Foo-1.2.dist-info",
+ metadata=Metadata((
+ "METADATA",
+ "Provides-Extra: baz-lightyear\n"
+ "Requires-Dist: quux; extra=='baz-lightyear'",
+ )),
+ )
+ ad.add(Foo)
+ assert list(ws.resolve(parse_requirements("Foo"), ad)) == [Foo]
+ quux = Distribution.from_filename("/foo_dir/quux-1.0.dist-info")
+ ad.add(quux)
+ res = list(ws.resolve(parse_requirements("Foo[baz-lightyear]"), ad))
+ assert res == [Foo, quux]
+
+ def test_marker_evaluation_with_multiple_extras(self):
+ ad = pkg_resources.Environment([])
+ ws = WorkingSet([])
+ Foo = Distribution.from_filename(
+ "/foo_dir/Foo-1.2.dist-info",
+ metadata=Metadata((
+ "METADATA",
+ "Provides-Extra: baz\n"
+ "Requires-Dist: quux; extra=='baz'\n"
+ "Provides-Extra: bar\n"
+ "Requires-Dist: fred; extra=='bar'\n",
+ )),
+ )
+ ad.add(Foo)
+ quux = Distribution.from_filename("/foo_dir/quux-1.0.dist-info")
+ ad.add(quux)
+ fred = Distribution.from_filename("/foo_dir/fred-0.1.dist-info")
+ ad.add(fred)
+ res = list(ws.resolve(parse_requirements("Foo[baz,bar]"), ad))
+ assert sorted(res) == [fred, quux, Foo]
+
+ def test_marker_evaluation_with_extras_loop(self):
+ ad = pkg_resources.Environment([])
+ ws = WorkingSet([])
+ a = Distribution.from_filename(
+ "/foo_dir/a-0.2.dist-info",
+ metadata=Metadata(("METADATA", "Requires-Dist: c[a]")),
+ )
+ b = Distribution.from_filename(
+ "/foo_dir/b-0.3.dist-info",
+ metadata=Metadata(("METADATA", "Requires-Dist: c[b]")),
+ )
+ c = Distribution.from_filename(
+ "/foo_dir/c-1.0.dist-info",
+ metadata=Metadata((
+ "METADATA",
+ "Provides-Extra: a\n"
+ "Requires-Dist: b;extra=='a'\n"
+ "Provides-Extra: b\n"
+ "Requires-Dist: foo;extra=='b'",
+ )),
+ )
+ foo = Distribution.from_filename("/foo_dir/foo-0.1.dist-info")
+ for dist in (a, b, c, foo):
+ ad.add(dist)
+ res = list(ws.resolve(parse_requirements("a"), ad))
+ assert res == [a, c, b, foo]
+
+ @pytest.mark.xfail(
+ sys.version_info[:2] == (3, 12) and sys.version_info.releaselevel != 'final',
+ reason="https://github.com/python/cpython/issues/103632",
+ )
+ def testDistroDependsOptions(self):
+ d = self.distRequires(
+ """
+ Twisted>=1.5
+ [docgen]
+ ZConfig>=2.0
+ docutils>=0.3
+ [fastcgi]
+ fcgiapp>=0.1"""
+ )
+ self.checkRequires(d, "Twisted>=1.5")
+ self.checkRequires(
+ d, "Twisted>=1.5 ZConfig>=2.0 docutils>=0.3".split(), ["docgen"]
+ )
+ self.checkRequires(d, "Twisted>=1.5 fcgiapp>=0.1".split(), ["fastcgi"])
+ self.checkRequires(
+ d,
+ "Twisted>=1.5 ZConfig>=2.0 docutils>=0.3 fcgiapp>=0.1".split(),
+ ["docgen", "fastcgi"],
+ )
+ self.checkRequires(
+ d,
+ "Twisted>=1.5 fcgiapp>=0.1 ZConfig>=2.0 docutils>=0.3".split(),
+ ["fastcgi", "docgen"],
+ )
+ with pytest.raises(pkg_resources.UnknownExtra):
+ d.requires(["foo"])
+
+
+class TestWorkingSet:
+ def test_find_conflicting(self):
+ ws = WorkingSet([])
+ Foo = Distribution.from_filename("/foo_dir/Foo-1.2.egg")
+ ws.add(Foo)
+
+ # create a requirement that conflicts with Foo 1.2
+ req = next(parse_requirements("Foo<1.2"))
+
+ with pytest.raises(VersionConflict) as vc:
+ ws.find(req)
+
+ msg = 'Foo 1.2 is installed but Foo<1.2 is required'
+ assert vc.value.report() == msg
+
+ def test_resolve_conflicts_with_prior(self):
+ """
+ A ContextualVersionConflict should be raised when a requirement
+ conflicts with a prior requirement for a different package.
+ """
+ # Create installation where Foo depends on Baz 1.0 and Bar depends on
+ # Baz 2.0.
+ ws = WorkingSet([])
+ md = Metadata(('depends.txt', "Baz==1.0"))
+ Foo = Distribution.from_filename("/foo_dir/Foo-1.0.egg", metadata=md)
+ ws.add(Foo)
+ md = Metadata(('depends.txt', "Baz==2.0"))
+ Bar = Distribution.from_filename("/foo_dir/Bar-1.0.egg", metadata=md)
+ ws.add(Bar)
+ Baz = Distribution.from_filename("/foo_dir/Baz-1.0.egg")
+ ws.add(Baz)
+ Baz = Distribution.from_filename("/foo_dir/Baz-2.0.egg")
+ ws.add(Baz)
+
+ with pytest.raises(VersionConflict) as vc:
+ ws.resolve(parse_requirements("Foo\nBar\n"))
+
+ msg = "Baz 1.0 is installed but Baz==2.0 is required by "
+ msg += repr(set(['Bar']))
+ assert vc.value.report() == msg
+
+
+class TestEntryPoints:
+ def assertfields(self, ep):
+ assert ep.name == "foo"
+ assert ep.module_name == "pkg_resources.tests.test_resources"
+ assert ep.attrs == ("TestEntryPoints",)
+ assert ep.extras == ("x",)
+ assert ep.load() is TestEntryPoints
+ expect = "foo = pkg_resources.tests.test_resources:TestEntryPoints [x]"
+ assert str(ep) == expect
+
+ def setup_method(self, method):
+ self.dist = Distribution.from_filename(
+ "FooPkg-1.2-py2.4.egg", metadata=Metadata(('requires.txt', '[x]'))
+ )
+
+ def testBasics(self):
+ ep = EntryPoint(
+ "foo",
+ "pkg_resources.tests.test_resources",
+ ["TestEntryPoints"],
+ ["x"],
+ self.dist,
+ )
+ self.assertfields(ep)
+
+ def testParse(self):
+ s = "foo = pkg_resources.tests.test_resources:TestEntryPoints [x]"
+ ep = EntryPoint.parse(s, self.dist)
+ self.assertfields(ep)
+
+ ep = EntryPoint.parse("bar baz= spammity[PING]")
+ assert ep.name == "bar baz"
+ assert ep.module_name == "spammity"
+ assert ep.attrs == ()
+ assert ep.extras == ("ping",)
+
+ ep = EntryPoint.parse(" fizzly = wocka:foo")
+ assert ep.name == "fizzly"
+ assert ep.module_name == "wocka"
+ assert ep.attrs == ("foo",)
+ assert ep.extras == ()
+
+ # plus in the name
+ spec = "html+mako = mako.ext.pygmentplugin:MakoHtmlLexer"
+ ep = EntryPoint.parse(spec)
+ assert ep.name == 'html+mako'
+
+ reject_specs = "foo", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2"
+
+ @pytest.mark.parametrize("reject_spec", reject_specs)
+ def test_reject_spec(self, reject_spec):
+ with pytest.raises(ValueError):
+ EntryPoint.parse(reject_spec)
+
+ def test_printable_name(self):
+ """
+ Allow any printable character in the name.
+ """
+ # Create a name with all printable characters; strip the whitespace.
+ name = string.printable.strip()
+ spec = "{name} = module:attr".format(**locals())
+ ep = EntryPoint.parse(spec)
+ assert ep.name == name
+
+ def checkSubMap(self, m):
+ assert len(m) == len(self.submap_expect)
+ for key, ep in self.submap_expect.items():
+ assert m.get(key).name == ep.name
+ assert m.get(key).module_name == ep.module_name
+ assert sorted(m.get(key).attrs) == sorted(ep.attrs)
+ assert sorted(m.get(key).extras) == sorted(ep.extras)
+
+ submap_expect = dict(
+ feature1=EntryPoint('feature1', 'somemodule', ['somefunction']),
+ feature2=EntryPoint(
+ 'feature2', 'another.module', ['SomeClass'], ['extra1', 'extra2']
+ ),
+ feature3=EntryPoint('feature3', 'this.module', extras=['something']),
+ )
+ submap_str = """
+ # define features for blah blah
+ feature1 = somemodule:somefunction
+ feature2 = another.module:SomeClass [extra1,extra2]
+ feature3 = this.module [something]
+ """
+
+ def testParseList(self):
+ self.checkSubMap(EntryPoint.parse_group("xyz", self.submap_str))
+ with pytest.raises(ValueError):
+ EntryPoint.parse_group("x a", "foo=bar")
+ with pytest.raises(ValueError):
+ EntryPoint.parse_group("x", ["foo=baz", "foo=bar"])
+
+ def testParseMap(self):
+ m = EntryPoint.parse_map({'xyz': self.submap_str})
+ self.checkSubMap(m['xyz'])
+ assert list(m.keys()) == ['xyz']
+ m = EntryPoint.parse_map("[xyz]\n" + self.submap_str)
+ self.checkSubMap(m['xyz'])
+ assert list(m.keys()) == ['xyz']
+ with pytest.raises(ValueError):
+ EntryPoint.parse_map(["[xyz]", "[xyz]"])
+ with pytest.raises(ValueError):
+ EntryPoint.parse_map(self.submap_str)
+
+ def testDeprecationWarnings(self):
+ ep = EntryPoint(
+ "foo", "pkg_resources.tests.test_resources", ["TestEntryPoints"], ["x"]
+ )
+ with pytest.warns(pkg_resources.PkgResourcesDeprecationWarning):
+ ep.load(require=False)
+
+
+class TestRequirements:
+ def testBasics(self):
+ r = Requirement.parse("Twisted>=1.2")
+ assert str(r) == "Twisted>=1.2"
+ assert repr(r) == "Requirement.parse('Twisted>=1.2')"
+ assert r == Requirement("Twisted>=1.2")
+ assert r == Requirement("twisTed>=1.2")
+ assert r != Requirement("Twisted>=2.0")
+ assert r != Requirement("Zope>=1.2")
+ assert r != Requirement("Zope>=3.0")
+ assert r != Requirement("Twisted[extras]>=1.2")
+
+ def testOrdering(self):
+ r1 = Requirement("Twisted==1.2c1,>=1.2")
+ r2 = Requirement("Twisted>=1.2,==1.2c1")
+ assert r1 == r2
+ assert str(r1) == str(r2)
+ assert str(r2) == "Twisted==1.2c1,>=1.2"
+ assert Requirement("Twisted") != Requirement(
+ "Twisted @ https://localhost/twisted.zip"
+ )
+
+ def testBasicContains(self):
+ r = Requirement("Twisted>=1.2")
+ foo_dist = Distribution.from_filename("FooPkg-1.3_1.egg")
+ twist11 = Distribution.from_filename("Twisted-1.1.egg")
+ twist12 = Distribution.from_filename("Twisted-1.2.egg")
+ assert parse_version('1.2') in r
+ assert parse_version('1.1') not in r
+ assert '1.2' in r
+ assert '1.1' not in r
+ assert foo_dist not in r
+ assert twist11 not in r
+ assert twist12 in r
+
+ def testOptionsAndHashing(self):
+ r1 = Requirement.parse("Twisted[foo,bar]>=1.2")
+ r2 = Requirement.parse("Twisted[bar,FOO]>=1.2")
+ assert r1 == r2
+ assert set(r1.extras) == set(("foo", "bar"))
+ assert set(r2.extras) == set(("foo", "bar"))
+ assert hash(r1) == hash(r2)
+ assert hash(r1) == hash((
+ "twisted",
+ None,
+ SpecifierSet(">=1.2"),
+ frozenset(["foo", "bar"]),
+ None,
+ ))
+ assert hash(
+ Requirement.parse("Twisted @ https://localhost/twisted.zip")
+ ) == hash((
+ "twisted",
+ "https://localhost/twisted.zip",
+ SpecifierSet(),
+ frozenset(),
+ None,
+ ))
+
+ def testVersionEquality(self):
+ r1 = Requirement.parse("foo==0.3a2")
+ r2 = Requirement.parse("foo!=0.3a4")
+ d = Distribution.from_filename
+
+ assert d("foo-0.3a4.egg") not in r1
+ assert d("foo-0.3a1.egg") not in r1
+ assert d("foo-0.3a4.egg") not in r2
+
+ assert d("foo-0.3a2.egg") in r1
+ assert d("foo-0.3a2.egg") in r2
+ assert d("foo-0.3a3.egg") in r2
+ assert d("foo-0.3a5.egg") in r2
+
+ def testSetuptoolsProjectName(self):
+ """
+ The setuptools project should implement the setuptools package.
+ """
+
+ assert Requirement.parse('setuptools').project_name == 'setuptools'
+ # setuptools 0.7 and higher means setuptools.
+ assert Requirement.parse('setuptools == 0.7').project_name == 'setuptools'
+ assert Requirement.parse('setuptools == 0.7a1').project_name == 'setuptools'
+ assert Requirement.parse('setuptools >= 0.7').project_name == 'setuptools'
+
+
+class TestParsing:
+ def testEmptyParse(self):
+ assert list(parse_requirements('')) == []
+
+ def testYielding(self):
+ for inp, out in [
+ ([], []),
+ ('x', ['x']),
+ ([[]], []),
+ (' x\n y', ['x', 'y']),
+ (['x\n\n', 'y'], ['x', 'y']),
+ ]:
+ assert list(pkg_resources.yield_lines(inp)) == out
+
+ def testSplitting(self):
+ sample = """
+ x
+ [Y]
+ z
+
+ a
+ [b ]
+ # foo
+ c
+ [ d]
+ [q]
+ v
+ """
+ assert list(pkg_resources.split_sections(sample)) == [
+ (None, ["x"]),
+ ("Y", ["z", "a"]),
+ ("b", ["c"]),
+ ("d", []),
+ ("q", ["v"]),
+ ]
+ with pytest.raises(ValueError):
+ list(pkg_resources.split_sections("[foo"))
+
+ def testSafeName(self):
+ assert safe_name("adns-python") == "adns-python"
+ assert safe_name("WSGI Utils") == "WSGI-Utils"
+ assert safe_name("WSGI Utils") == "WSGI-Utils"
+ assert safe_name("Money$$$Maker") == "Money-Maker"
+ assert safe_name("peak.web") != "peak-web"
+
+ def testSafeVersion(self):
+ assert safe_version("1.2-1") == "1.2.post1"
+ assert safe_version("1.2 alpha") == "1.2.alpha"
+ assert safe_version("2.3.4 20050521") == "2.3.4.20050521"
+ assert safe_version("Money$$$Maker") == "Money-Maker"
+ assert safe_version("peak.web") == "peak.web"
+
+ def testSimpleRequirements(self):
+ assert list(parse_requirements('Twis-Ted>=1.2-1')) == [
+ Requirement('Twis-Ted>=1.2-1')
+ ]
+ assert list(parse_requirements('Twisted >=1.2, \\ # more\n<2.0')) == [
+ Requirement('Twisted>=1.2,<2.0')
+ ]
+ assert Requirement.parse("FooBar==1.99a3") == Requirement("FooBar==1.99a3")
+ with pytest.raises(ValueError):
+ Requirement.parse(">=2.3")
+ with pytest.raises(ValueError):
+ Requirement.parse("x\\")
+ with pytest.raises(ValueError):
+ Requirement.parse("x==2 q")
+ with pytest.raises(ValueError):
+ Requirement.parse("X==1\nY==2")
+ with pytest.raises(ValueError):
+ Requirement.parse("#")
+
+ def test_requirements_with_markers(self):
+ assert Requirement.parse("foobar;os_name=='a'") == Requirement.parse(
+ "foobar;os_name=='a'"
+ )
+ assert Requirement.parse(
+ "name==1.1;python_version=='2.7'"
+ ) != Requirement.parse("name==1.1;python_version=='3.6'")
+ assert Requirement.parse(
+ "name==1.0;python_version=='2.7'"
+ ) != Requirement.parse("name==1.2;python_version=='2.7'")
+ assert Requirement.parse(
+ "name[foo]==1.0;python_version=='3.6'"
+ ) != Requirement.parse("name[foo,bar]==1.0;python_version=='3.6'")
+
+ def test_local_version(self):
+ parse_requirements('foo==1.0+org1')
+
+ def test_spaces_between_multiple_versions(self):
+ parse_requirements('foo>=1.0, <3')
+ parse_requirements('foo >= 1.0, < 3')
+
+ @pytest.mark.parametrize(
+ ("lower", "upper"),
+ [
+ ('1.2-rc1', '1.2rc1'),
+ ('0.4', '0.4.0'),
+ ('0.4.0.0', '0.4.0'),
+ ('0.4.0-0', '0.4-0'),
+ ('0post1', '0.0post1'),
+ ('0pre1', '0.0c1'),
+ ('0.0.0preview1', '0c1'),
+ ('0.0c1', '0-rc1'),
+ ('1.2a1', '1.2.a.1'),
+ ('1.2.a', '1.2a'),
+ ],
+ )
+ def testVersionEquality(self, lower, upper):
+ assert parse_version(lower) == parse_version(upper)
+
+ torture = """
+ 0.80.1-3 0.80.1-2 0.80.1-1 0.79.9999+0.80.0pre4-1
+ 0.79.9999+0.80.0pre2-3 0.79.9999+0.80.0pre2-2
+ 0.77.2-1 0.77.1-1 0.77.0-1
+ """
+
+ @pytest.mark.parametrize(
+ ("lower", "upper"),
+ [
+ ('2.1', '2.1.1'),
+ ('2a1', '2b0'),
+ ('2a1', '2.1'),
+ ('2.3a1', '2.3'),
+ ('2.1-1', '2.1-2'),
+ ('2.1-1', '2.1.1'),
+ ('2.1', '2.1post4'),
+ ('2.1a0-20040501', '2.1'),
+ ('1.1', '02.1'),
+ ('3.2', '3.2.post0'),
+ ('3.2post1', '3.2post2'),
+ ('0.4', '4.0'),
+ ('0.0.4', '0.4.0'),
+ ('0post1', '0.4post1'),
+ ('2.1.0-rc1', '2.1.0'),
+ ('2.1dev', '2.1a0'),
+ ]
+ + list(pairwise(reversed(torture.split()))),
+ )
+ def testVersionOrdering(self, lower, upper):
+ assert parse_version(lower) < parse_version(upper)
+
+ def testVersionHashable(self):
+ """
+ Ensure that our versions stay hashable even though we've subclassed
+ them and added some shim code to them.
+ """
+ assert hash(parse_version("1.0")) == hash(parse_version("1.0"))
+
+
+class TestNamespaces:
+ ns_str = "__import__('pkg_resources').declare_namespace(__name__)\n"
+
+ @pytest.fixture
+ def symlinked_tmpdir(self, tmpdir):
+ """
+ Where available, return the tempdir as a symlink,
+ which as revealed in #231 is more fragile than
+ a natural tempdir.
+ """
+ if not hasattr(os, 'symlink'):
+ yield str(tmpdir)
+ return
+
+ link_name = str(tmpdir) + '-linked'
+ os.symlink(str(tmpdir), link_name)
+ try:
+ yield type(tmpdir)(link_name)
+ finally:
+ os.unlink(link_name)
+
+ @pytest.fixture(autouse=True)
+ def patched_path(self, tmpdir):
+ """
+ Patch sys.path to include the 'site-pkgs' dir. Also
+ restore pkg_resources._namespace_packages to its
+ former state.
+ """
+ saved_ns_pkgs = pkg_resources._namespace_packages.copy()
+ saved_sys_path = sys.path[:]
+ site_pkgs = tmpdir.mkdir('site-pkgs')
+ sys.path.append(str(site_pkgs))
+ try:
+ yield
+ finally:
+ pkg_resources._namespace_packages = saved_ns_pkgs
+ sys.path = saved_sys_path
+
+ issue591 = pytest.mark.xfail(platform.system() == 'Windows', reason="#591")
+
+ @issue591
+ def test_two_levels_deep(self, symlinked_tmpdir):
+ """
+ Test nested namespace packages
+ Create namespace packages in the following tree :
+ site-packages-1/pkg1/pkg2
+ site-packages-2/pkg1/pkg2
+ Check both are in the _namespace_packages dict and that their __path__
+ is correct
+ """
+ real_tmpdir = symlinked_tmpdir.realpath()
+ tmpdir = symlinked_tmpdir
+ sys.path.append(str(tmpdir / 'site-pkgs2'))
+ site_dirs = tmpdir / 'site-pkgs', tmpdir / 'site-pkgs2'
+ for site in site_dirs:
+ pkg1 = site / 'pkg1'
+ pkg2 = pkg1 / 'pkg2'
+ pkg2.ensure_dir()
+ (pkg1 / '__init__.py').write_text(self.ns_str, encoding='utf-8')
+ (pkg2 / '__init__.py').write_text(self.ns_str, encoding='utf-8')
+ with pytest.warns(DeprecationWarning, match="pkg_resources.declare_namespace"):
+ import pkg1 # pyright: ignore[reportMissingImports] # Temporary package for test
+ assert "pkg1" in pkg_resources._namespace_packages
+ # attempt to import pkg2 from site-pkgs2
+ with pytest.warns(DeprecationWarning, match="pkg_resources.declare_namespace"):
+ import pkg1.pkg2 # pyright: ignore[reportMissingImports] # Temporary package for test
+ # check the _namespace_packages dict
+ assert "pkg1.pkg2" in pkg_resources._namespace_packages
+ assert pkg_resources._namespace_packages["pkg1"] == ["pkg1.pkg2"]
+ # check the __path__ attribute contains both paths
+ expected = [
+ str(real_tmpdir / "site-pkgs" / "pkg1" / "pkg2"),
+ str(real_tmpdir / "site-pkgs2" / "pkg1" / "pkg2"),
+ ]
+ assert pkg1.pkg2.__path__ == expected
+
+ @issue591
+ def test_path_order(self, symlinked_tmpdir):
+ """
+ Test that if multiple versions of the same namespace package subpackage
+ are on different sys.path entries, that only the one earliest on
+ sys.path is imported, and that the namespace package's __path__ is in
+ the correct order.
+
+ Regression test for https://github.com/pypa/setuptools/issues/207
+ """
+
+ tmpdir = symlinked_tmpdir
+ site_dirs = (
+ tmpdir / "site-pkgs",
+ tmpdir / "site-pkgs2",
+ tmpdir / "site-pkgs3",
+ )
+
+ vers_str = "__version__ = %r"
+
+ for number, site in enumerate(site_dirs, 1):
+ if number > 1:
+ sys.path.append(str(site))
+ nspkg = site / 'nspkg'
+ subpkg = nspkg / 'subpkg'
+ subpkg.ensure_dir()
+ (nspkg / '__init__.py').write_text(self.ns_str, encoding='utf-8')
+ (subpkg / '__init__.py').write_text(vers_str % number, encoding='utf-8')
+
+ with pytest.warns(DeprecationWarning, match="pkg_resources.declare_namespace"):
+ import nspkg # pyright: ignore[reportMissingImports] # Temporary package for test
+ import nspkg.subpkg # pyright: ignore[reportMissingImports] # Temporary package for test
+ expected = [str(site.realpath() / 'nspkg') for site in site_dirs]
+ assert nspkg.__path__ == expected
+ assert nspkg.subpkg.__version__ == 1
diff --git a/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_working_set.py b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_working_set.py
new file mode 100644
index 0000000..ed20c59
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pkg_resources/tests/test_working_set.py
@@ -0,0 +1,505 @@
+import functools
+import inspect
+import re
+import textwrap
+
+import pytest
+
+import pkg_resources
+
+from .test_resources import Metadata
+
+
+def strip_comments(s):
+ return '\n'.join(
+ line
+ for line in s.split('\n')
+ if line.strip() and not line.strip().startswith('#')
+ )
+
+
+def parse_distributions(s):
+ """
+ Parse a series of distribution specs of the form:
+ {project_name}-{version}
+ [optional, indented requirements specification]
+
+ Example:
+
+ foo-0.2
+ bar-1.0
+ foo>=3.0
+ [feature]
+ baz
+
+ yield 2 distributions:
+ - project_name=foo, version=0.2
+ - project_name=bar, version=1.0,
+ requires=['foo>=3.0', 'baz; extra=="feature"']
+ """
+ s = s.strip()
+ for spec in re.split(r'\n(?=[^\s])', s):
+ if not spec:
+ continue
+ fields = spec.split('\n', 1)
+ assert 1 <= len(fields) <= 2
+ name, version = fields.pop(0).rsplit('-', 1)
+ if fields:
+ requires = textwrap.dedent(fields.pop(0))
+ metadata = Metadata(('requires.txt', requires))
+ else:
+ metadata = None
+ dist = pkg_resources.Distribution(
+ project_name=name, version=version, metadata=metadata
+ )
+ yield dist
+
+
+class FakeInstaller:
+ def __init__(self, installable_dists) -> None:
+ self._installable_dists = installable_dists
+
+ def __call__(self, req):
+ return next(
+ iter(filter(lambda dist: dist in req, self._installable_dists)), None
+ )
+
+
+def parametrize_test_working_set_resolve(*test_list):
+ idlist = []
+ argvalues = []
+ for test in test_list:
+ (
+ name,
+ installed_dists,
+ installable_dists,
+ requirements,
+ expected1,
+ expected2,
+ ) = (
+ strip_comments(s.lstrip())
+ for s in textwrap.dedent(test).lstrip().split('\n\n', 5)
+ )
+ installed_dists = list(parse_distributions(installed_dists))
+ installable_dists = list(parse_distributions(installable_dists))
+ requirements = list(pkg_resources.parse_requirements(requirements))
+ for id_, replace_conflicting, expected in (
+ (name, False, expected1),
+ (name + '_replace_conflicting', True, expected2),
+ ):
+ idlist.append(id_)
+ expected = strip_comments(expected.strip())
+ if re.match(r'\w+$', expected):
+ expected = getattr(pkg_resources, expected)
+ assert issubclass(expected, Exception)
+ else:
+ expected = list(parse_distributions(expected))
+ argvalues.append(
+ pytest.param(
+ installed_dists,
+ installable_dists,
+ requirements,
+ replace_conflicting,
+ expected,
+ )
+ )
+ return pytest.mark.parametrize(
+ (
+ "installed_dists",
+ "installable_dists",
+ "requirements",
+ "replace_conflicting",
+ "resolved_dists_or_exception",
+ ),
+ argvalues,
+ ids=idlist,
+ )
+
+
+@parametrize_test_working_set_resolve(
+ """
+ # id
+ noop
+
+ # installed
+
+ # installable
+
+ # wanted
+
+ # resolved
+
+ # resolved [replace conflicting]
+ """,
+ """
+ # id
+ already_installed
+
+ # installed
+ foo-3.0
+
+ # installable
+
+ # wanted
+ foo>=2.1,!=3.1,<4
+
+ # resolved
+ foo-3.0
+
+ # resolved [replace conflicting]
+ foo-3.0
+ """,
+ """
+ # id
+ installable_not_installed
+
+ # installed
+
+ # installable
+ foo-3.0
+ foo-4.0
+
+ # wanted
+ foo>=2.1,!=3.1,<4
+
+ # resolved
+ foo-3.0
+
+ # resolved [replace conflicting]
+ foo-3.0
+ """,
+ """
+ # id
+ not_installable
+
+ # installed
+
+ # installable
+
+ # wanted
+ foo>=2.1,!=3.1,<4
+
+ # resolved
+ DistributionNotFound
+
+ # resolved [replace conflicting]
+ DistributionNotFound
+ """,
+ """
+ # id
+ no_matching_version
+
+ # installed
+
+ # installable
+ foo-3.1
+
+ # wanted
+ foo>=2.1,!=3.1,<4
+
+ # resolved
+ DistributionNotFound
+
+ # resolved [replace conflicting]
+ DistributionNotFound
+ """,
+ """
+ # id
+ installable_with_installed_conflict
+
+ # installed
+ foo-3.1
+
+ # installable
+ foo-3.5
+
+ # wanted
+ foo>=2.1,!=3.1,<4
+
+ # resolved
+ VersionConflict
+
+ # resolved [replace conflicting]
+ foo-3.5
+ """,
+ """
+ # id
+ not_installable_with_installed_conflict
+
+ # installed
+ foo-3.1
+
+ # installable
+
+ # wanted
+ foo>=2.1,!=3.1,<4
+
+ # resolved
+ VersionConflict
+
+ # resolved [replace conflicting]
+ DistributionNotFound
+ """,
+ """
+ # id
+ installed_with_installed_require
+
+ # installed
+ foo-3.9
+ baz-0.1
+ foo>=2.1,!=3.1,<4
+
+ # installable
+
+ # wanted
+ baz
+
+ # resolved
+ foo-3.9
+ baz-0.1
+
+ # resolved [replace conflicting]
+ foo-3.9
+ baz-0.1
+ """,
+ """
+ # id
+ installed_with_conflicting_installed_require
+
+ # installed
+ foo-5
+ baz-0.1
+ foo>=2.1,!=3.1,<4
+
+ # installable
+
+ # wanted
+ baz
+
+ # resolved
+ VersionConflict
+
+ # resolved [replace conflicting]
+ DistributionNotFound
+ """,
+ """
+ # id
+ installed_with_installable_conflicting_require
+
+ # installed
+ foo-5
+ baz-0.1
+ foo>=2.1,!=3.1,<4
+
+ # installable
+ foo-2.9
+
+ # wanted
+ baz
+
+ # resolved
+ VersionConflict
+
+ # resolved [replace conflicting]
+ baz-0.1
+ foo-2.9
+ """,
+ """
+ # id
+ installed_with_installable_require
+
+ # installed
+ baz-0.1
+ foo>=2.1,!=3.1,<4
+
+ # installable
+ foo-3.9
+
+ # wanted
+ baz
+
+ # resolved
+ foo-3.9
+ baz-0.1
+
+ # resolved [replace conflicting]
+ foo-3.9
+ baz-0.1
+ """,
+ """
+ # id
+ installable_with_installed_require
+
+ # installed
+ foo-3.9
+
+ # installable
+ baz-0.1
+ foo>=2.1,!=3.1,<4
+
+ # wanted
+ baz
+
+ # resolved
+ foo-3.9
+ baz-0.1
+
+ # resolved [replace conflicting]
+ foo-3.9
+ baz-0.1
+ """,
+ """
+ # id
+ installable_with_installable_require
+
+ # installed
+
+ # installable
+ foo-3.9
+ baz-0.1
+ foo>=2.1,!=3.1,<4
+
+ # wanted
+ baz
+
+ # resolved
+ foo-3.9
+ baz-0.1
+
+ # resolved [replace conflicting]
+ foo-3.9
+ baz-0.1
+ """,
+ """
+ # id
+ installable_with_conflicting_installable_require
+
+ # installed
+ foo-5
+
+ # installable
+ foo-2.9
+ baz-0.1
+ foo>=2.1,!=3.1,<4
+
+ # wanted
+ baz
+
+ # resolved
+ VersionConflict
+
+ # resolved [replace conflicting]
+ baz-0.1
+ foo-2.9
+ """,
+ """
+ # id
+ conflicting_installables
+
+ # installed
+
+ # installable
+ foo-2.9
+ foo-5.0
+
+ # wanted
+ foo>=2.1,!=3.1,<4
+ foo>=4
+
+ # resolved
+ VersionConflict
+
+ # resolved [replace conflicting]
+ VersionConflict
+ """,
+ """
+ # id
+ installables_with_conflicting_requires
+
+ # installed
+
+ # installable
+ foo-2.9
+ dep==1.0
+ baz-5.0
+ dep==2.0
+ dep-1.0
+ dep-2.0
+
+ # wanted
+ foo
+ baz
+
+ # resolved
+ VersionConflict
+
+ # resolved [replace conflicting]
+ VersionConflict
+ """,
+ """
+ # id
+ installables_with_conflicting_nested_requires
+
+ # installed
+
+ # installable
+ foo-2.9
+ dep1
+ dep1-1.0
+ subdep<1.0
+ baz-5.0
+ dep2
+ dep2-1.0
+ subdep>1.0
+ subdep-0.9
+ subdep-1.1
+
+ # wanted
+ foo
+ baz
+
+ # resolved
+ VersionConflict
+
+ # resolved [replace conflicting]
+ VersionConflict
+ """,
+ """
+ # id
+ wanted_normalized_name_installed_canonical
+
+ # installed
+ foo.bar-3.6
+
+ # installable
+
+ # wanted
+ foo-bar==3.6
+
+ # resolved
+ foo.bar-3.6
+
+ # resolved [replace conflicting]
+ foo.bar-3.6
+ """,
+)
+def test_working_set_resolve(
+ installed_dists,
+ installable_dists,
+ requirements,
+ replace_conflicting,
+ resolved_dists_or_exception,
+):
+ ws = pkg_resources.WorkingSet([])
+ list(map(ws.add, installed_dists))
+ resolve_call = functools.partial(
+ ws.resolve,
+ requirements,
+ installer=FakeInstaller(installable_dists),
+ replace_conflicting=replace_conflicting,
+ )
+ if inspect.isclass(resolved_dists_or_exception):
+ with pytest.raises(resolved_dists_or_exception):
+ resolve_call()
+ else:
+ assert sorted(resolve_call()) == sorted(resolved_dists_or_exception)
diff --git a/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/LICENSE.txt b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/LICENSE.txt
new file mode 100644
index 0000000..5f1c112
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/LICENSE.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2003-2019 Stuart Bishop
+
+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/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/METADATA b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/METADATA
new file mode 100644
index 0000000..6ecc5a3
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/METADATA
@@ -0,0 +1,648 @@
+Metadata-Version: 2.1
+Name: pytz
+Version: 2025.2
+Summary: World timezone definitions, modern and historical
+Home-page: http://pythonhosted.org/pytz
+Download-URL: https://pypi.org/project/pytz/
+Author: Stuart Bishop
+Author-email: stuart@stuartbishop.net
+Maintainer: Stuart Bishop
+Maintainer-email: stuart@stuartbishop.net
+License: MIT
+Keywords: timezone,tzinfo,datetime,olson,time
+Platform: Independent
+Classifier: Development Status :: 6 - Mature
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.4
+Classifier: Programming Language :: Python :: 2.5
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.1
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+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 :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3.13
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+License-File: LICENSE.txt
+
+pytz - World Timezone Definitions for Python
+============================================
+
+:Author: Stuart Bishop
+
+Introduction
+~~~~~~~~~~~~
+
+pytz brings the Olson tz database into Python. This library allows
+accurate and cross platform timezone calculations using Python 2.4
+or higher. It also solves the issue of ambiguous times at the end
+of daylight saving time, which you can read more about in the Python
+Library Reference (``datetime.tzinfo``).
+
+Almost all of the Olson timezones are supported.
+
+.. note::
+
+ Projects using Python 3.9 or later should be using the support
+ now included as part of the standard library, and third party
+ packages work with it such as `tzdata `_.
+ pytz offers no advantages beyond backwards compatibility with
+ code written for earlier versions of Python.
+
+.. note::
+
+ This library differs from the documented Python API for
+ tzinfo implementations; if you want to create local wallclock
+ times you need to use the ``localize()`` method documented in this
+ document. In addition, if you perform date arithmetic on local
+ times that cross DST boundaries, the result may be in an incorrect
+ timezone (ie. subtract 1 minute from 2002-10-27 1:00 EST and you get
+ 2002-10-27 0:59 EST instead of the correct 2002-10-27 1:59 EDT). A
+ ``normalize()`` method is provided to correct this. Unfortunately these
+ issues cannot be resolved without modifying the Python datetime
+ implementation (see PEP-431).
+
+
+Installation
+~~~~~~~~~~~~
+
+This package can either be installed using ``pip`` or from a tarball using the
+standard Python distutils.
+
+If you are installing using ``pip``, you don't need to download anything as the
+latest version will be downloaded for you from PyPI::
+
+ pip install pytz
+
+If you are installing from a tarball, run the following command as an
+administrative user::
+
+ python setup.py install
+
+
+pytz for Enterprise
+~~~~~~~~~~~~~~~~~~~
+
+Available as part of the Tidelift Subscription.
+
+The maintainers of pytz and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. `Learn more. `_.
+
+
+Example & Usage
+~~~~~~~~~~~~~~~
+
+Localized times and date arithmetic
+-----------------------------------
+
+>>> from datetime import datetime, timedelta
+>>> from pytz import timezone
+>>> import pytz
+>>> utc = pytz.utc
+>>> utc.zone
+'UTC'
+>>> eastern = timezone('US/Eastern')
+>>> eastern.zone
+'US/Eastern'
+>>> amsterdam = timezone('Europe/Amsterdam')
+>>> fmt = '%Y-%m-%d %H:%M:%S %Z%z'
+
+This library only supports two ways of building a localized time. The
+first is to use the ``localize()`` method provided by the pytz library.
+This is used to localize a naive datetime (datetime with no timezone
+information):
+
+>>> loc_dt = eastern.localize(datetime(2002, 10, 27, 6, 0, 0))
+>>> print(loc_dt.strftime(fmt))
+2002-10-27 06:00:00 EST-0500
+
+The second way of building a localized time is by converting an existing
+localized time using the standard ``astimezone()`` method:
+
+>>> ams_dt = loc_dt.astimezone(amsterdam)
+>>> ams_dt.strftime(fmt)
+'2002-10-27 12:00:00 CET+0100'
+
+Unfortunately using the tzinfo argument of the standard datetime
+constructors ''does not work'' with pytz for many timezones.
+
+>>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=amsterdam).strftime(fmt) # /!\ Does not work this way!
+'2002-10-27 12:00:00 LMT+0018'
+
+It is safe for timezones without daylight saving transitions though, such
+as UTC:
+
+>>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=pytz.utc).strftime(fmt) # /!\ Not recommended except for UTC
+'2002-10-27 12:00:00 UTC+0000'
+
+The preferred way of dealing with times is to always work in UTC,
+converting to localtime only when generating output to be read
+by humans.
+
+>>> utc_dt = datetime(2002, 10, 27, 6, 0, 0, tzinfo=utc)
+>>> loc_dt = utc_dt.astimezone(eastern)
+>>> loc_dt.strftime(fmt)
+'2002-10-27 01:00:00 EST-0500'
+
+This library also allows you to do date arithmetic using local
+times, although it is more complicated than working in UTC as you
+need to use the ``normalize()`` method to handle daylight saving time
+and other timezone transitions. In this example, ``loc_dt`` is set
+to the instant when daylight saving time ends in the US/Eastern
+timezone.
+
+>>> before = loc_dt - timedelta(minutes=10)
+>>> before.strftime(fmt)
+'2002-10-27 00:50:00 EST-0500'
+>>> eastern.normalize(before).strftime(fmt)
+'2002-10-27 01:50:00 EDT-0400'
+>>> after = eastern.normalize(before + timedelta(minutes=20))
+>>> after.strftime(fmt)
+'2002-10-27 01:10:00 EST-0500'
+
+Creating local times is also tricky, and the reason why working with
+local times is not recommended. Unfortunately, you cannot just pass
+a ``tzinfo`` argument when constructing a datetime (see the next
+section for more details)
+
+>>> dt = datetime(2002, 10, 27, 1, 30, 0)
+>>> dt1 = eastern.localize(dt, is_dst=True)
+>>> dt1.strftime(fmt)
+'2002-10-27 01:30:00 EDT-0400'
+>>> dt2 = eastern.localize(dt, is_dst=False)
+>>> dt2.strftime(fmt)
+'2002-10-27 01:30:00 EST-0500'
+
+Converting between timezones is more easily done, using the
+standard astimezone method.
+
+>>> utc_dt = datetime.fromtimestamp(1143408899, tz=utc)
+>>> utc_dt.strftime(fmt)
+'2006-03-26 21:34:59 UTC+0000'
+>>> au_tz = timezone('Australia/Sydney')
+>>> au_dt = utc_dt.astimezone(au_tz)
+>>> au_dt.strftime(fmt)
+'2006-03-27 08:34:59 AEDT+1100'
+>>> utc_dt2 = au_dt.astimezone(utc)
+>>> utc_dt2.strftime(fmt)
+'2006-03-26 21:34:59 UTC+0000'
+>>> utc_dt == utc_dt2
+True
+
+You can take shortcuts when dealing with the UTC side of timezone
+conversions. ``normalize()`` and ``localize()`` are not really
+necessary when there are no daylight saving time transitions to
+deal with.
+
+>>> utc_dt = datetime.fromtimestamp(1143408899, tz=utc)
+>>> utc_dt.strftime(fmt)
+'2006-03-26 21:34:59 UTC+0000'
+>>> au_tz = timezone('Australia/Sydney')
+>>> au_dt = au_tz.normalize(utc_dt.astimezone(au_tz))
+>>> au_dt.strftime(fmt)
+'2006-03-27 08:34:59 AEDT+1100'
+>>> utc_dt2 = au_dt.astimezone(utc)
+>>> utc_dt2.strftime(fmt)
+'2006-03-26 21:34:59 UTC+0000'
+
+
+``tzinfo`` API
+--------------
+
+The ``tzinfo`` instances returned by the ``timezone()`` function have
+been extended to cope with ambiguous times by adding an ``is_dst``
+parameter to the ``utcoffset()``, ``dst()`` && ``tzname()`` methods.
+
+>>> tz = timezone('America/St_Johns')
+
+>>> normal = datetime(2009, 9, 1)
+>>> ambiguous = datetime(2009, 10, 31, 23, 30)
+
+The ``is_dst`` parameter is ignored for most timestamps. It is only used
+during DST transition ambiguous periods to resolve that ambiguity.
+
+>>> print(tz.utcoffset(normal, is_dst=True))
+-1 day, 21:30:00
+>>> print(tz.dst(normal, is_dst=True))
+1:00:00
+>>> tz.tzname(normal, is_dst=True)
+'NDT'
+
+>>> print(tz.utcoffset(ambiguous, is_dst=True))
+-1 day, 21:30:00
+>>> print(tz.dst(ambiguous, is_dst=True))
+1:00:00
+>>> tz.tzname(ambiguous, is_dst=True)
+'NDT'
+
+>>> print(tz.utcoffset(normal, is_dst=False))
+-1 day, 21:30:00
+>>> tz.dst(normal, is_dst=False).seconds
+3600
+>>> tz.tzname(normal, is_dst=False)
+'NDT'
+
+>>> print(tz.utcoffset(ambiguous, is_dst=False))
+-1 day, 20:30:00
+>>> tz.dst(ambiguous, is_dst=False)
+datetime.timedelta(0)
+>>> tz.tzname(ambiguous, is_dst=False)
+'NST'
+
+If ``is_dst`` is not specified, ambiguous timestamps will raise
+an ``pytz.exceptions.AmbiguousTimeError`` exception.
+
+>>> print(tz.utcoffset(normal))
+-1 day, 21:30:00
+>>> print(tz.dst(normal))
+1:00:00
+>>> tz.tzname(normal)
+'NDT'
+
+>>> import pytz.exceptions
+>>> try:
+... tz.utcoffset(ambiguous)
+... except pytz.exceptions.AmbiguousTimeError:
+... print('pytz.exceptions.AmbiguousTimeError: %s' % ambiguous)
+pytz.exceptions.AmbiguousTimeError: 2009-10-31 23:30:00
+>>> try:
+... tz.dst(ambiguous)
+... except pytz.exceptions.AmbiguousTimeError:
+... print('pytz.exceptions.AmbiguousTimeError: %s' % ambiguous)
+pytz.exceptions.AmbiguousTimeError: 2009-10-31 23:30:00
+>>> try:
+... tz.tzname(ambiguous)
+... except pytz.exceptions.AmbiguousTimeError:
+... print('pytz.exceptions.AmbiguousTimeError: %s' % ambiguous)
+pytz.exceptions.AmbiguousTimeError: 2009-10-31 23:30:00
+
+
+Problems with Localtime
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The major problem we have to deal with is that certain datetimes
+may occur twice in a year. For example, in the US/Eastern timezone
+on the last Sunday morning in October, the following sequence
+happens:
+
+ - 01:00 EDT occurs
+ - 1 hour later, instead of 2:00am the clock is turned back 1 hour
+ and 01:00 happens again (this time 01:00 EST)
+
+In fact, every instant between 01:00 and 02:00 occurs twice. This means
+that if you try and create a time in the 'US/Eastern' timezone
+the standard datetime syntax, there is no way to specify if you meant
+before of after the end-of-daylight-saving-time transition. Using the
+pytz custom syntax, the best you can do is make an educated guess:
+
+>>> loc_dt = eastern.localize(datetime(2002, 10, 27, 1, 30, 00))
+>>> loc_dt.strftime(fmt)
+'2002-10-27 01:30:00 EST-0500'
+
+As you can see, the system has chosen one for you and there is a 50%
+chance of it being out by one hour. For some applications, this does
+not matter. However, if you are trying to schedule meetings with people
+in different timezones or analyze log files it is not acceptable.
+
+The best and simplest solution is to stick with using UTC. The pytz
+package encourages using UTC for internal timezone representation by
+including a special UTC implementation based on the standard Python
+reference implementation in the Python documentation.
+
+The UTC timezone unpickles to be the same instance, and pickles to a
+smaller size than other pytz tzinfo instances. The UTC implementation
+can be obtained as pytz.utc, pytz.UTC, or pytz.timezone('UTC').
+
+>>> import pickle, pytz
+>>> dt = datetime(2005, 3, 1, 14, 13, 21, tzinfo=utc)
+>>> naive = dt.replace(tzinfo=None)
+>>> p = pickle.dumps(dt, 1)
+>>> naive_p = pickle.dumps(naive, 1)
+>>> len(p) - len(naive_p)
+17
+>>> new = pickle.loads(p)
+>>> new == dt
+True
+>>> new is dt
+False
+>>> new.tzinfo is dt.tzinfo
+True
+>>> pytz.utc is pytz.UTC is pytz.timezone('UTC')
+True
+
+Note that some other timezones are commonly thought of as the same (GMT,
+Greenwich, Universal, etc.). The definition of UTC is distinct from these
+other timezones, and they are not equivalent. For this reason, they will
+not compare the same in Python.
+
+>>> utc == pytz.timezone('GMT')
+False
+
+See the section `What is UTC`_, below.
+
+If you insist on working with local times, this library provides a
+facility for constructing them unambiguously:
+
+>>> loc_dt = datetime(2002, 10, 27, 1, 30, 00)
+>>> est_dt = eastern.localize(loc_dt, is_dst=True)
+>>> edt_dt = eastern.localize(loc_dt, is_dst=False)
+>>> print(est_dt.strftime(fmt) + ' / ' + edt_dt.strftime(fmt))
+2002-10-27 01:30:00 EDT-0400 / 2002-10-27 01:30:00 EST-0500
+
+If you pass None as the is_dst flag to localize(), pytz will refuse to
+guess and raise exceptions if you try to build ambiguous or non-existent
+times.
+
+For example, 1:30am on 27th Oct 2002 happened twice in the US/Eastern
+timezone when the clocks where put back at the end of Daylight Saving
+Time:
+
+>>> dt = datetime(2002, 10, 27, 1, 30, 00)
+>>> try:
+... eastern.localize(dt, is_dst=None)
+... except pytz.exceptions.AmbiguousTimeError:
+... print('pytz.exceptions.AmbiguousTimeError: %s' % dt)
+pytz.exceptions.AmbiguousTimeError: 2002-10-27 01:30:00
+
+Similarly, 2:30am on 7th April 2002 never happened at all in the
+US/Eastern timezone, as the clocks where put forward at 2:00am skipping
+the entire hour:
+
+>>> dt = datetime(2002, 4, 7, 2, 30, 00)
+>>> try:
+... eastern.localize(dt, is_dst=None)
+... except pytz.exceptions.NonExistentTimeError:
+... print('pytz.exceptions.NonExistentTimeError: %s' % dt)
+pytz.exceptions.NonExistentTimeError: 2002-04-07 02:30:00
+
+Both of these exceptions share a common base class to make error handling
+easier:
+
+>>> isinstance(pytz.AmbiguousTimeError(), pytz.InvalidTimeError)
+True
+>>> isinstance(pytz.NonExistentTimeError(), pytz.InvalidTimeError)
+True
+
+
+A special case is where countries change their timezone definitions
+with no daylight savings time switch. For example, in 1915 Warsaw
+switched from Warsaw time to Central European time with no daylight savings
+transition. So at the stroke of midnight on August 5th 1915 the clocks
+were wound back 24 minutes creating an ambiguous time period that cannot
+be specified without referring to the timezone abbreviation or the
+actual UTC offset. In this case midnight happened twice, neither time
+during a daylight saving time period. pytz handles this transition by
+treating the ambiguous period before the switch as daylight savings
+time, and the ambiguous period after as standard time.
+
+
+>>> warsaw = pytz.timezone('Europe/Warsaw')
+>>> amb_dt1 = warsaw.localize(datetime(1915, 8, 4, 23, 59, 59), is_dst=True)
+>>> amb_dt1.strftime(fmt)
+'1915-08-04 23:59:59 WMT+0124'
+>>> amb_dt2 = warsaw.localize(datetime(1915, 8, 4, 23, 59, 59), is_dst=False)
+>>> amb_dt2.strftime(fmt)
+'1915-08-04 23:59:59 CET+0100'
+>>> switch_dt = warsaw.localize(datetime(1915, 8, 5, 00, 00, 00), is_dst=False)
+>>> switch_dt.strftime(fmt)
+'1915-08-05 00:00:00 CET+0100'
+>>> str(switch_dt - amb_dt1)
+'0:24:01'
+>>> str(switch_dt - amb_dt2)
+'0:00:01'
+
+The best way of creating a time during an ambiguous time period is
+by converting from another timezone such as UTC:
+
+>>> utc_dt = datetime(1915, 8, 4, 22, 36, tzinfo=pytz.utc)
+>>> utc_dt.astimezone(warsaw).strftime(fmt)
+'1915-08-04 23:36:00 CET+0100'
+
+The standard Python way of handling all these ambiguities is not to
+handle them, such as demonstrated in this example using the US/Eastern
+timezone definition from the Python documentation (Note that this
+implementation only works for dates between 1987 and 2006 - it is
+included for tests only!):
+
+>>> from pytz.reference import Eastern # pytz.reference only for tests
+>>> dt = datetime(2002, 10, 27, 0, 30, tzinfo=Eastern)
+>>> str(dt)
+'2002-10-27 00:30:00-04:00'
+>>> str(dt + timedelta(hours=1))
+'2002-10-27 01:30:00-05:00'
+>>> str(dt + timedelta(hours=2))
+'2002-10-27 02:30:00-05:00'
+>>> str(dt + timedelta(hours=3))
+'2002-10-27 03:30:00-05:00'
+
+Notice the first two results? At first glance you might think they are
+correct, but taking the UTC offset into account you find that they are
+actually two hours appart instead of the 1 hour we asked for.
+
+>>> from pytz.reference import UTC # pytz.reference only for tests
+>>> str(dt.astimezone(UTC))
+'2002-10-27 04:30:00+00:00'
+>>> str((dt + timedelta(hours=1)).astimezone(UTC))
+'2002-10-27 06:30:00+00:00'
+
+
+Country Information
+~~~~~~~~~~~~~~~~~~~
+
+A mechanism is provided to access the timezones commonly in use
+for a particular country, looked up using the ISO 3166 country code.
+It returns a list of strings that can be used to retrieve the relevant
+tzinfo instance using ``pytz.timezone()``:
+
+>>> print(' '.join(pytz.country_timezones['nz']))
+Pacific/Auckland Pacific/Chatham
+
+The Olson database comes with a ISO 3166 country code to English country
+name mapping that pytz exposes as a dictionary:
+
+>>> print(pytz.country_names['nz'])
+New Zealand
+
+
+What is UTC
+~~~~~~~~~~~
+
+'UTC' is `Coordinated Universal Time`_. It is a successor to, but distinct
+from, Greenwich Mean Time (GMT) and the various definitions of Universal
+Time. UTC is now the worldwide standard for regulating clocks and time
+measurement.
+
+All other timezones are defined relative to UTC, and include offsets like
+UTC+0800 - hours to add or subtract from UTC to derive the local time. No
+daylight saving time occurs in UTC, making it a useful timezone to perform
+date arithmetic without worrying about the confusion and ambiguities caused
+by daylight saving time transitions, your country changing its timezone, or
+mobile computers that roam through multiple timezones.
+
+.. _Coordinated Universal Time: https://en.wikipedia.org/wiki/Coordinated_Universal_Time
+
+
+Helpers
+~~~~~~~
+
+There are two lists of timezones provided.
+
+``all_timezones`` is the exhaustive list of the timezone names that can
+be used.
+
+>>> from pytz import all_timezones
+>>> len(all_timezones) >= 500
+True
+>>> 'Etc/Greenwich' in all_timezones
+True
+
+``common_timezones`` is a list of useful, current timezones. It doesn't
+contain deprecated zones or historical zones, except for a few I've
+deemed in common usage, such as US/Eastern (open a bug report if you
+think other timezones are deserving of being included here). It is also
+a sequence of strings.
+
+>>> from pytz import common_timezones
+>>> len(common_timezones) < len(all_timezones)
+True
+>>> 'Etc/Greenwich' in common_timezones
+False
+>>> 'Australia/Melbourne' in common_timezones
+True
+>>> 'US/Eastern' in common_timezones
+True
+>>> 'Canada/Eastern' in common_timezones
+True
+>>> 'Australia/Yancowinna' in all_timezones
+True
+>>> 'Australia/Yancowinna' in common_timezones
+False
+
+Both ``common_timezones`` and ``all_timezones`` are alphabetically
+sorted:
+
+>>> common_timezones_dupe = common_timezones[:]
+>>> common_timezones_dupe.sort()
+>>> common_timezones == common_timezones_dupe
+True
+>>> all_timezones_dupe = all_timezones[:]
+>>> all_timezones_dupe.sort()
+>>> all_timezones == all_timezones_dupe
+True
+
+``all_timezones`` and ``common_timezones`` are also available as sets.
+
+>>> from pytz import all_timezones_set, common_timezones_set
+>>> 'US/Eastern' in all_timezones_set
+True
+>>> 'US/Eastern' in common_timezones_set
+True
+>>> 'Australia/Victoria' in common_timezones_set
+False
+
+You can also retrieve lists of timezones used by particular countries
+using the ``country_timezones()`` function. It requires an ISO-3166
+two letter country code.
+
+>>> from pytz import country_timezones
+>>> print(' '.join(country_timezones('ch')))
+Europe/Zurich
+>>> print(' '.join(country_timezones('CH')))
+Europe/Zurich
+
+
+Internationalization - i18n/l10n
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Pytz is an interface to the IANA database, which uses ASCII names. The `Unicode Consortium's Unicode Locales (CLDR) `_
+project provides translations. Python packages such as
+`Babel `_
+and Thomas Khyn's `l18n `_ package can be used
+to access these translations from Python.
+
+
+License
+~~~~~~~
+
+MIT license.
+
+This code is also available as part of Zope 3 under the Zope Public
+License, Version 2.1 (ZPL).
+
+I'm happy to relicense this code if necessary for inclusion in other
+open source projects.
+
+
+Latest Versions
+~~~~~~~~~~~~~~~
+
+This package will be updated after releases of the Olson timezone
+database. The latest version can be downloaded from the `Python Package
+Index `_. The code that is used
+to generate this distribution is hosted on Github and available
+using git::
+
+ git clone https://github.com/stub42/pytz.git
+
+Announcements of new releases are made on
+`Launchpad `_, and the
+`Atom feed `_
+hosted there.
+
+
+Bugs, Feature Requests & Patches
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Bugs should be reported on `Github `_.
+Feature requests are unlikely to be considered, and efforts instead directed
+to timezone support now built into Python or packages that work with it.
+
+
+Security Issues
+~~~~~~~~~~~~~~~
+
+Reports about security issues can be made via `Tidelift `_.
+
+
+Issues & Limitations
+~~~~~~~~~~~~~~~~~~~~
+
+- This project is in maintenance mode. Projects using Python 3.9 or later
+ are best served by using the timezone functionaly now included in core
+ Python and packages that work with it such as `tzdata `_.
+
+- Offsets from UTC are rounded to the nearest whole minute, so timezones
+ such as Europe/Amsterdam pre 1937 will be up to 30 seconds out. This
+ was a limitation of the Python datetime library.
+
+- If you think a timezone definition is incorrect, I probably can't fix
+ it. pytz is a direct translation of the Olson timezone database, and
+ changes to the timezone definitions need to be made to this source.
+ If you find errors they should be reported to the time zone mailing
+ list, linked from http://www.iana.org/time-zones.
+
+
+Further Reading
+~~~~~~~~~~~~~~~
+
+More info than you want to know about timezones:
+https://data.iana.org/time-zones/tz-link.html
+
+
+Contact
+~~~~~~~
+
+Stuart Bishop
diff --git a/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/RECORD b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/RECORD
new file mode 100644
index 0000000..f9afc2a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/RECORD
@@ -0,0 +1,623 @@
+pytz-2025.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+pytz-2025.2.dist-info/LICENSE.txt,sha256=vosaN-vibFkqkPbA6zMQOn84POL010mMCvmlJpkKB7g,1088
+pytz-2025.2.dist-info/METADATA,sha256=5iDk4fnxyAGWGTiNTaSW6wIRmhPzWqrVXwImlKPIH2w,22374
+pytz-2025.2.dist-info/RECORD,,
+pytz-2025.2.dist-info/WHEEL,sha256=-G_t0oGuE7UD0DrSpVZnq1hHMBV9DD2XkS5v7XpmTnk,110
+pytz-2025.2.dist-info/top_level.txt,sha256=6xRYlt934v1yHb1JIrXgHyGxn3cqACvd-yE8ski_kcc,5
+pytz-2025.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
+pytz/__init__.py,sha256=dml-pbWn-1xqv_ZWHoKoPmhruaO63GoIubnxtFnEvDc,35125
+pytz/__pycache__/__init__.cpython-312.pyc,,
+pytz/__pycache__/exceptions.cpython-312.pyc,,
+pytz/__pycache__/lazy.cpython-312.pyc,,
+pytz/__pycache__/reference.cpython-312.pyc,,
+pytz/__pycache__/tzfile.cpython-312.pyc,,
+pytz/__pycache__/tzinfo.cpython-312.pyc,,
+pytz/exceptions.py,sha256=434ZcuLlpLQY9mWoGq7zJMV1TyiYvVgpKBU1qZkbDjM,1571
+pytz/lazy.py,sha256=toeR5uDWKBj6ezsUZ4elNP6CEMtK7CO2jS9A30nsFbo,5404
+pytz/reference.py,sha256=zUtCki7JFEmrzrjNsfMD7YL0lWDxynKc1Ubo4iXSs74,3778
+pytz/tzfile.py,sha256=K2y7pZs4vydpZVftrfAA_-hgw17y1Szc7z_QCse6udU,4723
+pytz/tzinfo.py,sha256=XfaVOoO3KsCvtUYaCd0fvgBXWZ8tgevGYUoBh_uiE60,19340
+pytz/zoneinfo/Africa/Abidjan,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Africa/Accra,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Africa/Addis_Ababa,sha256=yJsuJTqJJqbOz37_NOS_zbf-JNr_IthHGMMN7sDqSWg,265
+pytz/zoneinfo/Africa/Algiers,sha256=vaFpjNVCwObnbfu82rOQzdJvN6nVgmpXpQ1aqzfzsqY,735
+pytz/zoneinfo/Africa/Asmara,sha256=yJsuJTqJJqbOz37_NOS_zbf-JNr_IthHGMMN7sDqSWg,265
+pytz/zoneinfo/Africa/Asmera,sha256=yJsuJTqJJqbOz37_NOS_zbf-JNr_IthHGMMN7sDqSWg,265
+pytz/zoneinfo/Africa/Bamako,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Africa/Bangui,sha256=z_6wKCzL1_ug5JP_hneh5abdUZeIUELkN_ladz-ESEY,235
+pytz/zoneinfo/Africa/Banjul,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Africa/Bissau,sha256=IjuxDP6EZiDHFvl_bHS6NN7sdRxLKXllooBC829poak,194
+pytz/zoneinfo/Africa/Blantyre,sha256=RE7TpxBBS8a_Q-sn5ZHaSdO-PbFTRJpqDJRz9-Of28s,149
+pytz/zoneinfo/Africa/Brazzaville,sha256=z_6wKCzL1_ug5JP_hneh5abdUZeIUELkN_ladz-ESEY,235
+pytz/zoneinfo/Africa/Bujumbura,sha256=RE7TpxBBS8a_Q-sn5ZHaSdO-PbFTRJpqDJRz9-Of28s,149
+pytz/zoneinfo/Africa/Cairo,sha256=Lft-GCLQhaSJm9VqUmsEFoHIS1Vhfa7pFJn9GZCpifs,2399
+pytz/zoneinfo/Africa/Casablanca,sha256=4RqVbw_F3ZucopIC2ivAJ8WDwj5wRODAB67tBpdXcgA,2429
+pytz/zoneinfo/Africa/Ceuta,sha256=Cw-2_nFDGbN8WqIsVpcauyZooWX8j3Kmx2PnC0fHut8,2052
+pytz/zoneinfo/Africa/Conakry,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Africa/Dakar,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Africa/Dar_es_Salaam,sha256=yJsuJTqJJqbOz37_NOS_zbf-JNr_IthHGMMN7sDqSWg,265
+pytz/zoneinfo/Africa/Djibouti,sha256=yJsuJTqJJqbOz37_NOS_zbf-JNr_IthHGMMN7sDqSWg,265
+pytz/zoneinfo/Africa/Douala,sha256=z_6wKCzL1_ug5JP_hneh5abdUZeIUELkN_ladz-ESEY,235
+pytz/zoneinfo/Africa/El_Aaiun,sha256=UWCCqQLJxd8qsTYw82kz9W1suwW5TRgnZw31sDWDz20,2295
+pytz/zoneinfo/Africa/Freetown,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Africa/Gaborone,sha256=RE7TpxBBS8a_Q-sn5ZHaSdO-PbFTRJpqDJRz9-Of28s,149
+pytz/zoneinfo/Africa/Harare,sha256=RE7TpxBBS8a_Q-sn5ZHaSdO-PbFTRJpqDJRz9-Of28s,149
+pytz/zoneinfo/Africa/Johannesburg,sha256=bBvMdSZo53WFowiuhUO9C8zY6BOGViboCb-U8_49l34,246
+pytz/zoneinfo/Africa/Juba,sha256=UVnIqEPJwHLTMC-r5qZQHNv9opoYVsKdq-ta_5XUw_Q,679
+pytz/zoneinfo/Africa/Kampala,sha256=yJsuJTqJJqbOz37_NOS_zbf-JNr_IthHGMMN7sDqSWg,265
+pytz/zoneinfo/Africa/Khartoum,sha256=MYWDoJ3AcCItZdApoeOgtWWDDxquwTon5v5TOGP70-o,679
+pytz/zoneinfo/Africa/Kigali,sha256=RE7TpxBBS8a_Q-sn5ZHaSdO-PbFTRJpqDJRz9-Of28s,149
+pytz/zoneinfo/Africa/Kinshasa,sha256=z_6wKCzL1_ug5JP_hneh5abdUZeIUELkN_ladz-ESEY,235
+pytz/zoneinfo/Africa/Lagos,sha256=z_6wKCzL1_ug5JP_hneh5abdUZeIUELkN_ladz-ESEY,235
+pytz/zoneinfo/Africa/Libreville,sha256=z_6wKCzL1_ug5JP_hneh5abdUZeIUELkN_ladz-ESEY,235
+pytz/zoneinfo/Africa/Lome,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Africa/Luanda,sha256=z_6wKCzL1_ug5JP_hneh5abdUZeIUELkN_ladz-ESEY,235
+pytz/zoneinfo/Africa/Lubumbashi,sha256=RE7TpxBBS8a_Q-sn5ZHaSdO-PbFTRJpqDJRz9-Of28s,149
+pytz/zoneinfo/Africa/Lusaka,sha256=RE7TpxBBS8a_Q-sn5ZHaSdO-PbFTRJpqDJRz9-Of28s,149
+pytz/zoneinfo/Africa/Malabo,sha256=z_6wKCzL1_ug5JP_hneh5abdUZeIUELkN_ladz-ESEY,235
+pytz/zoneinfo/Africa/Maputo,sha256=RE7TpxBBS8a_Q-sn5ZHaSdO-PbFTRJpqDJRz9-Of28s,149
+pytz/zoneinfo/Africa/Maseru,sha256=bBvMdSZo53WFowiuhUO9C8zY6BOGViboCb-U8_49l34,246
+pytz/zoneinfo/Africa/Mbabane,sha256=bBvMdSZo53WFowiuhUO9C8zY6BOGViboCb-U8_49l34,246
+pytz/zoneinfo/Africa/Mogadishu,sha256=yJsuJTqJJqbOz37_NOS_zbf-JNr_IthHGMMN7sDqSWg,265
+pytz/zoneinfo/Africa/Monrovia,sha256=-VsJW5cU4KdvfgYaQVv4lcuzmaKIVFMd42nO6RXOBdU,208
+pytz/zoneinfo/Africa/Nairobi,sha256=yJsuJTqJJqbOz37_NOS_zbf-JNr_IthHGMMN7sDqSWg,265
+pytz/zoneinfo/Africa/Ndjamena,sha256=8T3A0Zm9Gj0Bvm6rd88t3GAXKiKdGUfHlIqYlkYI0KM,199
+pytz/zoneinfo/Africa/Niamey,sha256=z_6wKCzL1_ug5JP_hneh5abdUZeIUELkN_ladz-ESEY,235
+pytz/zoneinfo/Africa/Nouakchott,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Africa/Ouagadougou,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Africa/Porto-Novo,sha256=z_6wKCzL1_ug5JP_hneh5abdUZeIUELkN_ladz-ESEY,235
+pytz/zoneinfo/Africa/Sao_Tome,sha256=MdjxpQ268uzJ7Zx1ZroFUtRUwqsJ6F_yY3AYV9FXw1I,254
+pytz/zoneinfo/Africa/Timbuktu,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Africa/Tripoli,sha256=W1dptGD70T7ppGoo0fczFQeDiIp0nultLNPV66MwB2c,625
+pytz/zoneinfo/Africa/Tunis,sha256=OFVMEM4eYT2Ez0beuhEUCTSIpcFldWxsV2uEoTZIUNI,689
+pytz/zoneinfo/Africa/Windhoek,sha256=xuhvudrMH4alnVmouSTQI8YL8F_HbgsF2EQ7AZKzuHs,955
+pytz/zoneinfo/America/Adak,sha256=IB1DhwJQAKbhPJ9jHLf8zW5Dad7HIkBS-dhv64E1OlM,2356
+pytz/zoneinfo/America/Anchorage,sha256=oZA1NSPS2BWdymYpnCHFO8BlYVS-ll5KLg2Ez9CbETs,2371
+pytz/zoneinfo/America/Anguilla,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Antigua,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Araguaina,sha256=G6v9wYFZ8EB4WQfIsqRbbiiKd2b27j7Zt5dFjBbzx2o,870
+pytz/zoneinfo/America/Argentina/Buenos_Aires,sha256=JmU8lBwmy29gR6OmeytvFdMRx6ObJKnYNHmLyMmXX2M,1062
+pytz/zoneinfo/America/Argentina/Catamarca,sha256=uMCJXXGYmNESHVvj5RYBZ0McrOdE14hwm17l25MgRW0,1062
+pytz/zoneinfo/America/Argentina/ComodRivadavia,sha256=uMCJXXGYmNESHVvj5RYBZ0McrOdE14hwm17l25MgRW0,1062
+pytz/zoneinfo/America/Argentina/Cordoba,sha256=uniNihhMHnr4XK4WpwiPUnrAT0YPmvzqB6f0hRLtXvY,1062
+pytz/zoneinfo/America/Argentina/Jujuy,sha256=PGmAehypCxj0XCenCSWqylDIPbKLK0DlrwJK_24D590,1034
+pytz/zoneinfo/America/Argentina/La_Rioja,sha256=Um6XoVXhsr62ad1mWuebe6NY0ZHauBdR9tMGDgqCOHg,1076
+pytz/zoneinfo/America/Argentina/Mendoza,sha256=xcOVtvRyVYFAU90y2QYwpyQhpMLyAp7-Fxvku4kgl0c,1062
+pytz/zoneinfo/America/Argentina/Rio_Gallegos,sha256=F9ZKR4o8gLHX7QBuIjMapGIdmzJxpqwbouPgZ5MqDpY,1062
+pytz/zoneinfo/America/Argentina/Salta,sha256=h1KYrDNIapvDkYhi1PaB8WD1qWOe4vhhgDJWDCGV4jc,1034
+pytz/zoneinfo/America/Argentina/San_Juan,sha256=AI2GltA80mPNzhHxYycuEwIbO1ANXyIqBQZMpjqKqdQ,1076
+pytz/zoneinfo/America/Argentina/San_Luis,sha256=2ItGRcLVK2wx8MyJsHbIBBeAkU4B-MN5x1ZxNyZ7UJE,1088
+pytz/zoneinfo/America/Argentina/Tucuman,sha256=twO-FqtNJV8XOzWTvFQ-xnEcWCoDUHY3gpVIG0Mzbf8,1090
+pytz/zoneinfo/America/Argentina/Ushuaia,sha256=A6IbpVlY9IIPoSKMFRR9DMROdwXUSDc2HsASueOSnqo,1062
+pytz/zoneinfo/America/Aruba,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Asuncion,sha256=9yfGiENhXNgd2_0xHVsF-hLeJkGSqRs-zD9O945KJWc,1644
+pytz/zoneinfo/America/Atikokan,sha256=kayA_pdpMcSQ0FjIzotdcf-m1JYfbKE-qcFT8LC8zqA,182
+pytz/zoneinfo/America/Atka,sha256=IB1DhwJQAKbhPJ9jHLf8zW5Dad7HIkBS-dhv64E1OlM,2356
+pytz/zoneinfo/America/Bahia,sha256=qi7dA6FofDhLxVMmd2L8bK3HeaQnc9X-jiijwyfhs3g,1010
+pytz/zoneinfo/America/Bahia_Banderas,sha256=MvrXGJ5LzaHOeguJqxszxjxMhVafGVbk-ojXEc7_YEI,1100
+pytz/zoneinfo/America/Barbados,sha256=ima-Qrrhazu4Qfvu2Z0-e6E-GTiYknuJBu6c2yVG9LE,436
+pytz/zoneinfo/America/Belem,sha256=aZMUgtFDdHNISpqyQRYbmS2IBD-BAS3CaJnhu6onLCY,562
+pytz/zoneinfo/America/Belize,sha256=pkfLY2KfPchbeJa1pWcXmWAwp4ZlRvxWLVezXnrbkws,1614
+pytz/zoneinfo/America/Blanc-Sablon,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Boa_Vista,sha256=dMtaG11kGlJrgJJgGWEDZZAmnO_HfT3L4X8pI72LLFY,618
+pytz/zoneinfo/America/Bogota,sha256=Z1ernZZGQxulE8KFWHYWcM3SV1jn2_QEc1Q0OJzHRak,232
+pytz/zoneinfo/America/Boise,sha256=7HQsNPJiUheQgFz5kVLvTnf5xhXAYaeANqDskxKz2Vs,2410
+pytz/zoneinfo/America/Buenos_Aires,sha256=JmU8lBwmy29gR6OmeytvFdMRx6ObJKnYNHmLyMmXX2M,1062
+pytz/zoneinfo/America/Cambridge_Bay,sha256=_4xRlX3WdVpEcqoT6myD7NeTCXnn9OYk_iH006bwULo,2254
+pytz/zoneinfo/America/Campo_Grande,sha256=gINiXg5i2e6Rh2Nbo2bFqhPAJL4F4cAqGnBankXTDXw,1430
+pytz/zoneinfo/America/Cancun,sha256=EdV0Nw2WjM7VnjFHoq5jsSbLuuE7eP1OE74utEyWJG4,864
+pytz/zoneinfo/America/Caracas,sha256=mUNMFdDzZLav_ePA1ocBdmqVBierkeEszTIFpNCm5J0,250
+pytz/zoneinfo/America/Catamarca,sha256=uMCJXXGYmNESHVvj5RYBZ0McrOdE14hwm17l25MgRW0,1062
+pytz/zoneinfo/America/Cayenne,sha256=4k7Iv1woX4atqePKrcvMQD2Vk9Tmma7rW_AW_R62pCc,184
+pytz/zoneinfo/America/Cayman,sha256=kayA_pdpMcSQ0FjIzotdcf-m1JYfbKE-qcFT8LC8zqA,182
+pytz/zoneinfo/America/Chicago,sha256=_roybr6I6sIAF6cYdIxGxoRpoef153Fty48dQ6bm9oY,3592
+pytz/zoneinfo/America/Chihuahua,sha256=3Ngzbedg8AzAqxsbQSG0jVRx-LxYlw1i3kx-Yzl-2Ic,1102
+pytz/zoneinfo/America/Ciudad_Juarez,sha256=ir4b27DiFrhL0H4fZQ92nEa-BBoPfLWIz3phU373dgE,1538
+pytz/zoneinfo/America/Coral_Harbour,sha256=kayA_pdpMcSQ0FjIzotdcf-m1JYfbKE-qcFT8LC8zqA,182
+pytz/zoneinfo/America/Cordoba,sha256=uniNihhMHnr4XK4WpwiPUnrAT0YPmvzqB6f0hRLtXvY,1062
+pytz/zoneinfo/America/Costa_Rica,sha256=74rYa6lrgIkyls9PkHo8SCYl9oOqiuG5S7MWdnJelP4,316
+pytz/zoneinfo/America/Coyhaique,sha256=beZXU6Lw5jx2Wp3dNRkFiofXGma2dM6DsqvJT9CSHdc,2126
+pytz/zoneinfo/America/Creston,sha256=illz0sYuLL8lIPK0Tkou6dL0Vck_D0W_3rRTOvFYRmQ,360
+pytz/zoneinfo/America/Cuiaba,sha256=GRJqkhRXNsOUcgjZddQxRIJdRYaw9pM_YLWbun88dkg,1402
+pytz/zoneinfo/America/Curacao,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Danmarkshavn,sha256=YRZAfUCoVtaL1L-MYMYMH1wyOaVQnfUo_gFnvMXSuzw,698
+pytz/zoneinfo/America/Dawson,sha256=rAHhyuMuyjf_eyA2SBG76MRBf_fj_xi5FAuiWVQgJhw,1614
+pytz/zoneinfo/America/Dawson_Creek,sha256=aJXCyP4j3ggE4wGCN-LrS9hpD_5zWHzQTeSAKTWEPUM,1050
+pytz/zoneinfo/America/Denver,sha256=MugZwApDs8NI9TnXANQlUE8guNBowWQY0m-ptpPndck,2460
+pytz/zoneinfo/America/Detroit,sha256=hecz8yqY2Cj5B61G3gLZdAVZvRgK9l0P90c_gN-uD5g,2230
+pytz/zoneinfo/America/Dominica,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Edmonton,sha256=-TkIfc3QlvaCf0p8COZ43Y1HRBAl-nARUi-JdXeK1vE,2332
+pytz/zoneinfo/America/Eirunepe,sha256=j5eExkjFaqtC-D8XK0rGzoF9yEgbSlTbPqVG9WKhEa8,642
+pytz/zoneinfo/America/El_Salvador,sha256=gvGN8Lkj-sGm2_rs8OUjAMf1oMtKp2Xes6UfWT0WqgU,224
+pytz/zoneinfo/America/Ensenada,sha256=SluV7xzZm24LgMXSUVt1cD1AlE7y_bdE65HhDIdXLcs,2458
+pytz/zoneinfo/America/Fort_Nelson,sha256=erfODr3DrSpz65kAdO7Ts2dGbZxvddEP6gx4BX3y2J0,2240
+pytz/zoneinfo/America/Fort_Wayne,sha256=kNKy9Kj9ICsiYYfCCbAggzMA7exf-GpGPMxoXocHUyw,1682
+pytz/zoneinfo/America/Fortaleza,sha256=rjiSB0q1cBuMDOM9orW_uwe5UOLBwTlfjFotwOYe1mU,702
+pytz/zoneinfo/America/Glace_Bay,sha256=G8DGLGCapH_aYCF_OhaL5Qonf7FOAgAPwelO5htCWBc,2192
+pytz/zoneinfo/America/Godthab,sha256=KGXrMN-YkYpVCgLdpcfwMFQ77EsRAGsjUCG3yAUvVfw,1889
+pytz/zoneinfo/America/Goose_Bay,sha256=JgaLueghSvX2g725FOfIgpgvsqxZGykWOhAZWGpQZRY,3210
+pytz/zoneinfo/America/Grand_Turk,sha256=4YOFEPK60Bel2_fCsY6vSZxUcMJKjiKtyOf_Q0khEwU,1834
+pytz/zoneinfo/America/Grenada,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Guadeloupe,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Guatemala,sha256=dugUgCd6QY52yHkHuUP4jRWzo5x439IQigaYCvEF46Q,280
+pytz/zoneinfo/America/Guayaquil,sha256=j2UuIo-4RgSOlTNfu77mhZ92waNTeKFSvmoVemJooT0,232
+pytz/zoneinfo/America/Guyana,sha256=R0bOvCRDC8SRIexmhsduPdHbbRPwI2GviD9otExiUrk,248
+pytz/zoneinfo/America/Halifax,sha256=TZpmc5PwWoLfTfQoQ_b3U17BE2iVKSeNkR0Ho8mbTn8,3424
+pytz/zoneinfo/America/Havana,sha256=HUQeAuKBsEkI5SLZjqynXICOUVOajkKzKH5r-Ov5Odc,2416
+pytz/zoneinfo/America/Hermosillo,sha256=ixYKestLmS7gWobk9Kq6FtLZo1yqbWActrFUKluzctw,388
+pytz/zoneinfo/America/Indiana/Indianapolis,sha256=kNKy9Kj9ICsiYYfCCbAggzMA7exf-GpGPMxoXocHUyw,1682
+pytz/zoneinfo/America/Indiana/Knox,sha256=CsvZ5BKw2qVav3x_F8CU9taJdDk7jX41Cfsqms6jXV8,2444
+pytz/zoneinfo/America/Indiana/Marengo,sha256=f3tQ-lgMSUA7nvn64pXhKtJL7mWzGajoCega5MEJSbI,1738
+pytz/zoneinfo/America/Indiana/Petersburg,sha256=A88OHuM0Rg3iMLHjKgXq_d2jZCdVSytUQs-9W0KcFyQ,1920
+pytz/zoneinfo/America/Indiana/Tell_City,sha256=4dWqAr9Y2BXfL4pAQk-81c3gGl2cNdHXOD7_wJhhhn8,1700
+pytz/zoneinfo/America/Indiana/Vevay,sha256=H7VR2G-_sD_C5Rm4P3g1iRC1FWCPg4m0MGD3P1PLzsk,1430
+pytz/zoneinfo/America/Indiana/Vincennes,sha256=62mAxT7APFCaoygflnEzdOpe-fuW1yObI6m6EUUcS7A,1710
+pytz/zoneinfo/America/Indiana/Winamac,sha256=aZGM2jR8CH9BHSUq7XygiweDd6dorXLPXg246XsbR6s,1794
+pytz/zoneinfo/America/Indianapolis,sha256=kNKy9Kj9ICsiYYfCCbAggzMA7exf-GpGPMxoXocHUyw,1682
+pytz/zoneinfo/America/Inuvik,sha256=6J-mapDnrk9A1LtswoE34tqSy_ufedcEBNxixkrEjIo,2074
+pytz/zoneinfo/America/Iqaluit,sha256=feOnxAN0N0r-M1qlkrA4JMyawoc0tqae0iiBCPDAs4k,2202
+pytz/zoneinfo/America/Jamaica,sha256=wlagieUPRf5-beie-h7QsONbNzjGsm8vMs8uf28pw28,482
+pytz/zoneinfo/America/Jujuy,sha256=PGmAehypCxj0XCenCSWqylDIPbKLK0DlrwJK_24D590,1034
+pytz/zoneinfo/America/Juneau,sha256=k7hxb0aGRnfnE-DBi3LkcjAzRPyAf0_Hw0vVFfjGeb0,2353
+pytz/zoneinfo/America/Kentucky/Louisville,sha256=tP072xV_n_vIQjxxcJ77AGeGj6yL1KPpn3fwids9g1U,2788
+pytz/zoneinfo/America/Kentucky/Monticello,sha256=LtdyCo85BrXQs6rlH61Ym-8KqWHH6PwAOjD0QxhIdzM,2368
+pytz/zoneinfo/America/Knox_IN,sha256=CsvZ5BKw2qVav3x_F8CU9taJdDk7jX41Cfsqms6jXV8,2444
+pytz/zoneinfo/America/Kralendijk,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/La_Paz,sha256=hqfD8LQHupdZhji2e93_9pOQAT-R7muzzjP0nyfbFXY,218
+pytz/zoneinfo/America/Lima,sha256=HHgTnDUnCZzibvL0MrG8qyOuvjmYYw3e3R5VbnxMZs8,392
+pytz/zoneinfo/America/Los_Angeles,sha256=aJd7ua1tGG_vxser02AQpm4wAI3LLTdgh6QcSYYecmg,2852
+pytz/zoneinfo/America/Louisville,sha256=tP072xV_n_vIQjxxcJ77AGeGj6yL1KPpn3fwids9g1U,2788
+pytz/zoneinfo/America/Lower_Princes,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Maceio,sha256=3R5DlSe32kQDmoSVIWpcyk2o7qohr-rliwqDSGFIMyQ,730
+pytz/zoneinfo/America/Managua,sha256=xBzF01AHn2E2fD8Qdy-DHFe36UqoeNpKPfChduBKWdk,430
+pytz/zoneinfo/America/Manaus,sha256=F6RLOOeOi9lymZiQmQ9pR8tFpPZ6EguNdPfOc6BhXDE,590
+pytz/zoneinfo/America/Marigot,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Martinique,sha256=fMs80kOU2YFvC0f9y2eje97JeAtTYBamXrnlTunNLzQ,232
+pytz/zoneinfo/America/Matamoros,sha256=fq-PqdmZrQ98UsFmHA9ivjBZv5GEBRTOuLQ5Cu5ajW8,1418
+pytz/zoneinfo/America/Mazatlan,sha256=BWH2NqVPA1PsyELPN_2BF8KllrsmQkqg1eujsQvnnx8,1060
+pytz/zoneinfo/America/Mendoza,sha256=xcOVtvRyVYFAU90y2QYwpyQhpMLyAp7-Fxvku4kgl0c,1062
+pytz/zoneinfo/America/Menominee,sha256=Arv9WLbfhNcpRsUjHDU757BEdwlp08Gt30AixG3gZ04,2274
+pytz/zoneinfo/America/Merida,sha256=SVNEHCazjomftnuPVBayFI-E-IQ0WmluHfTpHP0h3d0,1004
+pytz/zoneinfo/America/Metlakatla,sha256=twmieGTVY2V-U8nFxqvx7asYv8GVjeWdLtrOI7UApVI,1423
+pytz/zoneinfo/America/Mexico_City,sha256=Uog2-FMWz2o12jR6sK9vemJamLeo6OEFMQR3s0xTxkc,1222
+pytz/zoneinfo/America/Miquelon,sha256=l5txBJYe9HTRZlILcbSL_HNDYrjUb0ouecNy7QEkg9c,1652
+pytz/zoneinfo/America/Moncton,sha256=Wmv-bk9aKKcWWzOpc1UFu67HOfwaIk2Wmh3LgqGctys,3154
+pytz/zoneinfo/America/Monterrey,sha256=YixTESJubf6ZBUXy6g32hAM2gR4GXXPqOU4tv0L3kG0,1114
+pytz/zoneinfo/America/Montevideo,sha256=dQEBE4mjZPtyRjKXK6Z-bMHJdFqpwhIzxDH4x04rKYk,1496
+pytz/zoneinfo/America/Montreal,sha256=pYehoWB0Ofe6woPhgV8r26-5ZJpFPRjgbC5E5pltiI8,3494
+pytz/zoneinfo/America/Montserrat,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Nassau,sha256=pYehoWB0Ofe6woPhgV8r26-5ZJpFPRjgbC5E5pltiI8,3494
+pytz/zoneinfo/America/New_York,sha256=6e0H177gx2qdRC0JHvHwFmj-58TyYBTAqGixn-bBipU,3552
+pytz/zoneinfo/America/Nipigon,sha256=pYehoWB0Ofe6woPhgV8r26-5ZJpFPRjgbC5E5pltiI8,3494
+pytz/zoneinfo/America/Nome,sha256=2izM3-P-PqJ9za6MdhzFfMvPFNq7Gim69tAvEwPeY2s,2367
+pytz/zoneinfo/America/Noronha,sha256=feeRAijQqKylZgqe84nKhsFLycT5zIBm7mLIvdyGw4w,702
+pytz/zoneinfo/America/North_Dakota/Beulah,sha256=qtgbqNu8M3AkHF2n-_oSps1pYT4SxgclbkkPKbXaBHs,2396
+pytz/zoneinfo/America/North_Dakota/Center,sha256=9ZWbK9YKkquULyBUFS3Lr_idxbt7V7y4W4EO0Kn20sw,2396
+pytz/zoneinfo/America/North_Dakota/New_Salem,sha256=DH_bsQfuUnK2obdb06KgisO4XLqht12BXdrgUsZZveg,2396
+pytz/zoneinfo/America/Nuuk,sha256=KGXrMN-YkYpVCgLdpcfwMFQ77EsRAGsjUCG3yAUvVfw,1889
+pytz/zoneinfo/America/Ojinaga,sha256=b38Q_7VdkCZzaVwb7OXuddihJAzUKPTTqXcmpBm1ntE,1524
+pytz/zoneinfo/America/Panama,sha256=kayA_pdpMcSQ0FjIzotdcf-m1JYfbKE-qcFT8LC8zqA,182
+pytz/zoneinfo/America/Pangnirtung,sha256=feOnxAN0N0r-M1qlkrA4JMyawoc0tqae0iiBCPDAs4k,2202
+pytz/zoneinfo/America/Paramaribo,sha256=Z7UZvNlgd-qEUHjEPYXIkLNTgjMcCzk9EfUUEmUyd7M,248
+pytz/zoneinfo/America/Phoenix,sha256=illz0sYuLL8lIPK0Tkou6dL0Vck_D0W_3rRTOvFYRmQ,360
+pytz/zoneinfo/America/Port-au-Prince,sha256=09ZAJd4IOiMpfdpUuF1U44R_hRt6BvpAkFXOnYO9yOM,1434
+pytz/zoneinfo/America/Port_of_Spain,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Porto_Acre,sha256=0gpJUl46hQbp0P6Xj1S0NArIWeAryuuDXjsldvB5GHE,614
+pytz/zoneinfo/America/Porto_Velho,sha256=uSMV2hZWj-VyBhFBwC950wcThfN3jq6KlycESmQTLOA,562
+pytz/zoneinfo/America/Puerto_Rico,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Punta_Arenas,sha256=tR5uIf1351AWFqrqNtmXnhQWnKREmJaZqKBzaWRVMTQ,1902
+pytz/zoneinfo/America/Rainy_River,sha256=7P-_YQrneFcon7QKSTOnkiGjEppFDn3Z48MJ1qq8VBw,2868
+pytz/zoneinfo/America/Rankin_Inlet,sha256=nXgqjL3O2BV0em-Xk8qVRRZb_X0yQmHE6vmSSvI9Kzc,2066
+pytz/zoneinfo/America/Recife,sha256=bJ_HE0-JFio4-owpZ0pLO8U3ai0fiGu8QHL0DexLiLc,702
+pytz/zoneinfo/America/Regina,sha256=yjqT08pHbICYe83H8JmtaDBvCFqRv7Tfze3Y8xuXukw,980
+pytz/zoneinfo/America/Resolute,sha256=CnMU2dBI-63vt8-J0Q1Ropx-8b9pRCLjhvrycMIedGg,2066
+pytz/zoneinfo/America/Rio_Branco,sha256=0gpJUl46hQbp0P6Xj1S0NArIWeAryuuDXjsldvB5GHE,614
+pytz/zoneinfo/America/Rosario,sha256=uniNihhMHnr4XK4WpwiPUnrAT0YPmvzqB6f0hRLtXvY,1062
+pytz/zoneinfo/America/Santa_Isabel,sha256=SluV7xzZm24LgMXSUVt1cD1AlE7y_bdE65HhDIdXLcs,2458
+pytz/zoneinfo/America/Santarem,sha256=VmZP9S5pPucFxyqAOV908EmWXQZvgCgWLmlJJTUl0LE,588
+pytz/zoneinfo/America/Santiago,sha256=0CDw13dCMUsoquMupoJgupkzAUNhDK6E0lVxURA7osA,2515
+pytz/zoneinfo/America/Santo_Domingo,sha256=DKtaEj8fQ92ybITTWU4Bm160S9pzJmUVbjaWRnenxU4,458
+pytz/zoneinfo/America/Sao_Paulo,sha256=BMBnRO4_4HjvO4t3njjrMGZr-ZPmegkvyvL8KPY6ZM4,1430
+pytz/zoneinfo/America/Scoresbysund,sha256=K-qkiMCCFgOe8ccPMABA-lDjc9vb6wpluBOCVfiBdLI,1935
+pytz/zoneinfo/America/Shiprock,sha256=MugZwApDs8NI9TnXANQlUE8guNBowWQY0m-ptpPndck,2460
+pytz/zoneinfo/America/Sitka,sha256=aiS7Fk37hZpzZ9VkeJQeF-BqTLRC1QOTCgMAJwT8UxA,2329
+pytz/zoneinfo/America/St_Barthelemy,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/St_Johns,sha256=r1-17uKv27eZ3JsVkw_DLZQbo6wvjuuVu7C2pDsmOgI,3655
+pytz/zoneinfo/America/St_Kitts,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/St_Lucia,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/St_Thomas,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/St_Vincent,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Swift_Current,sha256=RRKOF7vZC8VvYxD8PP4J1_hUPayKBP7Lu80avRkfPDY,560
+pytz/zoneinfo/America/Tegucigalpa,sha256=EzOz7ntTlreMq69JZ2CcAb8Ps98V9bUMN480tpPIyw4,252
+pytz/zoneinfo/America/Thule,sha256=8xuPRaZU8RgO5ECqFYHYmnHioc81sBOailkVu8Y02i8,1502
+pytz/zoneinfo/America/Thunder_Bay,sha256=pYehoWB0Ofe6woPhgV8r26-5ZJpFPRjgbC5E5pltiI8,3494
+pytz/zoneinfo/America/Tijuana,sha256=SluV7xzZm24LgMXSUVt1cD1AlE7y_bdE65HhDIdXLcs,2458
+pytz/zoneinfo/America/Toronto,sha256=pYehoWB0Ofe6woPhgV8r26-5ZJpFPRjgbC5E5pltiI8,3494
+pytz/zoneinfo/America/Tortola,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Vancouver,sha256=sknKH0jSPWam-DHfM35qXs8Nam7d5TFlkUI9Sgxryyg,2892
+pytz/zoneinfo/America/Virgin,sha256=hJHlV_-AGoMGUWuMpZRv9fLmghrzFHfrR9fRkcxaZJc,246
+pytz/zoneinfo/America/Whitehorse,sha256=TrR6PCnYG-mSClBMohqlP8qnYhXMUsydI-L-quXFxyM,1614
+pytz/zoneinfo/America/Winnipeg,sha256=7P-_YQrneFcon7QKSTOnkiGjEppFDn3Z48MJ1qq8VBw,2868
+pytz/zoneinfo/America/Yakutat,sha256=tFwnKbvwhyyn4LNTAn5ye_JWDdxjCerNDt7oOwUwO2M,2305
+pytz/zoneinfo/America/Yellowknife,sha256=-TkIfc3QlvaCf0p8COZ43Y1HRBAl-nARUi-JdXeK1vE,2332
+pytz/zoneinfo/Antarctica/Casey,sha256=VeaLOxTfDyjfGXq5Ul95JEIMXNWHSW-0N3yOoS7VK-c,423
+pytz/zoneinfo/Antarctica/Davis,sha256=XB12dEq0Q-3XkzBNTNC7G1fzH-WxxctIuZqI3zp8ypI,283
+pytz/zoneinfo/Antarctica/DumontDUrville,sha256=nB36HBWZTdh3TlP0DLFNz1KRQ0aHIfHbp7LC4Urp9fA,172
+pytz/zoneinfo/Antarctica/Macquarie,sha256=ie7RlaU8RHTorVVj-MX8StKMqx_oXf4UH2PUqpzcwe0,2260
+pytz/zoneinfo/Antarctica/Mawson,sha256=EjIFbqRdr2ZJBaI1XvoWRptnnW1LFrlhydxDDuIQjSI,185
+pytz/zoneinfo/Antarctica/McMurdo,sha256=gADjoyPo_QISQU6UJrAgcHp3HDaMoOFRdH-d23uBSyc,2437
+pytz/zoneinfo/Antarctica/Palmer,sha256=HTZY0M8td7oUx5REPgRCHuqKg5V3fjJEi4lYBNL4Etg,1404
+pytz/zoneinfo/Antarctica/Rothera,sha256=_9NY-f8vkozQYrjbUHP5YjcICg0-LuyA9PnIeK123RU,150
+pytz/zoneinfo/Antarctica/South_Pole,sha256=gADjoyPo_QISQU6UJrAgcHp3HDaMoOFRdH-d23uBSyc,2437
+pytz/zoneinfo/Antarctica/Syowa,sha256=oCKH7uafN8R1o-ijXGoT5U1JZxwvoLzJu_2Cqyi2hUM,151
+pytz/zoneinfo/Antarctica/Troll,sha256=fjcYppwr1FnjEssee-RLgGOANzoUyfjse-RGK46PR2E,1148
+pytz/zoneinfo/Antarctica/Vostok,sha256=KfftwdzK6PkMDz0d-D3z4HKIBgY9KqsqHnTnqsPMrUg,213
+pytz/zoneinfo/Arctic/Longyearbyen,sha256=XuR19xoPwaMvrrhJ-MOcbnqmbW1B7HQrl7OnQ2s7BwE,2298
+pytz/zoneinfo/Asia/Aden,sha256=oCKH7uafN8R1o-ijXGoT5U1JZxwvoLzJu_2Cqyi2hUM,151
+pytz/zoneinfo/Asia/Almaty,sha256=lPLWXk2f1mWYRQZFkIrq_5HkhocsUBis0M-yhdDHcBQ,983
+pytz/zoneinfo/Asia/Amman,sha256=Qv4cXXw7KBQWE882cgj0kjQ3wh1vpV1orJ2v2Jjxr2U,1433
+pytz/zoneinfo/Asia/Anadyr,sha256=WqKnHo5IHSWZ08d2sS5ytHtv0MQMoczP3W9zbDDrbYU,1174
+pytz/zoneinfo/Asia/Aqtau,sha256=4n654FZtDssXSfhQszjZG5OmtbE2zo1KbiWcYrFJg00,969
+pytz/zoneinfo/Asia/Aqtobe,sha256=1oFHTb-ybcTqLXm0r1ZOVgdYMTHlGoNs-Pgvux50d3E,997
+pytz/zoneinfo/Asia/Ashgabat,sha256=-sfGnRumio7_Bs8w9YH4xRDWgjB3wBeW7c0C56Qqk64,605
+pytz/zoneinfo/Asia/Ashkhabad,sha256=-sfGnRumio7_Bs8w9YH4xRDWgjB3wBeW7c0C56Qqk64,605
+pytz/zoneinfo/Asia/Atyrau,sha256=_U8COUIE9nG_HKddZE1Q0sPuz3rMwfjwmfnVDY_vSmg,977
+pytz/zoneinfo/Asia/Baghdad,sha256=S-plKI4zCLqI0idGABEk3oRTazNyrIj2T98-EtWtZD8,969
+pytz/zoneinfo/Asia/Bahrain,sha256=wklGY3WPGp-z1OUwb_KOHzRTwBndt1RfDg9Uttt36G4,185
+pytz/zoneinfo/Asia/Baku,sha256=6_hq98SGG0j0JA8qYx96WcIMZSLW4w460QXh_OM_ccg,1213
+pytz/zoneinfo/Asia/Bangkok,sha256=hf_5PVegQcFSS60CjS80C7h-TGOrfQ4ncm83N8VmZkk,185
+pytz/zoneinfo/Asia/Barnaul,sha256=3zeUimLTMrIZE0vX6XHFvB3MoqExoVbE5CSm6GV0zf0,1207
+pytz/zoneinfo/Asia/Beirut,sha256=_Z_2ZAg_iL9vU51JDB8CB04uXBDrf1kLIis-JnXaS2o,2154
+pytz/zoneinfo/Asia/Bishkek,sha256=IOoUyjABILCkXu1rjCIqSwAufRYFklc5YAC4jdhVw6Q,969
+pytz/zoneinfo/Asia/Brunei,sha256=D5qtyWJ_SM8bTQeJJIYhqqojxlVKbrFC1EYMDU9GzXQ,469
+pytz/zoneinfo/Asia/Calcutta,sha256=6Qw0EDbLcgMgDik8s7UTJn4QSjmllPNeGVJU5rwKF88,285
+pytz/zoneinfo/Asia/Chita,sha256=LbSlS23swFkANUScg8zkNR0imANWNfOIaYd39HbLdIQ,1207
+pytz/zoneinfo/Asia/Choibalsan,sha256=qUkXRsTc_u7B90JxULSu7yzKbGtGfKcfEFIasGPC2ec,877
+pytz/zoneinfo/Asia/Chongqing,sha256=ZP_C5DqUQ1oEPAQNHTr36S0DGtx453N68YYbqk7u8-Y,561
+pytz/zoneinfo/Asia/Chungking,sha256=ZP_C5DqUQ1oEPAQNHTr36S0DGtx453N68YYbqk7u8-Y,561
+pytz/zoneinfo/Asia/Colombo,sha256=w52L7bgT4m5hcgRuevIPY83xytfkBmkLhnKMwp16KsY,358
+pytz/zoneinfo/Asia/Dacca,sha256=-xulJ2KVhvKp6rlZLMydpw7oXVirk-riEH-181xPE54,323
+pytz/zoneinfo/Asia/Damascus,sha256=EthGheaHWmy5IrLCc9NmM3jvASQFHt8TsBF07I1tgbg,1873
+pytz/zoneinfo/Asia/Dhaka,sha256=-xulJ2KVhvKp6rlZLMydpw7oXVirk-riEH-181xPE54,323
+pytz/zoneinfo/Asia/Dili,sha256=2A9uFmwSwoFA5o2ek1LA0ucohPnM42ghWvD9D5TdnJk,257
+pytz/zoneinfo/Asia/Dubai,sha256=pmdhPhaJRwKwONvxiZNGeFSICjlWzyY9JlFHv-H9upY,151
+pytz/zoneinfo/Asia/Dushanbe,sha256=koYnnYWuFsBXd1vJfZsGdpwnbFHEwvkGBmSrrx3KIss,577
+pytz/zoneinfo/Asia/Famagusta,sha256=CFrcygd8ude5x6OEtfM_Dw0KYHoxpPPzq46KoHVxjjc,2028
+pytz/zoneinfo/Asia/Gaza,sha256=t0YxcUQL53VNKnKbKijn0OE_MaryEynonabse-iTtzs,3844
+pytz/zoneinfo/Asia/Harbin,sha256=ZP_C5DqUQ1oEPAQNHTr36S0DGtx453N68YYbqk7u8-Y,561
+pytz/zoneinfo/Asia/Hebron,sha256=6Y0USHKx-xoCxCr_WpCuM3olP1vUGnzrcnGiyQFcqdQ,3872
+pytz/zoneinfo/Asia/Ho_Chi_Minh,sha256=Lnv1vpUNAXBo8v0b9d9AQpy-AEyO5Qa2Ig0PvDkjrmU,337
+pytz/zoneinfo/Asia/Hong_Kong,sha256=al_O4kPlq5JpgkLYjEaZzrcgiiLul9NC0R5B69JVWhc,1233
+pytz/zoneinfo/Asia/Hovd,sha256=Zn4PLGlD-URJDsbChor5bqWTzuAil2tbrGJW0j5TLbs,877
+pytz/zoneinfo/Asia/Irkutsk,sha256=IVuoXCwdeI-KIUfFkEt6yBjqYP3V9GTrF-_WLnffFzk,1229
+pytz/zoneinfo/Asia/Istanbul,sha256=Jk4wjndDta_uLWc8W1dWdjbavJJbsL5ROTmZboVnGKU,1933
+pytz/zoneinfo/Asia/Jakarta,sha256=TvEzBvSzfzFCdOsMAZ0QgR95JA5xf3kAZONhy5gEXRE,383
+pytz/zoneinfo/Asia/Jayapura,sha256=ihzUd-L8HUVqG-Na10MyPE-YYwjVFj-xerqjTN4EJZs,221
+pytz/zoneinfo/Asia/Jerusalem,sha256=JUuWQmW5Tha0pJjw61Q5aN7CX0z4D7ops9OOSnda6Dc,2388
+pytz/zoneinfo/Asia/Kabul,sha256=JZEbo8bSj_L7HnXUm2gAUlNlCvJlRJhFkSHCg5o3ggk,194
+pytz/zoneinfo/Asia/Kamchatka,sha256=KY1PlJvRSNkY_5hyJBxj5DDweeYVQaBK05ZgL3kdcCY,1152
+pytz/zoneinfo/Asia/Karachi,sha256=iB-mWMTXUyfBwAkZdz8_UmEw0xsgxIub-KNI7akzhkk,379
+pytz/zoneinfo/Asia/Kashgar,sha256=F1ZOdZZDsVHwDJinksR-hjcqPzqOljvdreZIWFulJxY,151
+pytz/zoneinfo/Asia/Kathmandu,sha256=_RsfeSWbCr8kM4YRJi7Xv6hAEiHW14IFhsXsfhbPjoM,198
+pytz/zoneinfo/Asia/Katmandu,sha256=_RsfeSWbCr8kM4YRJi7Xv6hAEiHW14IFhsXsfhbPjoM,198
+pytz/zoneinfo/Asia/Khandyga,sha256=bKfmw6k5qYDQsEHG3Mv-VYis3YhCeV7qijDxfxQNn_g,1257
+pytz/zoneinfo/Asia/Kolkata,sha256=6Qw0EDbLcgMgDik8s7UTJn4QSjmllPNeGVJU5rwKF88,285
+pytz/zoneinfo/Asia/Krasnoyarsk,sha256=D5KE_1wWSD2YdixDy8n3LBNaAlE1_y3TWXw6NrxFKKA,1193
+pytz/zoneinfo/Asia/Kuala_Lumpur,sha256=XmeVImeqcJ8hJzm7TjAti1nWJAxawOqq7jIzDnHX2hI,401
+pytz/zoneinfo/Asia/Kuching,sha256=D5qtyWJ_SM8bTQeJJIYhqqojxlVKbrFC1EYMDU9GzXQ,469
+pytz/zoneinfo/Asia/Kuwait,sha256=oCKH7uafN8R1o-ijXGoT5U1JZxwvoLzJu_2Cqyi2hUM,151
+pytz/zoneinfo/Asia/Macao,sha256=MvAkRyRsrA2r052ItlyF5bh2FheRjI0jPwg0uIiH2Yk,1227
+pytz/zoneinfo/Asia/Macau,sha256=MvAkRyRsrA2r052ItlyF5bh2FheRjI0jPwg0uIiH2Yk,1227
+pytz/zoneinfo/Asia/Magadan,sha256=HccEEXBQvMmLoC_JE-zP_MlLAZ1WmNLQLfM3tJt55M4,1208
+pytz/zoneinfo/Asia/Makassar,sha256=OhJtCqSTEU-u5n0opBVO5Bu-wQzcYPy9S_6aAhJXgOw,254
+pytz/zoneinfo/Asia/Manila,sha256=8xTSHFQuYVdW3ThdNqiWzVe6Fv75g_5rTQYURLvxrJ4,422
+pytz/zoneinfo/Asia/Muscat,sha256=pmdhPhaJRwKwONvxiZNGeFSICjlWzyY9JlFHv-H9upY,151
+pytz/zoneinfo/Asia/Nicosia,sha256=0Unm0IFT7HyGeQ7F3vTa_-klfysCgrulqFO6BD1plZU,2002
+pytz/zoneinfo/Asia/Novokuznetsk,sha256=pyxxtSUtYDeVmFk0Cg-F33laZS0iKtde9_GJnL9f0KM,1151
+pytz/zoneinfo/Asia/Novosibirsk,sha256=5K2-Gx15ThlHfolyW85S5zREtAcMjeHBYWK4E8x2LdY,1207
+pytz/zoneinfo/Asia/Omsk,sha256=HyXIWItJXBKVHUzWcQPi1Mmd6ZLmZk-QhRUo9Kv2XOI,1193
+pytz/zoneinfo/Asia/Oral,sha256=WQT4qRmC9RI_ll8zB9FvkAL8ezGb8qoqWd75GTlC7kQ,991
+pytz/zoneinfo/Asia/Phnom_Penh,sha256=hf_5PVegQcFSS60CjS80C7h-TGOrfQ4ncm83N8VmZkk,185
+pytz/zoneinfo/Asia/Pontianak,sha256=inOXwuKtjKv1z_eliPZSIqjSt6whtuxhPeG1YpjU_BQ,353
+pytz/zoneinfo/Asia/Pyongyang,sha256=_-g3GnDAtfDX4XAktXH9jFouLUDmOovnjoOfvRpUDsE,237
+pytz/zoneinfo/Asia/Qatar,sha256=wklGY3WPGp-z1OUwb_KOHzRTwBndt1RfDg9Uttt36G4,185
+pytz/zoneinfo/Asia/Qostanay,sha256=HIjln8QIPNRU6MkWzyPi6vDrjlmVZ4XzFxcUHtXMi7s,1025
+pytz/zoneinfo/Asia/Qyzylorda,sha256=JZLNN6NuLkqaWEeVaCZiW_gL6BrIFL9lr65iK7myVPg,1011
+pytz/zoneinfo/Asia/Rangoon,sha256=_YHASq4Z5YcUILIdhEzg27CGLzarUHPDHs1Dj0QgNGM,254
+pytz/zoneinfo/Asia/Riyadh,sha256=oCKH7uafN8R1o-ijXGoT5U1JZxwvoLzJu_2Cqyi2hUM,151
+pytz/zoneinfo/Asia/Saigon,sha256=Lnv1vpUNAXBo8v0b9d9AQpy-AEyO5Qa2Ig0PvDkjrmU,337
+pytz/zoneinfo/Asia/Sakhalin,sha256=xzAor82ihAe-yXEwC6OWiMzo9b6Z-oQl39NIkU5Hhbs,1188
+pytz/zoneinfo/Asia/Samarkand,sha256=zJKSRt3lEvd6Qvg9b49QAyO4cTJyVnTKyPYcyudpHxk,563
+pytz/zoneinfo/Asia/Seoul,sha256=LI9LsV3XcJC0l-KoQf8zI-y7rk-du57erS-N2Ptdi7Q,617
+pytz/zoneinfo/Asia/Shanghai,sha256=ZP_C5DqUQ1oEPAQNHTr36S0DGtx453N68YYbqk7u8-Y,561
+pytz/zoneinfo/Asia/Singapore,sha256=XmeVImeqcJ8hJzm7TjAti1nWJAxawOqq7jIzDnHX2hI,401
+pytz/zoneinfo/Asia/Srednekolymsk,sha256=efaaT8iFHrcccp-VZKNMvtTuPLNjG5V9JH5KKHhH3SI,1194
+pytz/zoneinfo/Asia/Taipei,sha256=DMmQwOpPql25ue3Nf8vAKKT4em06D1Z9rHbLIitxixk,761
+pytz/zoneinfo/Asia/Tashkent,sha256=apRPy251fSRy_ixsg3BOZNmUbHdO86P5-PdgC1Xws7U,577
+pytz/zoneinfo/Asia/Tbilisi,sha256=zQ-2bVq5_USUSbwN6q0qvWjD-HXkKaH4ifMVq1lEeIM,1021
+pytz/zoneinfo/Asia/Tehran,sha256=Lb2H9BCBXtz819FL6E3gBA7w2ROiIgPgx-f08XpqkVo,1248
+pytz/zoneinfo/Asia/Tel_Aviv,sha256=JUuWQmW5Tha0pJjw61Q5aN7CX0z4D7ops9OOSnda6Dc,2388
+pytz/zoneinfo/Asia/Thimbu,sha256=G2nTQVEMmKlWt0B74_fUAL7KQ3YAu__J6HciiYs2IyU,189
+pytz/zoneinfo/Asia/Thimphu,sha256=G2nTQVEMmKlWt0B74_fUAL7KQ3YAu__J6HciiYs2IyU,189
+pytz/zoneinfo/Asia/Tokyo,sha256=oCueZgRNxcNcX3ZGdif9y6Su4cyVhga4XHdwlcrYLOs,309
+pytz/zoneinfo/Asia/Tomsk,sha256=cr0ULZgWBnQfzDiJeYmqpA7Xo5QRzurvrHsrbZsnhOQ,1207
+pytz/zoneinfo/Asia/Ujung_Pandang,sha256=OhJtCqSTEU-u5n0opBVO5Bu-wQzcYPy9S_6aAhJXgOw,254
+pytz/zoneinfo/Asia/Ulaanbaatar,sha256=qUkXRsTc_u7B90JxULSu7yzKbGtGfKcfEFIasGPC2ec,877
+pytz/zoneinfo/Asia/Ulan_Bator,sha256=qUkXRsTc_u7B90JxULSu7yzKbGtGfKcfEFIasGPC2ec,877
+pytz/zoneinfo/Asia/Urumqi,sha256=F1ZOdZZDsVHwDJinksR-hjcqPzqOljvdreZIWFulJxY,151
+pytz/zoneinfo/Asia/Ust-Nera,sha256=zsG8kgnw0Fcs5N2WwNTVmvWkTlpwf7Oo8y68HcXjYyw,1238
+pytz/zoneinfo/Asia/Vientiane,sha256=hf_5PVegQcFSS60CjS80C7h-TGOrfQ4ncm83N8VmZkk,185
+pytz/zoneinfo/Asia/Vladivostok,sha256=XMQLMh5SPbI6C4R3UO4KhbnG4hWVkHNedzCQeqxFk6A,1194
+pytz/zoneinfo/Asia/Yakutsk,sha256=PPNrRGgg9jefOUM-6M8XqaIm-ElfmRZSWAtSGKLzNXQ,1193
+pytz/zoneinfo/Asia/Yangon,sha256=_YHASq4Z5YcUILIdhEzg27CGLzarUHPDHs1Dj0QgNGM,254
+pytz/zoneinfo/Asia/Yekaterinburg,sha256=4NyEW6Xjr4UsWPh63HIPI4G6GT_tVG1Xkgc2xbwGjzA,1229
+pytz/zoneinfo/Asia/Yerevan,sha256=FM0pUA4NbTWBb_CsJ5KCLVrLoNmad7njBKqFrJBDoxE,1137
+pytz/zoneinfo/Atlantic/Azores,sha256=66hDxaK8xFnktLMrpNxkD4r1gGkhS-PEpleuwzuGRA0,3442
+pytz/zoneinfo/Atlantic/Bermuda,sha256=LNGKfMsnYvwImjTyzXrLhMOHHDu7qI67RbYNKvvI15I,2396
+pytz/zoneinfo/Atlantic/Canary,sha256=ymK9ufqphvNjDK3hzikN4GfkcR3QeCBiPKyVc6FjlbA,1897
+pytz/zoneinfo/Atlantic/Cape_Verde,sha256=o92pLdLFX_b9vUiq3rNpca4tupIO3dx9rNrnPcA8474,256
+pytz/zoneinfo/Atlantic/Faeroe,sha256=NibdZPZtapnYR_myIZnMdTaSKGsOBGgujj0_T2NvAzs,1815
+pytz/zoneinfo/Atlantic/Faroe,sha256=NibdZPZtapnYR_myIZnMdTaSKGsOBGgujj0_T2NvAzs,1815
+pytz/zoneinfo/Atlantic/Jan_Mayen,sha256=XuR19xoPwaMvrrhJ-MOcbnqmbW1B7HQrl7OnQ2s7BwE,2298
+pytz/zoneinfo/Atlantic/Madeira,sha256=lYY85MC5-GUKExm353ixwtZDxasYavTTWELvv5RXLxE,3377
+pytz/zoneinfo/Atlantic/Reykjavik,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Atlantic/South_Georgia,sha256=I9SAcPPumy6Xf9P7dg2aE16oxwDIqyKFqinJTC-XsgM,150
+pytz/zoneinfo/Atlantic/St_Helena,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Atlantic/Stanley,sha256=siEjXTAuTum_4XGtS98MBE34XW_5xgXShEX5OMnSFjo,1200
+pytz/zoneinfo/Australia/ACT,sha256=QsOFdYWxbbL4_9R7oZ-qYPRzNA3o1P6TIOp76GFgWQY,2190
+pytz/zoneinfo/Australia/Adelaide,sha256=ld2EbxU75oVgmPe703z-I6aqLg0Kmv62ZcCGzkT5R20,2208
+pytz/zoneinfo/Australia/Brisbane,sha256=eW6Qzze2t0-speJmmvt1JMzbkSadIKdE84XHc7JUtGc,419
+pytz/zoneinfo/Australia/Broken_Hill,sha256=3k_3ljTvS5GSfo7Xh6w71UgR3aAwYPBsnCJ-mlEYCqQ,2229
+pytz/zoneinfo/Australia/Canberra,sha256=QsOFdYWxbbL4_9R7oZ-qYPRzNA3o1P6TIOp76GFgWQY,2190
+pytz/zoneinfo/Australia/Currie,sha256=GLQSzgIfsWxOvmKOrhpfofWqINQf6h36NYy3mcq6gcg,2358
+pytz/zoneinfo/Australia/Darwin,sha256=fn0IZhIW98FAnzLig-_GBtW5LA54jajdeeUzg4tCGvo,325
+pytz/zoneinfo/Australia/Eucla,sha256=i1-XGG8I6E0dXIdWGF4DlkfDLWhiAxJ_3gMpt-nm_u4,456
+pytz/zoneinfo/Australia/Hobart,sha256=GLQSzgIfsWxOvmKOrhpfofWqINQf6h36NYy3mcq6gcg,2358
+pytz/zoneinfo/Australia/LHI,sha256=oyPFQzmRqWPrSXt9pNHQmEi_PvX11k2clknziOS6ud8,1846
+pytz/zoneinfo/Australia/Lindeman,sha256=xM6Udx22oLNoLR1Y7GQhHOYov8nw3xQNqgc_NVQ2JK4,475
+pytz/zoneinfo/Australia/Lord_Howe,sha256=oyPFQzmRqWPrSXt9pNHQmEi_PvX11k2clknziOS6ud8,1846
+pytz/zoneinfo/Australia/Melbourne,sha256=lvx_MQcunMc6u2smIrl8X427bLsXvjkgpCSdjYCTNBM,2190
+pytz/zoneinfo/Australia/NSW,sha256=QsOFdYWxbbL4_9R7oZ-qYPRzNA3o1P6TIOp76GFgWQY,2190
+pytz/zoneinfo/Australia/North,sha256=fn0IZhIW98FAnzLig-_GBtW5LA54jajdeeUzg4tCGvo,325
+pytz/zoneinfo/Australia/Perth,sha256=Al1DOUh4U_ofMUQSeVlzSyD3x7SUjP9dchSaBUGmeWg,446
+pytz/zoneinfo/Australia/Queensland,sha256=eW6Qzze2t0-speJmmvt1JMzbkSadIKdE84XHc7JUtGc,419
+pytz/zoneinfo/Australia/South,sha256=ld2EbxU75oVgmPe703z-I6aqLg0Kmv62ZcCGzkT5R20,2208
+pytz/zoneinfo/Australia/Sydney,sha256=QsOFdYWxbbL4_9R7oZ-qYPRzNA3o1P6TIOp76GFgWQY,2190
+pytz/zoneinfo/Australia/Tasmania,sha256=GLQSzgIfsWxOvmKOrhpfofWqINQf6h36NYy3mcq6gcg,2358
+pytz/zoneinfo/Australia/Victoria,sha256=lvx_MQcunMc6u2smIrl8X427bLsXvjkgpCSdjYCTNBM,2190
+pytz/zoneinfo/Australia/West,sha256=Al1DOUh4U_ofMUQSeVlzSyD3x7SUjP9dchSaBUGmeWg,446
+pytz/zoneinfo/Australia/Yancowinna,sha256=3k_3ljTvS5GSfo7Xh6w71UgR3aAwYPBsnCJ-mlEYCqQ,2229
+pytz/zoneinfo/Brazil/Acre,sha256=0gpJUl46hQbp0P6Xj1S0NArIWeAryuuDXjsldvB5GHE,614
+pytz/zoneinfo/Brazil/DeNoronha,sha256=feeRAijQqKylZgqe84nKhsFLycT5zIBm7mLIvdyGw4w,702
+pytz/zoneinfo/Brazil/East,sha256=BMBnRO4_4HjvO4t3njjrMGZr-ZPmegkvyvL8KPY6ZM4,1430
+pytz/zoneinfo/Brazil/West,sha256=F6RLOOeOi9lymZiQmQ9pR8tFpPZ6EguNdPfOc6BhXDE,590
+pytz/zoneinfo/CET,sha256=gS9Vrrbozend9HhuFetCVrIegs9fXSjaG60X2UVwysA,2933
+pytz/zoneinfo/CST6CDT,sha256=_roybr6I6sIAF6cYdIxGxoRpoef153Fty48dQ6bm9oY,3592
+pytz/zoneinfo/Canada/Atlantic,sha256=TZpmc5PwWoLfTfQoQ_b3U17BE2iVKSeNkR0Ho8mbTn8,3424
+pytz/zoneinfo/Canada/Central,sha256=7P-_YQrneFcon7QKSTOnkiGjEppFDn3Z48MJ1qq8VBw,2868
+pytz/zoneinfo/Canada/Eastern,sha256=pYehoWB0Ofe6woPhgV8r26-5ZJpFPRjgbC5E5pltiI8,3494
+pytz/zoneinfo/Canada/Mountain,sha256=-TkIfc3QlvaCf0p8COZ43Y1HRBAl-nARUi-JdXeK1vE,2332
+pytz/zoneinfo/Canada/Newfoundland,sha256=r1-17uKv27eZ3JsVkw_DLZQbo6wvjuuVu7C2pDsmOgI,3655
+pytz/zoneinfo/Canada/Pacific,sha256=sknKH0jSPWam-DHfM35qXs8Nam7d5TFlkUI9Sgxryyg,2892
+pytz/zoneinfo/Canada/Saskatchewan,sha256=yjqT08pHbICYe83H8JmtaDBvCFqRv7Tfze3Y8xuXukw,980
+pytz/zoneinfo/Canada/Yukon,sha256=TrR6PCnYG-mSClBMohqlP8qnYhXMUsydI-L-quXFxyM,1614
+pytz/zoneinfo/Chile/Continental,sha256=0CDw13dCMUsoquMupoJgupkzAUNhDK6E0lVxURA7osA,2515
+pytz/zoneinfo/Chile/EasterIsland,sha256=QbubBs_xQlvKweAnurhyHjIK4ji77Gh4G-usXul6XVM,2219
+pytz/zoneinfo/Cuba,sha256=HUQeAuKBsEkI5SLZjqynXICOUVOajkKzKH5r-Ov5Odc,2416
+pytz/zoneinfo/EET,sha256=XDY-FBUddRyQHN8GxQLZ4awjuOlWlzlUdjv7OdXFNzA,2262
+pytz/zoneinfo/EST,sha256=kayA_pdpMcSQ0FjIzotdcf-m1JYfbKE-qcFT8LC8zqA,182
+pytz/zoneinfo/EST5EDT,sha256=6e0H177gx2qdRC0JHvHwFmj-58TyYBTAqGixn-bBipU,3552
+pytz/zoneinfo/Egypt,sha256=Lft-GCLQhaSJm9VqUmsEFoHIS1Vhfa7pFJn9GZCpifs,2399
+pytz/zoneinfo/Eire,sha256=QOjSocO1cihNo59vQkWxvIFPRSxE9apz0KARVx1czEM,3492
+pytz/zoneinfo/Etc/GMT,sha256=bZ83iIPAefhsA4elVHqSxEmGnYBuB94QCEqwTwJJAY0,114
+pytz/zoneinfo/Etc/GMT+0,sha256=bZ83iIPAefhsA4elVHqSxEmGnYBuB94QCEqwTwJJAY0,114
+pytz/zoneinfo/Etc/GMT+1,sha256=1Qzl2X9rQ_RXEf11yH09wQZCr_ph6UdFP7E0yu9s-IQ,116
+pytz/zoneinfo/Etc/GMT+10,sha256=JEQyQyQlkC0o6ZTdeVjZhCIOh6cK5TF7H00Pkls-sUI,117
+pytz/zoneinfo/Etc/GMT+11,sha256=tWvcvYMFCaE60nJVvDrrov7stJvs1KQYOyrhl3dzcUs,117
+pytz/zoneinfo/Etc/GMT+12,sha256=b70HEhErq8IJmq8x7cOZy4eR__3fq5uHHpjvPBEHqMA,117
+pytz/zoneinfo/Etc/GMT+2,sha256=T6Ep5zhslBKbYaECFUB6gUKh3iTZPyMoW1kjhonxrUo,116
+pytz/zoneinfo/Etc/GMT+3,sha256=QGoYrE04bUJ-OzL37dt2MZT5FxWNLpJDPVXgJbstYZA,116
+pytz/zoneinfo/Etc/GMT+4,sha256=RWrkNki-wV7X-coe0VvufBe6LrWVpkPJgia5QQYEnBo,116
+pytz/zoneinfo/Etc/GMT+5,sha256=oRmeC41dgYXT-zzyZIRKXN9IvdL2Da5nTuwmG2_prIA,116
+pytz/zoneinfo/Etc/GMT+6,sha256=d6dAnwiejyFI2n7AzFlFW0aFAT6zYNEjBIEG0uu0sbQ,116
+pytz/zoneinfo/Etc/GMT+7,sha256=TqjYbzd0YHpx1wisFg08J19wTpg6ztJLLongZY_lozs,116
+pytz/zoneinfo/Etc/GMT+8,sha256=th_8bIMmYgRPCesBrbmBhRr0jQO7whd70LiY9HfwJyk,116
+pytz/zoneinfo/Etc/GMT+9,sha256=Qq5E6iUS7JMJIymT7YoqlI8MtqtVy0mr9t6zWFtWc9Y,116
+pytz/zoneinfo/Etc/GMT-0,sha256=bZ83iIPAefhsA4elVHqSxEmGnYBuB94QCEqwTwJJAY0,114
+pytz/zoneinfo/Etc/GMT-1,sha256=73F1eU8uAQGP3mcoB2q99CjfManGFHk3fefljp9pYC4,117
+pytz/zoneinfo/Etc/GMT-10,sha256=fKWWNwLBOp1OkKjtc1w9LIXJR1mTTD-JdvYflRy1IrU,118
+pytz/zoneinfo/Etc/GMT-11,sha256=D2S79n6psa9t9_2vj5wIrFpHH2OJLcCKP6vtwzFZINY,118
+pytz/zoneinfo/Etc/GMT-12,sha256=me4V6lmWI8gSr8H7N41WAD0Eww1anh_EF34Qr9UoSnI,118
+pytz/zoneinfo/Etc/GMT-13,sha256=xbmbG1BQA6Dlpa_iUwEGyJxW4a3t6lmawdPKAE8vbR8,118
+pytz/zoneinfo/Etc/GMT-14,sha256=PpXoREBh02qFpvxVMj2pV9IAzSQvBE7XPvnN9qSZ-Kc,118
+pytz/zoneinfo/Etc/GMT-2,sha256=ve6hWLdeuiLhqagaWLqMD6HNybS1chRwjudfTZ2bYBE,117
+pytz/zoneinfo/Etc/GMT-3,sha256=N77jILanuLDVkLsdujXZSu-dsHiwN5MIpwh7fMUifso,117
+pytz/zoneinfo/Etc/GMT-4,sha256=LSko5fVHqPl5zfwjGqkbMa_OFnvtpT6o_4xYxNz9n5o,117
+pytz/zoneinfo/Etc/GMT-5,sha256=uLaSR5Mb18HRTsAA5SveY9PAJ97dO8QzIWqNXe3wZb4,117
+pytz/zoneinfo/Etc/GMT-6,sha256=JSN-RUAphJ50fpIv7cYC6unrtrz9S1Wma-piDHlGe7c,117
+pytz/zoneinfo/Etc/GMT-7,sha256=vVAOF8xU9T9ESnw68c0SFXpcvkoopaiwTR0zbefHHSU,117
+pytz/zoneinfo/Etc/GMT-8,sha256=S7xFQbFMpiDZy4v5L4D9fCrjRIzzoLC5p8Se23xi7us,117
+pytz/zoneinfo/Etc/GMT-9,sha256=I5vHNmUK-Yyg_S1skFN44VGVzBgktjFgVQiDIKO4aMI,117
+pytz/zoneinfo/Etc/GMT0,sha256=bZ83iIPAefhsA4elVHqSxEmGnYBuB94QCEqwTwJJAY0,114
+pytz/zoneinfo/Etc/Greenwich,sha256=bZ83iIPAefhsA4elVHqSxEmGnYBuB94QCEqwTwJJAY0,114
+pytz/zoneinfo/Etc/UCT,sha256=i4WEZ5GrLIpUY8g6W-PAQ-JXDXRIQ01BOYlp7Ufj5vI,114
+pytz/zoneinfo/Etc/UTC,sha256=i4WEZ5GrLIpUY8g6W-PAQ-JXDXRIQ01BOYlp7Ufj5vI,114
+pytz/zoneinfo/Etc/Universal,sha256=i4WEZ5GrLIpUY8g6W-PAQ-JXDXRIQ01BOYlp7Ufj5vI,114
+pytz/zoneinfo/Etc/Zulu,sha256=i4WEZ5GrLIpUY8g6W-PAQ-JXDXRIQ01BOYlp7Ufj5vI,114
+pytz/zoneinfo/Europe/Amsterdam,sha256=gS9Vrrbozend9HhuFetCVrIegs9fXSjaG60X2UVwysA,2933
+pytz/zoneinfo/Europe/Andorra,sha256=gTB5jCQmvIw3JJi1_vAcOYuhtzPBR6RXUx9gVV6p6ug,1742
+pytz/zoneinfo/Europe/Astrakhan,sha256=ZeGDZjwVVRoeR-J642zEnN26BPL58ViTJLbwnk7pLXk,1151
+pytz/zoneinfo/Europe/Athens,sha256=XDY-FBUddRyQHN8GxQLZ4awjuOlWlzlUdjv7OdXFNzA,2262
+pytz/zoneinfo/Europe/Belfast,sha256=yFSVBw3KQmh99qHD7ngKJ8vLgvGER1Dqb2QoM6RNKbQ,3664
+pytz/zoneinfo/Europe/Belgrade,sha256=OpWtsGFWBE_S-mYoQcAmjCta9HwbGQANnSmVY9OHCTo,1920
+pytz/zoneinfo/Europe/Berlin,sha256=XuR19xoPwaMvrrhJ-MOcbnqmbW1B7HQrl7OnQ2s7BwE,2298
+pytz/zoneinfo/Europe/Bratislava,sha256=G9fdhUXmzx651BnyZ6V7AOYIV9EV5aMJMm44eJaLLZw,2301
+pytz/zoneinfo/Europe/Brussels,sha256=gS9Vrrbozend9HhuFetCVrIegs9fXSjaG60X2UVwysA,2933
+pytz/zoneinfo/Europe/Bucharest,sha256=nfg6-bU2D6DMEWb9EMIBR5kxnNsbDSx0UKfHH_ZzqFc,2184
+pytz/zoneinfo/Europe/Budapest,sha256=lNwqxWciBvw9ei81VQwIKHbC_ZDJjpgHU6HFg4wCUkY,2368
+pytz/zoneinfo/Europe/Busingen,sha256=K5QY7Ujj2VUchKR4bhhb0hgdAJhmwED71ykXDQOGKe8,1909
+pytz/zoneinfo/Europe/Chisinau,sha256=p1J_rqFE13pL8cpBRrEFe-teCI8f0fKK4uTUy_4diF4,2390
+pytz/zoneinfo/Europe/Copenhagen,sha256=XuR19xoPwaMvrrhJ-MOcbnqmbW1B7HQrl7OnQ2s7BwE,2298
+pytz/zoneinfo/Europe/Dublin,sha256=QOjSocO1cihNo59vQkWxvIFPRSxE9apz0KARVx1czEM,3492
+pytz/zoneinfo/Europe/Gibraltar,sha256=a87WpaBlvxI4gAU9OpQOkN8VUJbirVWYf-VfFLTIoS4,3068
+pytz/zoneinfo/Europe/Guernsey,sha256=yFSVBw3KQmh99qHD7ngKJ8vLgvGER1Dqb2QoM6RNKbQ,3664
+pytz/zoneinfo/Europe/Helsinki,sha256=GEkB7LsVhmegt7YuuWheCDvDGC7b7Nw9bTdDGS9qkJc,1900
+pytz/zoneinfo/Europe/Isle_of_Man,sha256=yFSVBw3KQmh99qHD7ngKJ8vLgvGER1Dqb2QoM6RNKbQ,3664
+pytz/zoneinfo/Europe/Istanbul,sha256=Jk4wjndDta_uLWc8W1dWdjbavJJbsL5ROTmZboVnGKU,1933
+pytz/zoneinfo/Europe/Jersey,sha256=yFSVBw3KQmh99qHD7ngKJ8vLgvGER1Dqb2QoM6RNKbQ,3664
+pytz/zoneinfo/Europe/Kaliningrad,sha256=s7GXSe1YvMcs7AiUhHNTA6I4nAOQn_Kmz_ZqJYO-LMM,1493
+pytz/zoneinfo/Europe/Kiev,sha256=-wrpG9jPuIKFP1NgBVvnxsMRf9L_h5z3J6Q3jj1AwNM,2120
+pytz/zoneinfo/Europe/Kirov,sha256=P7T2Zf5Eo6o4L4Dbg_BfiFjUgTj0dQXlrwY-QZ1eBVk,1185
+pytz/zoneinfo/Europe/Kyiv,sha256=-wrpG9jPuIKFP1NgBVvnxsMRf9L_h5z3J6Q3jj1AwNM,2120
+pytz/zoneinfo/Europe/Lisbon,sha256=krB8skaJImv5NDCNHxvTPDBqpNphDFLNW84lB3lgUCw,3527
+pytz/zoneinfo/Europe/Ljubljana,sha256=OpWtsGFWBE_S-mYoQcAmjCta9HwbGQANnSmVY9OHCTo,1920
+pytz/zoneinfo/Europe/London,sha256=yFSVBw3KQmh99qHD7ngKJ8vLgvGER1Dqb2QoM6RNKbQ,3664
+pytz/zoneinfo/Europe/Luxembourg,sha256=gS9Vrrbozend9HhuFetCVrIegs9fXSjaG60X2UVwysA,2933
+pytz/zoneinfo/Europe/Madrid,sha256=mkLX03rW3t0tmzKBIPe_noUvaFDErwC6_5ZPZZsWHOo,2614
+pytz/zoneinfo/Europe/Malta,sha256=EhKcbPL47765tWAiQ57cusaK2TaIQqZCgtJoEZs3Ud0,2620
+pytz/zoneinfo/Europe/Mariehamn,sha256=GEkB7LsVhmegt7YuuWheCDvDGC7b7Nw9bTdDGS9qkJc,1900
+pytz/zoneinfo/Europe/Minsk,sha256=KgPm0fHycntgd3xbTmmDl4O13Xh_9e2zUnd8XFSU29o,1307
+pytz/zoneinfo/Europe/Monaco,sha256=q3ehSIot1GZ6TyMHIjbg0oRf4ghAXuwbSDSYVim6evg,2962
+pytz/zoneinfo/Europe/Moscow,sha256=KmkofRcj6T8Ph28PJChm8JVp13uRvef6TZ0GuPzUiDw,1535
+pytz/zoneinfo/Europe/Nicosia,sha256=0Unm0IFT7HyGeQ7F3vTa_-klfysCgrulqFO6BD1plZU,2002
+pytz/zoneinfo/Europe/Oslo,sha256=XuR19xoPwaMvrrhJ-MOcbnqmbW1B7HQrl7OnQ2s7BwE,2298
+pytz/zoneinfo/Europe/Paris,sha256=q3ehSIot1GZ6TyMHIjbg0oRf4ghAXuwbSDSYVim6evg,2962
+pytz/zoneinfo/Europe/Podgorica,sha256=OpWtsGFWBE_S-mYoQcAmjCta9HwbGQANnSmVY9OHCTo,1920
+pytz/zoneinfo/Europe/Prague,sha256=G9fdhUXmzx651BnyZ6V7AOYIV9EV5aMJMm44eJaLLZw,2301
+pytz/zoneinfo/Europe/Riga,sha256=hJ2_0m1taW9IuA-hMyP5n-WX7YOrR0heKszJhgljRWk,2198
+pytz/zoneinfo/Europe/Rome,sha256=1a3oLMSiMpSbh9QxV8hLLDVbZqash89iUO1urYC1AY8,2641
+pytz/zoneinfo/Europe/Samara,sha256=nXL0IxbT6qu10CNuaDHxx4W1OaAnaaKTtIJ9N9URMoU,1201
+pytz/zoneinfo/Europe/San_Marino,sha256=1a3oLMSiMpSbh9QxV8hLLDVbZqash89iUO1urYC1AY8,2641
+pytz/zoneinfo/Europe/Sarajevo,sha256=OpWtsGFWBE_S-mYoQcAmjCta9HwbGQANnSmVY9OHCTo,1920
+pytz/zoneinfo/Europe/Saratov,sha256=ygwjvXN13TgaWxjg6ysWEnHWNxwrVtkEbrk8t9bzVVw,1169
+pytz/zoneinfo/Europe/Simferopol,sha256=tzl7xdNVSZprNCul4YE5LSpoR9JoujmOq8VbbB8wHic,1469
+pytz/zoneinfo/Europe/Skopje,sha256=OpWtsGFWBE_S-mYoQcAmjCta9HwbGQANnSmVY9OHCTo,1920
+pytz/zoneinfo/Europe/Sofia,sha256=hCQKXfMNrnA5xHNw_uzTjKzVw4-Bvsq5oGO4yUCv5tY,2077
+pytz/zoneinfo/Europe/Stockholm,sha256=XuR19xoPwaMvrrhJ-MOcbnqmbW1B7HQrl7OnQ2s7BwE,2298
+pytz/zoneinfo/Europe/Tallinn,sha256=4a6JC0aIpMzqIV7O35zoG0LLJwkQq5AoXZ2ivkic6-w,2148
+pytz/zoneinfo/Europe/Tirane,sha256=ztlZyCS9WCXeVW8nBun3Tyi5HUY0EtFbiBbEc1gucuw,2084
+pytz/zoneinfo/Europe/Tiraspol,sha256=p1J_rqFE13pL8cpBRrEFe-teCI8f0fKK4uTUy_4diF4,2390
+pytz/zoneinfo/Europe/Ulyanovsk,sha256=c8Ad5p7CKj_1cCA7lVRpcPqbQXGYaX83cuu6uIFx-Bg,1253
+pytz/zoneinfo/Europe/Uzhgorod,sha256=-wrpG9jPuIKFP1NgBVvnxsMRf9L_h5z3J6Q3jj1AwNM,2120
+pytz/zoneinfo/Europe/Vaduz,sha256=K5QY7Ujj2VUchKR4bhhb0hgdAJhmwED71ykXDQOGKe8,1909
+pytz/zoneinfo/Europe/Vatican,sha256=1a3oLMSiMpSbh9QxV8hLLDVbZqash89iUO1urYC1AY8,2641
+pytz/zoneinfo/Europe/Vienna,sha256=ZmI3kADE6bnrJEccqh73XXBY36L1G4DkpiTQImtNrUk,2200
+pytz/zoneinfo/Europe/Vilnius,sha256=UFzRX3orCTB8d9IzlxJPy5eUA2oBPuCu1UJl-2D7C3U,2162
+pytz/zoneinfo/Europe/Volgograd,sha256=RgFvt7mzZ-TtIKL9BVHmoNZLIeLIuiDdXeY10g2_vks,1193
+pytz/zoneinfo/Europe/Warsaw,sha256=TiLDPbeVF0ckgLVEkaSeDaKZ8wctdJDOl_HE_Wd5rKs,2654
+pytz/zoneinfo/Europe/Zagreb,sha256=OpWtsGFWBE_S-mYoQcAmjCta9HwbGQANnSmVY9OHCTo,1920
+pytz/zoneinfo/Europe/Zaporozhye,sha256=-wrpG9jPuIKFP1NgBVvnxsMRf9L_h5z3J6Q3jj1AwNM,2120
+pytz/zoneinfo/Europe/Zurich,sha256=K5QY7Ujj2VUchKR4bhhb0hgdAJhmwED71ykXDQOGKe8,1909
+pytz/zoneinfo/Factory,sha256=aFFlKx93HXoJoF4SSuTlD8cZtJA-ne5oKzAa6eX2V4k,116
+pytz/zoneinfo/GB,sha256=yFSVBw3KQmh99qHD7ngKJ8vLgvGER1Dqb2QoM6RNKbQ,3664
+pytz/zoneinfo/GB-Eire,sha256=yFSVBw3KQmh99qHD7ngKJ8vLgvGER1Dqb2QoM6RNKbQ,3664
+pytz/zoneinfo/GMT,sha256=bZ83iIPAefhsA4elVHqSxEmGnYBuB94QCEqwTwJJAY0,114
+pytz/zoneinfo/GMT+0,sha256=bZ83iIPAefhsA4elVHqSxEmGnYBuB94QCEqwTwJJAY0,114
+pytz/zoneinfo/GMT-0,sha256=bZ83iIPAefhsA4elVHqSxEmGnYBuB94QCEqwTwJJAY0,114
+pytz/zoneinfo/GMT0,sha256=bZ83iIPAefhsA4elVHqSxEmGnYBuB94QCEqwTwJJAY0,114
+pytz/zoneinfo/Greenwich,sha256=bZ83iIPAefhsA4elVHqSxEmGnYBuB94QCEqwTwJJAY0,114
+pytz/zoneinfo/HST,sha256=fwPRv1Jk56sCOi75uZfd_Iy2k2aSQHx3B2K5xUlSPzM,329
+pytz/zoneinfo/Hongkong,sha256=al_O4kPlq5JpgkLYjEaZzrcgiiLul9NC0R5B69JVWhc,1233
+pytz/zoneinfo/Iceland,sha256=0u-sTl8j2IyV1ywdtCgHFw9S9D3ZiiBa9akqkbny2Zc,148
+pytz/zoneinfo/Indian/Antananarivo,sha256=yJsuJTqJJqbOz37_NOS_zbf-JNr_IthHGMMN7sDqSWg,265
+pytz/zoneinfo/Indian/Chagos,sha256=2errXzKdFIcpU0L-XRhSHxhNabIzbI5lXV3Pq6lt40Y,185
+pytz/zoneinfo/Indian/Christmas,sha256=hf_5PVegQcFSS60CjS80C7h-TGOrfQ4ncm83N8VmZkk,185
+pytz/zoneinfo/Indian/Cocos,sha256=_YHASq4Z5YcUILIdhEzg27CGLzarUHPDHs1Dj0QgNGM,254
+pytz/zoneinfo/Indian/Comoro,sha256=yJsuJTqJJqbOz37_NOS_zbf-JNr_IthHGMMN7sDqSWg,265
+pytz/zoneinfo/Indian/Kerguelen,sha256=F73ffVfBoUoHre0-DwsiQrYJcLpPOW-JJGk3n88lM5U,185
+pytz/zoneinfo/Indian/Mahe,sha256=pmdhPhaJRwKwONvxiZNGeFSICjlWzyY9JlFHv-H9upY,151
+pytz/zoneinfo/Indian/Maldives,sha256=F73ffVfBoUoHre0-DwsiQrYJcLpPOW-JJGk3n88lM5U,185
+pytz/zoneinfo/Indian/Mauritius,sha256=Znqrc1chimlciJsYBOl0NvIHnrNdCxncGxWczq1PBeI,227
+pytz/zoneinfo/Indian/Mayotte,sha256=yJsuJTqJJqbOz37_NOS_zbf-JNr_IthHGMMN7sDqSWg,265
+pytz/zoneinfo/Indian/Reunion,sha256=pmdhPhaJRwKwONvxiZNGeFSICjlWzyY9JlFHv-H9upY,151
+pytz/zoneinfo/Iran,sha256=Lb2H9BCBXtz819FL6E3gBA7w2ROiIgPgx-f08XpqkVo,1248
+pytz/zoneinfo/Israel,sha256=JUuWQmW5Tha0pJjw61Q5aN7CX0z4D7ops9OOSnda6Dc,2388
+pytz/zoneinfo/Jamaica,sha256=wlagieUPRf5-beie-h7QsONbNzjGsm8vMs8uf28pw28,482
+pytz/zoneinfo/Japan,sha256=oCueZgRNxcNcX3ZGdif9y6Su4cyVhga4XHdwlcrYLOs,309
+pytz/zoneinfo/Kwajalein,sha256=TmZ_0f-ySQ-saBAlRXV0f49Itwne51VBXn6rWcrWqHQ,302
+pytz/zoneinfo/Libya,sha256=W1dptGD70T7ppGoo0fczFQeDiIp0nultLNPV66MwB2c,625
+pytz/zoneinfo/MET,sha256=gS9Vrrbozend9HhuFetCVrIegs9fXSjaG60X2UVwysA,2933
+pytz/zoneinfo/MST,sha256=illz0sYuLL8lIPK0Tkou6dL0Vck_D0W_3rRTOvFYRmQ,360
+pytz/zoneinfo/MST7MDT,sha256=MugZwApDs8NI9TnXANQlUE8guNBowWQY0m-ptpPndck,2460
+pytz/zoneinfo/Mexico/BajaNorte,sha256=SluV7xzZm24LgMXSUVt1cD1AlE7y_bdE65HhDIdXLcs,2458
+pytz/zoneinfo/Mexico/BajaSur,sha256=BWH2NqVPA1PsyELPN_2BF8KllrsmQkqg1eujsQvnnx8,1060
+pytz/zoneinfo/Mexico/General,sha256=Uog2-FMWz2o12jR6sK9vemJamLeo6OEFMQR3s0xTxkc,1222
+pytz/zoneinfo/NZ,sha256=gADjoyPo_QISQU6UJrAgcHp3HDaMoOFRdH-d23uBSyc,2437
+pytz/zoneinfo/NZ-CHAT,sha256=xhexVc5lfJ_qAv2d3HrII6lfRSxKZYBAjY2zpYkCGE8,2054
+pytz/zoneinfo/Navajo,sha256=MugZwApDs8NI9TnXANQlUE8guNBowWQY0m-ptpPndck,2460
+pytz/zoneinfo/PRC,sha256=ZP_C5DqUQ1oEPAQNHTr36S0DGtx453N68YYbqk7u8-Y,561
+pytz/zoneinfo/PST8PDT,sha256=aJd7ua1tGG_vxser02AQpm4wAI3LLTdgh6QcSYYecmg,2852
+pytz/zoneinfo/Pacific/Apia,sha256=M3QKsp75Q7H1X3aeE_9ZqQli9aEkNCCQctZQ5sEKu00,598
+pytz/zoneinfo/Pacific/Auckland,sha256=gADjoyPo_QISQU6UJrAgcHp3HDaMoOFRdH-d23uBSyc,2437
+pytz/zoneinfo/Pacific/Bougainville,sha256=hWE86eXnNx-vABbp7-YSIqWyecHPMIWLftVloAoPhL8,254
+pytz/zoneinfo/Pacific/Chatham,sha256=xhexVc5lfJ_qAv2d3HrII6lfRSxKZYBAjY2zpYkCGE8,2054
+pytz/zoneinfo/Pacific/Chuuk,sha256=nB36HBWZTdh3TlP0DLFNz1KRQ0aHIfHbp7LC4Urp9fA,172
+pytz/zoneinfo/Pacific/Easter,sha256=QbubBs_xQlvKweAnurhyHjIK4ji77Gh4G-usXul6XVM,2219
+pytz/zoneinfo/Pacific/Efate,sha256=oSxNcQYx5-1FU2_yHzHI-hT-dMJcPxzy4XmdI1UxXAo,524
+pytz/zoneinfo/Pacific/Enderbury,sha256=HNTAKrsH_R2W3QRlKcmNld5KcXdP0ygXCjEovc1i-6Q,220
+pytz/zoneinfo/Pacific/Fakaofo,sha256=qOodpTMKjztvZIXVLe_f_kZ6WcHl9fCLE9ZsyvdFKLI,186
+pytz/zoneinfo/Pacific/Fiji,sha256=jB5FbOsCnHVQQ2ohPiWEQUPhG6JybB3Nog3qT6WJQ0I,564
+pytz/zoneinfo/Pacific/Funafuti,sha256=UyaKimsR8LjgL8Z2g65I0HTvr3tMZuA2wUeBB6_Zp9c,152
+pytz/zoneinfo/Pacific/Galapagos,sha256=_GJUYOjSiIjoNBO2qdq23isLMJ4NCVk3DKIRGeDc8BA,224
+pytz/zoneinfo/Pacific/Gambier,sha256=gAS7gr1HH_re0uYnL6eWo5KGJ-B5QaiM8mV2cY5mQxE,150
+pytz/zoneinfo/Pacific/Guadalcanal,sha256=M4kTWqaSQaV1AMhyLSvmwoBJF7X9icrILbvQJwp940g,152
+pytz/zoneinfo/Pacific/Guam,sha256=Ex9znmf6rNfGze6gNpZJCMr1TT4rkl2SnrhecrdJufI,494
+pytz/zoneinfo/Pacific/Honolulu,sha256=fwPRv1Jk56sCOi75uZfd_Iy2k2aSQHx3B2K5xUlSPzM,329
+pytz/zoneinfo/Pacific/Johnston,sha256=fwPRv1Jk56sCOi75uZfd_Iy2k2aSQHx3B2K5xUlSPzM,329
+pytz/zoneinfo/Pacific/Kanton,sha256=HNTAKrsH_R2W3QRlKcmNld5KcXdP0ygXCjEovc1i-6Q,220
+pytz/zoneinfo/Pacific/Kiritimati,sha256=hYk1Ooz-Lj1PuZCbNV2WJIvOLtCwSwq2u63cb1Z-3NQ,224
+pytz/zoneinfo/Pacific/Kosrae,sha256=Q0jrb4zeDrd61bU4V8TqjMc0Iep8rWZyZqJ0uqsunxs,337
+pytz/zoneinfo/Pacific/Kwajalein,sha256=TmZ_0f-ySQ-saBAlRXV0f49Itwne51VBXn6rWcrWqHQ,302
+pytz/zoneinfo/Pacific/Majuro,sha256=UyaKimsR8LjgL8Z2g65I0HTvr3tMZuA2wUeBB6_Zp9c,152
+pytz/zoneinfo/Pacific/Marquesas,sha256=FTxPJTWtk48LVb3N2U64KLpLsmvu0DQBubTCg-dvyGM,159
+pytz/zoneinfo/Pacific/Midway,sha256=fCYrYphYY6rUfxOw712y5cyRe104AC3pouqD3bCINFg,175
+pytz/zoneinfo/Pacific/Nauru,sha256=9ASKgLHB-8nsTEK1ApzfTH0yQtbNAmGX-JI7uHZiqnA,238
+pytz/zoneinfo/Pacific/Niue,sha256=OllXxukncR7a-SMmdFox5az1xpIPMhbahQhtObmpuDM,189
+pytz/zoneinfo/Pacific/Norfolk,sha256=DMdX1Bm18lzNuiCWzwfeHUMRGXPS8v5AWnh-_EX_AZw,866
+pytz/zoneinfo/Pacific/Noumea,sha256=tkHxxnxsXTOqz3YzWi0mkhTCIONzg-W7EpSRMdPjKdQ,290
+pytz/zoneinfo/Pacific/Pago_Pago,sha256=fCYrYphYY6rUfxOw712y5cyRe104AC3pouqD3bCINFg,175
+pytz/zoneinfo/Pacific/Palau,sha256=aN2HbT0reqwKrtLKDK9M2zb0d0ikdNlTrrntVxdH66o,166
+pytz/zoneinfo/Pacific/Pitcairn,sha256=U4jAUuvsRNoy8XrPa16YpcXCcqHJY0u6JvCNgPEWO1c,188
+pytz/zoneinfo/Pacific/Pohnpei,sha256=M4kTWqaSQaV1AMhyLSvmwoBJF7X9icrILbvQJwp940g,152
+pytz/zoneinfo/Pacific/Ponape,sha256=M4kTWqaSQaV1AMhyLSvmwoBJF7X9icrILbvQJwp940g,152
+pytz/zoneinfo/Pacific/Port_Moresby,sha256=nB36HBWZTdh3TlP0DLFNz1KRQ0aHIfHbp7LC4Urp9fA,172
+pytz/zoneinfo/Pacific/Rarotonga,sha256=wPEsoXbyDnuhfzkgLvUqhSzrMx_FD42uAPluSPMh3Bc,589
+pytz/zoneinfo/Pacific/Saipan,sha256=Ex9znmf6rNfGze6gNpZJCMr1TT4rkl2SnrhecrdJufI,494
+pytz/zoneinfo/Pacific/Samoa,sha256=fCYrYphYY6rUfxOw712y5cyRe104AC3pouqD3bCINFg,175
+pytz/zoneinfo/Pacific/Tahiti,sha256=BRff9G3E-iWKhOWR1Wu02Z0iMgjrwDXV-XNrqItXdTY,151
+pytz/zoneinfo/Pacific/Tarawa,sha256=UyaKimsR8LjgL8Z2g65I0HTvr3tMZuA2wUeBB6_Zp9c,152
+pytz/zoneinfo/Pacific/Tongatapu,sha256=OppBZqTAZib9HY7U9AC-JavO7m6NxPGUtUfPQAl9oBY,358
+pytz/zoneinfo/Pacific/Truk,sha256=nB36HBWZTdh3TlP0DLFNz1KRQ0aHIfHbp7LC4Urp9fA,172
+pytz/zoneinfo/Pacific/Wake,sha256=UyaKimsR8LjgL8Z2g65I0HTvr3tMZuA2wUeBB6_Zp9c,152
+pytz/zoneinfo/Pacific/Wallis,sha256=UyaKimsR8LjgL8Z2g65I0HTvr3tMZuA2wUeBB6_Zp9c,152
+pytz/zoneinfo/Pacific/Yap,sha256=nB36HBWZTdh3TlP0DLFNz1KRQ0aHIfHbp7LC4Urp9fA,172
+pytz/zoneinfo/Poland,sha256=TiLDPbeVF0ckgLVEkaSeDaKZ8wctdJDOl_HE_Wd5rKs,2654
+pytz/zoneinfo/Portugal,sha256=krB8skaJImv5NDCNHxvTPDBqpNphDFLNW84lB3lgUCw,3527
+pytz/zoneinfo/ROC,sha256=DMmQwOpPql25ue3Nf8vAKKT4em06D1Z9rHbLIitxixk,761
+pytz/zoneinfo/ROK,sha256=LI9LsV3XcJC0l-KoQf8zI-y7rk-du57erS-N2Ptdi7Q,617
+pytz/zoneinfo/Singapore,sha256=XmeVImeqcJ8hJzm7TjAti1nWJAxawOqq7jIzDnHX2hI,401
+pytz/zoneinfo/Turkey,sha256=Jk4wjndDta_uLWc8W1dWdjbavJJbsL5ROTmZboVnGKU,1933
+pytz/zoneinfo/UCT,sha256=i4WEZ5GrLIpUY8g6W-PAQ-JXDXRIQ01BOYlp7Ufj5vI,114
+pytz/zoneinfo/US/Alaska,sha256=oZA1NSPS2BWdymYpnCHFO8BlYVS-ll5KLg2Ez9CbETs,2371
+pytz/zoneinfo/US/Aleutian,sha256=IB1DhwJQAKbhPJ9jHLf8zW5Dad7HIkBS-dhv64E1OlM,2356
+pytz/zoneinfo/US/Arizona,sha256=illz0sYuLL8lIPK0Tkou6dL0Vck_D0W_3rRTOvFYRmQ,360
+pytz/zoneinfo/US/Central,sha256=_roybr6I6sIAF6cYdIxGxoRpoef153Fty48dQ6bm9oY,3592
+pytz/zoneinfo/US/East-Indiana,sha256=kNKy9Kj9ICsiYYfCCbAggzMA7exf-GpGPMxoXocHUyw,1682
+pytz/zoneinfo/US/Eastern,sha256=6e0H177gx2qdRC0JHvHwFmj-58TyYBTAqGixn-bBipU,3552
+pytz/zoneinfo/US/Hawaii,sha256=fwPRv1Jk56sCOi75uZfd_Iy2k2aSQHx3B2K5xUlSPzM,329
+pytz/zoneinfo/US/Indiana-Starke,sha256=CsvZ5BKw2qVav3x_F8CU9taJdDk7jX41Cfsqms6jXV8,2444
+pytz/zoneinfo/US/Michigan,sha256=hecz8yqY2Cj5B61G3gLZdAVZvRgK9l0P90c_gN-uD5g,2230
+pytz/zoneinfo/US/Mountain,sha256=MugZwApDs8NI9TnXANQlUE8guNBowWQY0m-ptpPndck,2460
+pytz/zoneinfo/US/Pacific,sha256=aJd7ua1tGG_vxser02AQpm4wAI3LLTdgh6QcSYYecmg,2852
+pytz/zoneinfo/US/Samoa,sha256=fCYrYphYY6rUfxOw712y5cyRe104AC3pouqD3bCINFg,175
+pytz/zoneinfo/UTC,sha256=i4WEZ5GrLIpUY8g6W-PAQ-JXDXRIQ01BOYlp7Ufj5vI,114
+pytz/zoneinfo/Universal,sha256=i4WEZ5GrLIpUY8g6W-PAQ-JXDXRIQ01BOYlp7Ufj5vI,114
+pytz/zoneinfo/W-SU,sha256=KmkofRcj6T8Ph28PJChm8JVp13uRvef6TZ0GuPzUiDw,1535
+pytz/zoneinfo/WET,sha256=krB8skaJImv5NDCNHxvTPDBqpNphDFLNW84lB3lgUCw,3527
+pytz/zoneinfo/Zulu,sha256=i4WEZ5GrLIpUY8g6W-PAQ-JXDXRIQ01BOYlp7Ufj5vI,114
+pytz/zoneinfo/iso3166.tab,sha256=oBpdFY8x1GrY5vjMKgbGQYEGgqk5fUYDIPaNVCG2XnE,4791
+pytz/zoneinfo/leapseconds,sha256=gWAzwRuERloD6ADF5V6tUV26U_oVm5xh2nYC6jVwYOg,3257
+pytz/zoneinfo/tzdata.zi,sha256=-EeBhT7eWZNN3RIVLVFnf0Ekn2iff5gPQIxShpDY0lA,107471
+pytz/zoneinfo/zone.tab,sha256=WGtCB-bHZyLegq3Npr9J12H2aFF_RaZz9k2oOzM-7MQ,18822
+pytz/zoneinfo/zone1970.tab,sha256=VxlOQ7ABuPgymHshuClT2Zeu6uvrU6hSAUC8EtfYz8w,17597
+pytz/zoneinfo/zonenow.tab,sha256=JGdDvM4N0VGEYGVD2AgcuxIExbb_gje3WMtnwQkAzi8,8084
diff --git a/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/WHEEL
new file mode 100644
index 0000000..4724c45
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/WHEEL
@@ -0,0 +1,6 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.42.0)
+Root-Is-Purelib: true
+Tag: py2-none-any
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/top_level.txt
new file mode 100644
index 0000000..af44f19
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/top_level.txt
@@ -0,0 +1 @@
+pytz
diff --git a/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/zip-safe b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz-2025.2.dist-info/zip-safe
@@ -0,0 +1 @@
+
diff --git a/testcline/lib/python3.12/site-packages/pytz/__init__.py b/testcline/lib/python3.12/site-packages/pytz/__init__.py
new file mode 100644
index 0000000..8e44c3c
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/__init__.py
@@ -0,0 +1,1556 @@
+'''
+datetime.tzinfo timezone definitions generated from the
+Olson timezone database:
+
+ ftp://elsie.nci.nih.gov/pub/tz*.tar.gz
+
+See the datetime section of the Python Library Reference for information
+on how to use these modules.
+'''
+
+import sys
+import datetime
+import os.path
+
+from pytz.exceptions import AmbiguousTimeError
+from pytz.exceptions import InvalidTimeError
+from pytz.exceptions import NonExistentTimeError
+from pytz.exceptions import UnknownTimeZoneError
+from pytz.lazy import LazyDict, LazyList, LazySet # noqa
+from pytz.tzinfo import unpickler, BaseTzInfo
+from pytz.tzfile import build_tzinfo
+
+
+# The IANA (nee Olson) database is updated several times a year.
+OLSON_VERSION = '2025b'
+VERSION = '2025.2' # pip compatible version number.
+__version__ = VERSION
+
+OLSEN_VERSION = OLSON_VERSION # Old releases had this misspelling
+
+__all__ = [
+ 'timezone', 'utc', 'country_timezones', 'country_names',
+ 'AmbiguousTimeError', 'InvalidTimeError',
+ 'NonExistentTimeError', 'UnknownTimeZoneError',
+ 'all_timezones', 'all_timezones_set',
+ 'common_timezones', 'common_timezones_set',
+ 'BaseTzInfo', 'FixedOffset',
+]
+
+
+if sys.version_info[0] > 2: # Python 3.x
+
+ # Python 3.x doesn't have unicode(), making writing code
+ # for Python 2.3 and Python 3.x a pain.
+ unicode = str
+
+ def ascii(s):
+ r"""
+ >>> ascii('Hello')
+ 'Hello'
+ >>> ascii('\N{TRADE MARK SIGN}') #doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ UnicodeEncodeError: ...
+ """
+ if type(s) == bytes:
+ s = s.decode('ASCII')
+ else:
+ s.encode('ASCII') # Raise an exception if not ASCII
+ return s # But the string - not a byte string.
+
+else: # Python 2.x
+
+ def ascii(s):
+ r"""
+ >>> ascii('Hello')
+ 'Hello'
+ >>> ascii(u'Hello')
+ 'Hello'
+ >>> ascii(u'\N{TRADE MARK SIGN}') #doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ UnicodeEncodeError: ...
+ """
+ return s.encode('ASCII')
+
+
+def open_resource(name):
+ """Open a resource from the zoneinfo subdir for reading.
+
+ Uses the pkg_resources module if available and no standard file
+ found at the calculated location.
+
+ It is possible to specify different location for zoneinfo
+ subdir by using the PYTZ_TZDATADIR environment variable.
+ """
+ name_parts = name.lstrip('/').split('/')
+ for part in name_parts:
+ if part == os.path.pardir or os.sep in part:
+ raise ValueError('Bad path segment: %r' % part)
+ zoneinfo_dir = os.environ.get('PYTZ_TZDATADIR', None)
+ if zoneinfo_dir is not None:
+ filename = os.path.join(zoneinfo_dir, *name_parts)
+ else:
+ filename = os.path.join(os.path.dirname(__file__),
+ 'zoneinfo', *name_parts)
+ if not os.path.exists(filename):
+ # http://bugs.launchpad.net/bugs/383171 - we avoid using this
+ # unless absolutely necessary to help when a broken version of
+ # pkg_resources is installed.
+ try:
+ from pkg_resources import resource_stream
+ except ImportError:
+ resource_stream = None
+
+ if resource_stream is not None:
+ return resource_stream(__name__, 'zoneinfo/' + name)
+ return open(filename, 'rb')
+
+
+def resource_exists(name):
+ """Return true if the given resource exists"""
+ try:
+ if os.environ.get('PYTZ_SKIPEXISTSCHECK', ''):
+ # In "standard" distributions, we can assume that
+ # all the listed timezones are present. As an
+ # import-speed optimization, you can set the
+ # PYTZ_SKIPEXISTSCHECK flag to skip checking
+ # for the presence of the resource file on disk.
+ return True
+ open_resource(name).close()
+ return True
+ except IOError:
+ return False
+
+
+_tzinfo_cache = {}
+
+
+def timezone(zone):
+ r''' Return a datetime.tzinfo implementation for the given timezone
+
+ >>> from datetime import datetime, timedelta
+ >>> utc = timezone('UTC')
+ >>> eastern = timezone('US/Eastern')
+ >>> eastern.zone
+ 'US/Eastern'
+ >>> timezone(unicode('US/Eastern')) is eastern
+ True
+ >>> utc_dt = datetime(2002, 10, 27, 6, 0, 0, tzinfo=utc)
+ >>> loc_dt = utc_dt.astimezone(eastern)
+ >>> fmt = '%Y-%m-%d %H:%M:%S %Z (%z)'
+ >>> loc_dt.strftime(fmt)
+ '2002-10-27 01:00:00 EST (-0500)'
+ >>> (loc_dt - timedelta(minutes=10)).strftime(fmt)
+ '2002-10-27 00:50:00 EST (-0500)'
+ >>> eastern.normalize(loc_dt - timedelta(minutes=10)).strftime(fmt)
+ '2002-10-27 01:50:00 EDT (-0400)'
+ >>> (loc_dt + timedelta(minutes=10)).strftime(fmt)
+ '2002-10-27 01:10:00 EST (-0500)'
+
+ Raises UnknownTimeZoneError if passed an unknown zone.
+
+ >>> try:
+ ... timezone('Asia/Shangri-La')
+ ... except UnknownTimeZoneError:
+ ... print('Unknown')
+ Unknown
+
+ >>> try:
+ ... timezone(unicode('\N{TRADE MARK SIGN}'))
+ ... except UnknownTimeZoneError:
+ ... print('Unknown')
+ Unknown
+
+ '''
+ if zone is None:
+ raise UnknownTimeZoneError(None)
+
+ if zone.upper() == 'UTC':
+ return utc
+
+ try:
+ zone = ascii(zone)
+ except UnicodeEncodeError:
+ # All valid timezones are ASCII
+ raise UnknownTimeZoneError(zone)
+
+ zone = _case_insensitive_zone_lookup(_unmunge_zone(zone))
+ if zone not in _tzinfo_cache:
+ if zone in all_timezones_set: # noqa
+ fp = open_resource(zone)
+ try:
+ _tzinfo_cache[zone] = build_tzinfo(zone, fp)
+ finally:
+ fp.close()
+ else:
+ raise UnknownTimeZoneError(zone)
+
+ return _tzinfo_cache[zone]
+
+
+def _unmunge_zone(zone):
+ """Undo the time zone name munging done by older versions of pytz."""
+ return zone.replace('_plus_', '+').replace('_minus_', '-')
+
+
+_all_timezones_lower_to_standard = None
+
+
+def _case_insensitive_zone_lookup(zone):
+ """case-insensitively matching timezone, else return zone unchanged"""
+ global _all_timezones_lower_to_standard
+ if _all_timezones_lower_to_standard is None:
+ _all_timezones_lower_to_standard = dict((tz.lower(), tz) for tz in _all_timezones_unchecked) # noqa
+ return _all_timezones_lower_to_standard.get(zone.lower()) or zone # noqa
+
+
+ZERO = datetime.timedelta(0)
+HOUR = datetime.timedelta(hours=1)
+
+
+class UTC(BaseTzInfo):
+ """UTC
+
+ Optimized UTC implementation. It unpickles using the single module global
+ instance defined beneath this class declaration.
+ """
+ zone = "UTC"
+
+ _utcoffset = ZERO
+ _dst = ZERO
+ _tzname = zone
+
+ def fromutc(self, dt):
+ if dt.tzinfo is None:
+ return self.localize(dt)
+ return super(utc.__class__, self).fromutc(dt)
+
+ def utcoffset(self, dt):
+ return ZERO
+
+ def tzname(self, dt):
+ return "UTC"
+
+ def dst(self, dt):
+ return ZERO
+
+ def __reduce__(self):
+ return _UTC, ()
+
+ def localize(self, dt, is_dst=False):
+ '''Convert naive time to local time'''
+ if dt.tzinfo is not None:
+ raise ValueError('Not naive datetime (tzinfo is already set)')
+ return dt.replace(tzinfo=self)
+
+ def normalize(self, dt, is_dst=False):
+ '''Correct the timezone information on the given datetime'''
+ if dt.tzinfo is self:
+ return dt
+ if dt.tzinfo is None:
+ raise ValueError('Naive time - no tzinfo set')
+ return dt.astimezone(self)
+
+ def __repr__(self):
+ return ""
+
+ def __str__(self):
+ return "UTC"
+
+
+UTC = utc = UTC() # UTC is a singleton
+
+
+def _UTC():
+ """Factory function for utc unpickling.
+
+ Makes sure that unpickling a utc instance always returns the same
+ module global.
+
+ These examples belong in the UTC class above, but it is obscured; or in
+ the README.rst, but we are not depending on Python 2.4 so integrating
+ the README.rst examples with the unit tests is not trivial.
+
+ >>> import datetime, pickle
+ >>> dt = datetime.datetime(2005, 3, 1, 14, 13, 21, tzinfo=utc)
+ >>> naive = dt.replace(tzinfo=None)
+ >>> p = pickle.dumps(dt, 1)
+ >>> naive_p = pickle.dumps(naive, 1)
+ >>> len(p) - len(naive_p)
+ 17
+ >>> new = pickle.loads(p)
+ >>> new == dt
+ True
+ >>> new is dt
+ False
+ >>> new.tzinfo is dt.tzinfo
+ True
+ >>> utc is UTC is timezone('UTC')
+ True
+ >>> utc is timezone('GMT')
+ False
+ """
+ return utc
+
+
+_UTC.__safe_for_unpickling__ = True
+
+
+def _p(*args):
+ """Factory function for unpickling pytz tzinfo instances.
+
+ Just a wrapper around tzinfo.unpickler to save a few bytes in each pickle
+ by shortening the path.
+ """
+ return unpickler(*args)
+
+
+_p.__safe_for_unpickling__ = True
+
+
+class _CountryTimezoneDict(LazyDict):
+ """Map ISO 3166 country code to a list of timezone names commonly used
+ in that country.
+
+ iso3166_code is the two letter code used to identify the country.
+
+ >>> def print_list(list_of_strings):
+ ... 'We use a helper so doctests work under Python 2.3 -> 3.x'
+ ... for s in list_of_strings:
+ ... print(s)
+
+ >>> print_list(country_timezones['nz'])
+ Pacific/Auckland
+ Pacific/Chatham
+ >>> print_list(country_timezones['ch'])
+ Europe/Zurich
+ >>> print_list(country_timezones['CH'])
+ Europe/Zurich
+ >>> print_list(country_timezones[unicode('ch')])
+ Europe/Zurich
+ >>> print_list(country_timezones['XXX'])
+ Traceback (most recent call last):
+ ...
+ KeyError: 'XXX'
+
+ Previously, this information was exposed as a function rather than a
+ dictionary. This is still supported::
+
+ >>> print_list(country_timezones('nz'))
+ Pacific/Auckland
+ Pacific/Chatham
+ """
+ def __call__(self, iso3166_code):
+ """Backwards compatibility."""
+ return self[iso3166_code]
+
+ def _fill(self):
+ data = {}
+ zone_tab = open_resource('zone.tab')
+ try:
+ for line in zone_tab:
+ line = line.decode('UTF-8')
+ if line.startswith('#'):
+ continue
+ code, coordinates, zone = line.split(None, 4)[:3]
+ if zone not in all_timezones_set: # noqa
+ continue
+ try:
+ data[code].append(zone)
+ except KeyError:
+ data[code] = [zone]
+ self.data = data
+ finally:
+ zone_tab.close()
+
+
+country_timezones = _CountryTimezoneDict()
+
+
+class _CountryNameDict(LazyDict):
+ '''Dictionary proving ISO3166 code -> English name.
+
+ >>> print(country_names['au'])
+ Australia
+ '''
+ def _fill(self):
+ data = {}
+ zone_tab = open_resource('iso3166.tab')
+ try:
+ for line in zone_tab.readlines():
+ line = line.decode('UTF-8')
+ if line.startswith('#'):
+ continue
+ code, name = line.split(None, 1)
+ data[code] = name.strip()
+ self.data = data
+ finally:
+ zone_tab.close()
+
+
+country_names = _CountryNameDict()
+
+
+# Time-zone info based solely on fixed offsets
+
+class _FixedOffset(datetime.tzinfo):
+
+ zone = None # to match the standard pytz API
+
+ def __init__(self, minutes):
+ if abs(minutes) >= 1440:
+ raise ValueError("absolute offset is too large", minutes)
+ self._minutes = minutes
+ self._offset = datetime.timedelta(minutes=minutes)
+
+ def utcoffset(self, dt):
+ return self._offset
+
+ def __reduce__(self):
+ return FixedOffset, (self._minutes, )
+
+ def dst(self, dt):
+ return ZERO
+
+ def tzname(self, dt):
+ return None
+
+ def __repr__(self):
+ return 'pytz.FixedOffset(%d)' % self._minutes
+
+ def localize(self, dt, is_dst=False):
+ '''Convert naive time to local time'''
+ if dt.tzinfo is not None:
+ raise ValueError('Not naive datetime (tzinfo is already set)')
+ return dt.replace(tzinfo=self)
+
+ def normalize(self, dt, is_dst=False):
+ '''Correct the timezone information on the given datetime'''
+ if dt.tzinfo is self:
+ return dt
+ if dt.tzinfo is None:
+ raise ValueError('Naive time - no tzinfo set')
+ return dt.astimezone(self)
+
+
+def FixedOffset(offset, _tzinfos={}):
+ """return a fixed-offset timezone based off a number of minutes.
+
+ >>> one = FixedOffset(-330)
+ >>> one
+ pytz.FixedOffset(-330)
+ >>> str(one.utcoffset(datetime.datetime.now()))
+ '-1 day, 18:30:00'
+ >>> str(one.dst(datetime.datetime.now()))
+ '0:00:00'
+
+ >>> two = FixedOffset(1380)
+ >>> two
+ pytz.FixedOffset(1380)
+ >>> str(two.utcoffset(datetime.datetime.now()))
+ '23:00:00'
+ >>> str(two.dst(datetime.datetime.now()))
+ '0:00:00'
+
+ The datetime.timedelta must be between the range of -1 and 1 day,
+ non-inclusive.
+
+ >>> FixedOffset(1440)
+ Traceback (most recent call last):
+ ...
+ ValueError: ('absolute offset is too large', 1440)
+
+ >>> FixedOffset(-1440)
+ Traceback (most recent call last):
+ ...
+ ValueError: ('absolute offset is too large', -1440)
+
+ An offset of 0 is special-cased to return UTC.
+
+ >>> FixedOffset(0) is UTC
+ True
+
+ There should always be only one instance of a FixedOffset per timedelta.
+ This should be true for multiple creation calls.
+
+ >>> FixedOffset(-330) is one
+ True
+ >>> FixedOffset(1380) is two
+ True
+
+ It should also be true for pickling.
+
+ >>> import pickle
+ >>> pickle.loads(pickle.dumps(one)) is one
+ True
+ >>> pickle.loads(pickle.dumps(two)) is two
+ True
+ """
+ if offset == 0:
+ return UTC
+
+ info = _tzinfos.get(offset)
+ if info is None:
+ # We haven't seen this one before. we need to save it.
+
+ # Use setdefault to avoid a race condition and make sure we have
+ # only one
+ info = _tzinfos.setdefault(offset, _FixedOffset(offset))
+
+ return info
+
+
+FixedOffset.__safe_for_unpickling__ = True
+
+
+def _test():
+ import doctest
+ sys.path.insert(0, os.pardir)
+ import pytz
+ return doctest.testmod(pytz)
+
+
+if __name__ == '__main__':
+ _test()
+_all_timezones_unchecked = \
+['Africa/Abidjan',
+ 'Africa/Accra',
+ 'Africa/Addis_Ababa',
+ 'Africa/Algiers',
+ 'Africa/Asmara',
+ 'Africa/Asmera',
+ 'Africa/Bamako',
+ 'Africa/Bangui',
+ 'Africa/Banjul',
+ 'Africa/Bissau',
+ 'Africa/Blantyre',
+ 'Africa/Brazzaville',
+ 'Africa/Bujumbura',
+ 'Africa/Cairo',
+ 'Africa/Casablanca',
+ 'Africa/Ceuta',
+ 'Africa/Conakry',
+ 'Africa/Dakar',
+ 'Africa/Dar_es_Salaam',
+ 'Africa/Djibouti',
+ 'Africa/Douala',
+ 'Africa/El_Aaiun',
+ 'Africa/Freetown',
+ 'Africa/Gaborone',
+ 'Africa/Harare',
+ 'Africa/Johannesburg',
+ 'Africa/Juba',
+ 'Africa/Kampala',
+ 'Africa/Khartoum',
+ 'Africa/Kigali',
+ 'Africa/Kinshasa',
+ 'Africa/Lagos',
+ 'Africa/Libreville',
+ 'Africa/Lome',
+ 'Africa/Luanda',
+ 'Africa/Lubumbashi',
+ 'Africa/Lusaka',
+ 'Africa/Malabo',
+ 'Africa/Maputo',
+ 'Africa/Maseru',
+ 'Africa/Mbabane',
+ 'Africa/Mogadishu',
+ 'Africa/Monrovia',
+ 'Africa/Nairobi',
+ 'Africa/Ndjamena',
+ 'Africa/Niamey',
+ 'Africa/Nouakchott',
+ 'Africa/Ouagadougou',
+ 'Africa/Porto-Novo',
+ 'Africa/Sao_Tome',
+ 'Africa/Timbuktu',
+ 'Africa/Tripoli',
+ 'Africa/Tunis',
+ 'Africa/Windhoek',
+ 'America/Adak',
+ 'America/Anchorage',
+ 'America/Anguilla',
+ 'America/Antigua',
+ 'America/Araguaina',
+ 'America/Argentina/Buenos_Aires',
+ 'America/Argentina/Catamarca',
+ 'America/Argentina/ComodRivadavia',
+ 'America/Argentina/Cordoba',
+ 'America/Argentina/Jujuy',
+ 'America/Argentina/La_Rioja',
+ 'America/Argentina/Mendoza',
+ 'America/Argentina/Rio_Gallegos',
+ 'America/Argentina/Salta',
+ 'America/Argentina/San_Juan',
+ 'America/Argentina/San_Luis',
+ 'America/Argentina/Tucuman',
+ 'America/Argentina/Ushuaia',
+ 'America/Aruba',
+ 'America/Asuncion',
+ 'America/Atikokan',
+ 'America/Atka',
+ 'America/Bahia',
+ 'America/Bahia_Banderas',
+ 'America/Barbados',
+ 'America/Belem',
+ 'America/Belize',
+ 'America/Blanc-Sablon',
+ 'America/Boa_Vista',
+ 'America/Bogota',
+ 'America/Boise',
+ 'America/Buenos_Aires',
+ 'America/Cambridge_Bay',
+ 'America/Campo_Grande',
+ 'America/Cancun',
+ 'America/Caracas',
+ 'America/Catamarca',
+ 'America/Cayenne',
+ 'America/Cayman',
+ 'America/Chicago',
+ 'America/Chihuahua',
+ 'America/Ciudad_Juarez',
+ 'America/Coral_Harbour',
+ 'America/Cordoba',
+ 'America/Costa_Rica',
+ 'America/Coyhaique',
+ 'America/Creston',
+ 'America/Cuiaba',
+ 'America/Curacao',
+ 'America/Danmarkshavn',
+ 'America/Dawson',
+ 'America/Dawson_Creek',
+ 'America/Denver',
+ 'America/Detroit',
+ 'America/Dominica',
+ 'America/Edmonton',
+ 'America/Eirunepe',
+ 'America/El_Salvador',
+ 'America/Ensenada',
+ 'America/Fort_Nelson',
+ 'America/Fort_Wayne',
+ 'America/Fortaleza',
+ 'America/Glace_Bay',
+ 'America/Godthab',
+ 'America/Goose_Bay',
+ 'America/Grand_Turk',
+ 'America/Grenada',
+ 'America/Guadeloupe',
+ 'America/Guatemala',
+ 'America/Guayaquil',
+ 'America/Guyana',
+ 'America/Halifax',
+ 'America/Havana',
+ 'America/Hermosillo',
+ 'America/Indiana/Indianapolis',
+ 'America/Indiana/Knox',
+ 'America/Indiana/Marengo',
+ 'America/Indiana/Petersburg',
+ 'America/Indiana/Tell_City',
+ 'America/Indiana/Vevay',
+ 'America/Indiana/Vincennes',
+ 'America/Indiana/Winamac',
+ 'America/Indianapolis',
+ 'America/Inuvik',
+ 'America/Iqaluit',
+ 'America/Jamaica',
+ 'America/Jujuy',
+ 'America/Juneau',
+ 'America/Kentucky/Louisville',
+ 'America/Kentucky/Monticello',
+ 'America/Knox_IN',
+ 'America/Kralendijk',
+ 'America/La_Paz',
+ 'America/Lima',
+ 'America/Los_Angeles',
+ 'America/Louisville',
+ 'America/Lower_Princes',
+ 'America/Maceio',
+ 'America/Managua',
+ 'America/Manaus',
+ 'America/Marigot',
+ 'America/Martinique',
+ 'America/Matamoros',
+ 'America/Mazatlan',
+ 'America/Mendoza',
+ 'America/Menominee',
+ 'America/Merida',
+ 'America/Metlakatla',
+ 'America/Mexico_City',
+ 'America/Miquelon',
+ 'America/Moncton',
+ 'America/Monterrey',
+ 'America/Montevideo',
+ 'America/Montreal',
+ 'America/Montserrat',
+ 'America/Nassau',
+ 'America/New_York',
+ 'America/Nipigon',
+ 'America/Nome',
+ 'America/Noronha',
+ 'America/North_Dakota/Beulah',
+ 'America/North_Dakota/Center',
+ 'America/North_Dakota/New_Salem',
+ 'America/Nuuk',
+ 'America/Ojinaga',
+ 'America/Panama',
+ 'America/Pangnirtung',
+ 'America/Paramaribo',
+ 'America/Phoenix',
+ 'America/Port-au-Prince',
+ 'America/Port_of_Spain',
+ 'America/Porto_Acre',
+ 'America/Porto_Velho',
+ 'America/Puerto_Rico',
+ 'America/Punta_Arenas',
+ 'America/Rainy_River',
+ 'America/Rankin_Inlet',
+ 'America/Recife',
+ 'America/Regina',
+ 'America/Resolute',
+ 'America/Rio_Branco',
+ 'America/Rosario',
+ 'America/Santa_Isabel',
+ 'America/Santarem',
+ 'America/Santiago',
+ 'America/Santo_Domingo',
+ 'America/Sao_Paulo',
+ 'America/Scoresbysund',
+ 'America/Shiprock',
+ 'America/Sitka',
+ 'America/St_Barthelemy',
+ 'America/St_Johns',
+ 'America/St_Kitts',
+ 'America/St_Lucia',
+ 'America/St_Thomas',
+ 'America/St_Vincent',
+ 'America/Swift_Current',
+ 'America/Tegucigalpa',
+ 'America/Thule',
+ 'America/Thunder_Bay',
+ 'America/Tijuana',
+ 'America/Toronto',
+ 'America/Tortola',
+ 'America/Vancouver',
+ 'America/Virgin',
+ 'America/Whitehorse',
+ 'America/Winnipeg',
+ 'America/Yakutat',
+ 'America/Yellowknife',
+ 'Antarctica/Casey',
+ 'Antarctica/Davis',
+ 'Antarctica/DumontDUrville',
+ 'Antarctica/Macquarie',
+ 'Antarctica/Mawson',
+ 'Antarctica/McMurdo',
+ 'Antarctica/Palmer',
+ 'Antarctica/Rothera',
+ 'Antarctica/South_Pole',
+ 'Antarctica/Syowa',
+ 'Antarctica/Troll',
+ 'Antarctica/Vostok',
+ 'Arctic/Longyearbyen',
+ 'Asia/Aden',
+ 'Asia/Almaty',
+ 'Asia/Amman',
+ 'Asia/Anadyr',
+ 'Asia/Aqtau',
+ 'Asia/Aqtobe',
+ 'Asia/Ashgabat',
+ 'Asia/Ashkhabad',
+ 'Asia/Atyrau',
+ 'Asia/Baghdad',
+ 'Asia/Bahrain',
+ 'Asia/Baku',
+ 'Asia/Bangkok',
+ 'Asia/Barnaul',
+ 'Asia/Beirut',
+ 'Asia/Bishkek',
+ 'Asia/Brunei',
+ 'Asia/Calcutta',
+ 'Asia/Chita',
+ 'Asia/Choibalsan',
+ 'Asia/Chongqing',
+ 'Asia/Chungking',
+ 'Asia/Colombo',
+ 'Asia/Dacca',
+ 'Asia/Damascus',
+ 'Asia/Dhaka',
+ 'Asia/Dili',
+ 'Asia/Dubai',
+ 'Asia/Dushanbe',
+ 'Asia/Famagusta',
+ 'Asia/Gaza',
+ 'Asia/Harbin',
+ 'Asia/Hebron',
+ 'Asia/Ho_Chi_Minh',
+ 'Asia/Hong_Kong',
+ 'Asia/Hovd',
+ 'Asia/Irkutsk',
+ 'Asia/Istanbul',
+ 'Asia/Jakarta',
+ 'Asia/Jayapura',
+ 'Asia/Jerusalem',
+ 'Asia/Kabul',
+ 'Asia/Kamchatka',
+ 'Asia/Karachi',
+ 'Asia/Kashgar',
+ 'Asia/Kathmandu',
+ 'Asia/Katmandu',
+ 'Asia/Khandyga',
+ 'Asia/Kolkata',
+ 'Asia/Krasnoyarsk',
+ 'Asia/Kuala_Lumpur',
+ 'Asia/Kuching',
+ 'Asia/Kuwait',
+ 'Asia/Macao',
+ 'Asia/Macau',
+ 'Asia/Magadan',
+ 'Asia/Makassar',
+ 'Asia/Manila',
+ 'Asia/Muscat',
+ 'Asia/Nicosia',
+ 'Asia/Novokuznetsk',
+ 'Asia/Novosibirsk',
+ 'Asia/Omsk',
+ 'Asia/Oral',
+ 'Asia/Phnom_Penh',
+ 'Asia/Pontianak',
+ 'Asia/Pyongyang',
+ 'Asia/Qatar',
+ 'Asia/Qostanay',
+ 'Asia/Qyzylorda',
+ 'Asia/Rangoon',
+ 'Asia/Riyadh',
+ 'Asia/Saigon',
+ 'Asia/Sakhalin',
+ 'Asia/Samarkand',
+ 'Asia/Seoul',
+ 'Asia/Shanghai',
+ 'Asia/Singapore',
+ 'Asia/Srednekolymsk',
+ 'Asia/Taipei',
+ 'Asia/Tashkent',
+ 'Asia/Tbilisi',
+ 'Asia/Tehran',
+ 'Asia/Tel_Aviv',
+ 'Asia/Thimbu',
+ 'Asia/Thimphu',
+ 'Asia/Tokyo',
+ 'Asia/Tomsk',
+ 'Asia/Ujung_Pandang',
+ 'Asia/Ulaanbaatar',
+ 'Asia/Ulan_Bator',
+ 'Asia/Urumqi',
+ 'Asia/Ust-Nera',
+ 'Asia/Vientiane',
+ 'Asia/Vladivostok',
+ 'Asia/Yakutsk',
+ 'Asia/Yangon',
+ 'Asia/Yekaterinburg',
+ 'Asia/Yerevan',
+ 'Atlantic/Azores',
+ 'Atlantic/Bermuda',
+ 'Atlantic/Canary',
+ 'Atlantic/Cape_Verde',
+ 'Atlantic/Faeroe',
+ 'Atlantic/Faroe',
+ 'Atlantic/Jan_Mayen',
+ 'Atlantic/Madeira',
+ 'Atlantic/Reykjavik',
+ 'Atlantic/South_Georgia',
+ 'Atlantic/St_Helena',
+ 'Atlantic/Stanley',
+ 'Australia/ACT',
+ 'Australia/Adelaide',
+ 'Australia/Brisbane',
+ 'Australia/Broken_Hill',
+ 'Australia/Canberra',
+ 'Australia/Currie',
+ 'Australia/Darwin',
+ 'Australia/Eucla',
+ 'Australia/Hobart',
+ 'Australia/LHI',
+ 'Australia/Lindeman',
+ 'Australia/Lord_Howe',
+ 'Australia/Melbourne',
+ 'Australia/NSW',
+ 'Australia/North',
+ 'Australia/Perth',
+ 'Australia/Queensland',
+ 'Australia/South',
+ 'Australia/Sydney',
+ 'Australia/Tasmania',
+ 'Australia/Victoria',
+ 'Australia/West',
+ 'Australia/Yancowinna',
+ 'Brazil/Acre',
+ 'Brazil/DeNoronha',
+ 'Brazil/East',
+ 'Brazil/West',
+ 'CET',
+ 'CST6CDT',
+ 'Canada/Atlantic',
+ 'Canada/Central',
+ 'Canada/Eastern',
+ 'Canada/Mountain',
+ 'Canada/Newfoundland',
+ 'Canada/Pacific',
+ 'Canada/Saskatchewan',
+ 'Canada/Yukon',
+ 'Chile/Continental',
+ 'Chile/EasterIsland',
+ 'Cuba',
+ 'EET',
+ 'EST',
+ 'EST5EDT',
+ 'Egypt',
+ 'Eire',
+ 'Etc/GMT',
+ 'Etc/GMT+0',
+ 'Etc/GMT+1',
+ 'Etc/GMT+10',
+ 'Etc/GMT+11',
+ 'Etc/GMT+12',
+ 'Etc/GMT+2',
+ 'Etc/GMT+3',
+ 'Etc/GMT+4',
+ 'Etc/GMT+5',
+ 'Etc/GMT+6',
+ 'Etc/GMT+7',
+ 'Etc/GMT+8',
+ 'Etc/GMT+9',
+ 'Etc/GMT-0',
+ 'Etc/GMT-1',
+ 'Etc/GMT-10',
+ 'Etc/GMT-11',
+ 'Etc/GMT-12',
+ 'Etc/GMT-13',
+ 'Etc/GMT-14',
+ 'Etc/GMT-2',
+ 'Etc/GMT-3',
+ 'Etc/GMT-4',
+ 'Etc/GMT-5',
+ 'Etc/GMT-6',
+ 'Etc/GMT-7',
+ 'Etc/GMT-8',
+ 'Etc/GMT-9',
+ 'Etc/GMT0',
+ 'Etc/Greenwich',
+ 'Etc/UCT',
+ 'Etc/UTC',
+ 'Etc/Universal',
+ 'Etc/Zulu',
+ 'Europe/Amsterdam',
+ 'Europe/Andorra',
+ 'Europe/Astrakhan',
+ 'Europe/Athens',
+ 'Europe/Belfast',
+ 'Europe/Belgrade',
+ 'Europe/Berlin',
+ 'Europe/Bratislava',
+ 'Europe/Brussels',
+ 'Europe/Bucharest',
+ 'Europe/Budapest',
+ 'Europe/Busingen',
+ 'Europe/Chisinau',
+ 'Europe/Copenhagen',
+ 'Europe/Dublin',
+ 'Europe/Gibraltar',
+ 'Europe/Guernsey',
+ 'Europe/Helsinki',
+ 'Europe/Isle_of_Man',
+ 'Europe/Istanbul',
+ 'Europe/Jersey',
+ 'Europe/Kaliningrad',
+ 'Europe/Kiev',
+ 'Europe/Kirov',
+ 'Europe/Kyiv',
+ 'Europe/Lisbon',
+ 'Europe/Ljubljana',
+ 'Europe/London',
+ 'Europe/Luxembourg',
+ 'Europe/Madrid',
+ 'Europe/Malta',
+ 'Europe/Mariehamn',
+ 'Europe/Minsk',
+ 'Europe/Monaco',
+ 'Europe/Moscow',
+ 'Europe/Nicosia',
+ 'Europe/Oslo',
+ 'Europe/Paris',
+ 'Europe/Podgorica',
+ 'Europe/Prague',
+ 'Europe/Riga',
+ 'Europe/Rome',
+ 'Europe/Samara',
+ 'Europe/San_Marino',
+ 'Europe/Sarajevo',
+ 'Europe/Saratov',
+ 'Europe/Simferopol',
+ 'Europe/Skopje',
+ 'Europe/Sofia',
+ 'Europe/Stockholm',
+ 'Europe/Tallinn',
+ 'Europe/Tirane',
+ 'Europe/Tiraspol',
+ 'Europe/Ulyanovsk',
+ 'Europe/Uzhgorod',
+ 'Europe/Vaduz',
+ 'Europe/Vatican',
+ 'Europe/Vienna',
+ 'Europe/Vilnius',
+ 'Europe/Volgograd',
+ 'Europe/Warsaw',
+ 'Europe/Zagreb',
+ 'Europe/Zaporozhye',
+ 'Europe/Zurich',
+ 'GB',
+ 'GB-Eire',
+ 'GMT',
+ 'GMT+0',
+ 'GMT-0',
+ 'GMT0',
+ 'Greenwich',
+ 'HST',
+ 'Hongkong',
+ 'Iceland',
+ 'Indian/Antananarivo',
+ 'Indian/Chagos',
+ 'Indian/Christmas',
+ 'Indian/Cocos',
+ 'Indian/Comoro',
+ 'Indian/Kerguelen',
+ 'Indian/Mahe',
+ 'Indian/Maldives',
+ 'Indian/Mauritius',
+ 'Indian/Mayotte',
+ 'Indian/Reunion',
+ 'Iran',
+ 'Israel',
+ 'Jamaica',
+ 'Japan',
+ 'Kwajalein',
+ 'Libya',
+ 'MET',
+ 'MST',
+ 'MST7MDT',
+ 'Mexico/BajaNorte',
+ 'Mexico/BajaSur',
+ 'Mexico/General',
+ 'NZ',
+ 'NZ-CHAT',
+ 'Navajo',
+ 'PRC',
+ 'PST8PDT',
+ 'Pacific/Apia',
+ 'Pacific/Auckland',
+ 'Pacific/Bougainville',
+ 'Pacific/Chatham',
+ 'Pacific/Chuuk',
+ 'Pacific/Easter',
+ 'Pacific/Efate',
+ 'Pacific/Enderbury',
+ 'Pacific/Fakaofo',
+ 'Pacific/Fiji',
+ 'Pacific/Funafuti',
+ 'Pacific/Galapagos',
+ 'Pacific/Gambier',
+ 'Pacific/Guadalcanal',
+ 'Pacific/Guam',
+ 'Pacific/Honolulu',
+ 'Pacific/Johnston',
+ 'Pacific/Kanton',
+ 'Pacific/Kiritimati',
+ 'Pacific/Kosrae',
+ 'Pacific/Kwajalein',
+ 'Pacific/Majuro',
+ 'Pacific/Marquesas',
+ 'Pacific/Midway',
+ 'Pacific/Nauru',
+ 'Pacific/Niue',
+ 'Pacific/Norfolk',
+ 'Pacific/Noumea',
+ 'Pacific/Pago_Pago',
+ 'Pacific/Palau',
+ 'Pacific/Pitcairn',
+ 'Pacific/Pohnpei',
+ 'Pacific/Ponape',
+ 'Pacific/Port_Moresby',
+ 'Pacific/Rarotonga',
+ 'Pacific/Saipan',
+ 'Pacific/Samoa',
+ 'Pacific/Tahiti',
+ 'Pacific/Tarawa',
+ 'Pacific/Tongatapu',
+ 'Pacific/Truk',
+ 'Pacific/Wake',
+ 'Pacific/Wallis',
+ 'Pacific/Yap',
+ 'Poland',
+ 'Portugal',
+ 'ROC',
+ 'ROK',
+ 'Singapore',
+ 'Turkey',
+ 'UCT',
+ 'US/Alaska',
+ 'US/Aleutian',
+ 'US/Arizona',
+ 'US/Central',
+ 'US/East-Indiana',
+ 'US/Eastern',
+ 'US/Hawaii',
+ 'US/Indiana-Starke',
+ 'US/Michigan',
+ 'US/Mountain',
+ 'US/Pacific',
+ 'US/Samoa',
+ 'UTC',
+ 'Universal',
+ 'W-SU',
+ 'WET',
+ 'Zulu']
+all_timezones = LazyList(
+ tz for tz in _all_timezones_unchecked if resource_exists(tz))
+
+all_timezones_set = LazySet(all_timezones)
+common_timezones = \
+['Africa/Abidjan',
+ 'Africa/Accra',
+ 'Africa/Addis_Ababa',
+ 'Africa/Algiers',
+ 'Africa/Asmara',
+ 'Africa/Bamako',
+ 'Africa/Bangui',
+ 'Africa/Banjul',
+ 'Africa/Bissau',
+ 'Africa/Blantyre',
+ 'Africa/Brazzaville',
+ 'Africa/Bujumbura',
+ 'Africa/Cairo',
+ 'Africa/Casablanca',
+ 'Africa/Ceuta',
+ 'Africa/Conakry',
+ 'Africa/Dakar',
+ 'Africa/Dar_es_Salaam',
+ 'Africa/Djibouti',
+ 'Africa/Douala',
+ 'Africa/El_Aaiun',
+ 'Africa/Freetown',
+ 'Africa/Gaborone',
+ 'Africa/Harare',
+ 'Africa/Johannesburg',
+ 'Africa/Juba',
+ 'Africa/Kampala',
+ 'Africa/Khartoum',
+ 'Africa/Kigali',
+ 'Africa/Kinshasa',
+ 'Africa/Lagos',
+ 'Africa/Libreville',
+ 'Africa/Lome',
+ 'Africa/Luanda',
+ 'Africa/Lubumbashi',
+ 'Africa/Lusaka',
+ 'Africa/Malabo',
+ 'Africa/Maputo',
+ 'Africa/Maseru',
+ 'Africa/Mbabane',
+ 'Africa/Mogadishu',
+ 'Africa/Monrovia',
+ 'Africa/Nairobi',
+ 'Africa/Ndjamena',
+ 'Africa/Niamey',
+ 'Africa/Nouakchott',
+ 'Africa/Ouagadougou',
+ 'Africa/Porto-Novo',
+ 'Africa/Sao_Tome',
+ 'Africa/Tripoli',
+ 'Africa/Tunis',
+ 'Africa/Windhoek',
+ 'America/Adak',
+ 'America/Anchorage',
+ 'America/Anguilla',
+ 'America/Antigua',
+ 'America/Araguaina',
+ 'America/Argentina/Buenos_Aires',
+ 'America/Argentina/Catamarca',
+ 'America/Argentina/Cordoba',
+ 'America/Argentina/Jujuy',
+ 'America/Argentina/La_Rioja',
+ 'America/Argentina/Mendoza',
+ 'America/Argentina/Rio_Gallegos',
+ 'America/Argentina/Salta',
+ 'America/Argentina/San_Juan',
+ 'America/Argentina/San_Luis',
+ 'America/Argentina/Tucuman',
+ 'America/Argentina/Ushuaia',
+ 'America/Aruba',
+ 'America/Asuncion',
+ 'America/Atikokan',
+ 'America/Bahia',
+ 'America/Bahia_Banderas',
+ 'America/Barbados',
+ 'America/Belem',
+ 'America/Belize',
+ 'America/Blanc-Sablon',
+ 'America/Boa_Vista',
+ 'America/Bogota',
+ 'America/Boise',
+ 'America/Cambridge_Bay',
+ 'America/Campo_Grande',
+ 'America/Cancun',
+ 'America/Caracas',
+ 'America/Cayenne',
+ 'America/Cayman',
+ 'America/Chicago',
+ 'America/Chihuahua',
+ 'America/Ciudad_Juarez',
+ 'America/Costa_Rica',
+ 'America/Coyhaique',
+ 'America/Creston',
+ 'America/Cuiaba',
+ 'America/Curacao',
+ 'America/Danmarkshavn',
+ 'America/Dawson',
+ 'America/Dawson_Creek',
+ 'America/Denver',
+ 'America/Detroit',
+ 'America/Dominica',
+ 'America/Edmonton',
+ 'America/Eirunepe',
+ 'America/El_Salvador',
+ 'America/Fort_Nelson',
+ 'America/Fortaleza',
+ 'America/Glace_Bay',
+ 'America/Goose_Bay',
+ 'America/Grand_Turk',
+ 'America/Grenada',
+ 'America/Guadeloupe',
+ 'America/Guatemala',
+ 'America/Guayaquil',
+ 'America/Guyana',
+ 'America/Halifax',
+ 'America/Havana',
+ 'America/Hermosillo',
+ 'America/Indiana/Indianapolis',
+ 'America/Indiana/Knox',
+ 'America/Indiana/Marengo',
+ 'America/Indiana/Petersburg',
+ 'America/Indiana/Tell_City',
+ 'America/Indiana/Vevay',
+ 'America/Indiana/Vincennes',
+ 'America/Indiana/Winamac',
+ 'America/Inuvik',
+ 'America/Iqaluit',
+ 'America/Jamaica',
+ 'America/Juneau',
+ 'America/Kentucky/Louisville',
+ 'America/Kentucky/Monticello',
+ 'America/Kralendijk',
+ 'America/La_Paz',
+ 'America/Lima',
+ 'America/Los_Angeles',
+ 'America/Lower_Princes',
+ 'America/Maceio',
+ 'America/Managua',
+ 'America/Manaus',
+ 'America/Marigot',
+ 'America/Martinique',
+ 'America/Matamoros',
+ 'America/Mazatlan',
+ 'America/Menominee',
+ 'America/Merida',
+ 'America/Metlakatla',
+ 'America/Mexico_City',
+ 'America/Miquelon',
+ 'America/Moncton',
+ 'America/Monterrey',
+ 'America/Montevideo',
+ 'America/Montserrat',
+ 'America/Nassau',
+ 'America/New_York',
+ 'America/Nome',
+ 'America/Noronha',
+ 'America/North_Dakota/Beulah',
+ 'America/North_Dakota/Center',
+ 'America/North_Dakota/New_Salem',
+ 'America/Nuuk',
+ 'America/Ojinaga',
+ 'America/Panama',
+ 'America/Paramaribo',
+ 'America/Phoenix',
+ 'America/Port-au-Prince',
+ 'America/Port_of_Spain',
+ 'America/Porto_Velho',
+ 'America/Puerto_Rico',
+ 'America/Punta_Arenas',
+ 'America/Rankin_Inlet',
+ 'America/Recife',
+ 'America/Regina',
+ 'America/Resolute',
+ 'America/Rio_Branco',
+ 'America/Santarem',
+ 'America/Santiago',
+ 'America/Santo_Domingo',
+ 'America/Sao_Paulo',
+ 'America/Scoresbysund',
+ 'America/Sitka',
+ 'America/St_Barthelemy',
+ 'America/St_Johns',
+ 'America/St_Kitts',
+ 'America/St_Lucia',
+ 'America/St_Thomas',
+ 'America/St_Vincent',
+ 'America/Swift_Current',
+ 'America/Tegucigalpa',
+ 'America/Thule',
+ 'America/Tijuana',
+ 'America/Toronto',
+ 'America/Tortola',
+ 'America/Vancouver',
+ 'America/Whitehorse',
+ 'America/Winnipeg',
+ 'America/Yakutat',
+ 'Antarctica/Casey',
+ 'Antarctica/Davis',
+ 'Antarctica/DumontDUrville',
+ 'Antarctica/Macquarie',
+ 'Antarctica/Mawson',
+ 'Antarctica/McMurdo',
+ 'Antarctica/Palmer',
+ 'Antarctica/Rothera',
+ 'Antarctica/Syowa',
+ 'Antarctica/Troll',
+ 'Antarctica/Vostok',
+ 'Arctic/Longyearbyen',
+ 'Asia/Aden',
+ 'Asia/Almaty',
+ 'Asia/Amman',
+ 'Asia/Anadyr',
+ 'Asia/Aqtau',
+ 'Asia/Aqtobe',
+ 'Asia/Ashgabat',
+ 'Asia/Atyrau',
+ 'Asia/Baghdad',
+ 'Asia/Bahrain',
+ 'Asia/Baku',
+ 'Asia/Bangkok',
+ 'Asia/Barnaul',
+ 'Asia/Beirut',
+ 'Asia/Bishkek',
+ 'Asia/Brunei',
+ 'Asia/Chita',
+ 'Asia/Colombo',
+ 'Asia/Damascus',
+ 'Asia/Dhaka',
+ 'Asia/Dili',
+ 'Asia/Dubai',
+ 'Asia/Dushanbe',
+ 'Asia/Famagusta',
+ 'Asia/Gaza',
+ 'Asia/Hebron',
+ 'Asia/Ho_Chi_Minh',
+ 'Asia/Hong_Kong',
+ 'Asia/Hovd',
+ 'Asia/Irkutsk',
+ 'Asia/Jakarta',
+ 'Asia/Jayapura',
+ 'Asia/Jerusalem',
+ 'Asia/Kabul',
+ 'Asia/Kamchatka',
+ 'Asia/Karachi',
+ 'Asia/Kathmandu',
+ 'Asia/Khandyga',
+ 'Asia/Kolkata',
+ 'Asia/Krasnoyarsk',
+ 'Asia/Kuala_Lumpur',
+ 'Asia/Kuching',
+ 'Asia/Kuwait',
+ 'Asia/Macau',
+ 'Asia/Magadan',
+ 'Asia/Makassar',
+ 'Asia/Manila',
+ 'Asia/Muscat',
+ 'Asia/Nicosia',
+ 'Asia/Novokuznetsk',
+ 'Asia/Novosibirsk',
+ 'Asia/Omsk',
+ 'Asia/Oral',
+ 'Asia/Phnom_Penh',
+ 'Asia/Pontianak',
+ 'Asia/Pyongyang',
+ 'Asia/Qatar',
+ 'Asia/Qostanay',
+ 'Asia/Qyzylorda',
+ 'Asia/Riyadh',
+ 'Asia/Sakhalin',
+ 'Asia/Samarkand',
+ 'Asia/Seoul',
+ 'Asia/Shanghai',
+ 'Asia/Singapore',
+ 'Asia/Srednekolymsk',
+ 'Asia/Taipei',
+ 'Asia/Tashkent',
+ 'Asia/Tbilisi',
+ 'Asia/Tehran',
+ 'Asia/Thimphu',
+ 'Asia/Tokyo',
+ 'Asia/Tomsk',
+ 'Asia/Ulaanbaatar',
+ 'Asia/Urumqi',
+ 'Asia/Ust-Nera',
+ 'Asia/Vientiane',
+ 'Asia/Vladivostok',
+ 'Asia/Yakutsk',
+ 'Asia/Yangon',
+ 'Asia/Yekaterinburg',
+ 'Asia/Yerevan',
+ 'Atlantic/Azores',
+ 'Atlantic/Bermuda',
+ 'Atlantic/Canary',
+ 'Atlantic/Cape_Verde',
+ 'Atlantic/Faroe',
+ 'Atlantic/Madeira',
+ 'Atlantic/Reykjavik',
+ 'Atlantic/South_Georgia',
+ 'Atlantic/St_Helena',
+ 'Atlantic/Stanley',
+ 'Australia/Adelaide',
+ 'Australia/Brisbane',
+ 'Australia/Broken_Hill',
+ 'Australia/Darwin',
+ 'Australia/Eucla',
+ 'Australia/Hobart',
+ 'Australia/Lindeman',
+ 'Australia/Lord_Howe',
+ 'Australia/Melbourne',
+ 'Australia/Perth',
+ 'Australia/Sydney',
+ 'Canada/Atlantic',
+ 'Canada/Central',
+ 'Canada/Eastern',
+ 'Canada/Mountain',
+ 'Canada/Newfoundland',
+ 'Canada/Pacific',
+ 'Europe/Amsterdam',
+ 'Europe/Andorra',
+ 'Europe/Astrakhan',
+ 'Europe/Athens',
+ 'Europe/Belgrade',
+ 'Europe/Berlin',
+ 'Europe/Bratislava',
+ 'Europe/Brussels',
+ 'Europe/Bucharest',
+ 'Europe/Budapest',
+ 'Europe/Busingen',
+ 'Europe/Chisinau',
+ 'Europe/Copenhagen',
+ 'Europe/Dublin',
+ 'Europe/Gibraltar',
+ 'Europe/Guernsey',
+ 'Europe/Helsinki',
+ 'Europe/Isle_of_Man',
+ 'Europe/Istanbul',
+ 'Europe/Jersey',
+ 'Europe/Kaliningrad',
+ 'Europe/Kirov',
+ 'Europe/Kyiv',
+ 'Europe/Lisbon',
+ 'Europe/Ljubljana',
+ 'Europe/London',
+ 'Europe/Luxembourg',
+ 'Europe/Madrid',
+ 'Europe/Malta',
+ 'Europe/Mariehamn',
+ 'Europe/Minsk',
+ 'Europe/Monaco',
+ 'Europe/Moscow',
+ 'Europe/Oslo',
+ 'Europe/Paris',
+ 'Europe/Podgorica',
+ 'Europe/Prague',
+ 'Europe/Riga',
+ 'Europe/Rome',
+ 'Europe/Samara',
+ 'Europe/San_Marino',
+ 'Europe/Sarajevo',
+ 'Europe/Saratov',
+ 'Europe/Simferopol',
+ 'Europe/Skopje',
+ 'Europe/Sofia',
+ 'Europe/Stockholm',
+ 'Europe/Tallinn',
+ 'Europe/Tirane',
+ 'Europe/Ulyanovsk',
+ 'Europe/Vaduz',
+ 'Europe/Vatican',
+ 'Europe/Vienna',
+ 'Europe/Vilnius',
+ 'Europe/Volgograd',
+ 'Europe/Warsaw',
+ 'Europe/Zagreb',
+ 'Europe/Zurich',
+ 'GMT',
+ 'Indian/Antananarivo',
+ 'Indian/Chagos',
+ 'Indian/Christmas',
+ 'Indian/Cocos',
+ 'Indian/Comoro',
+ 'Indian/Kerguelen',
+ 'Indian/Mahe',
+ 'Indian/Maldives',
+ 'Indian/Mauritius',
+ 'Indian/Mayotte',
+ 'Indian/Reunion',
+ 'Pacific/Apia',
+ 'Pacific/Auckland',
+ 'Pacific/Bougainville',
+ 'Pacific/Chatham',
+ 'Pacific/Chuuk',
+ 'Pacific/Easter',
+ 'Pacific/Efate',
+ 'Pacific/Fakaofo',
+ 'Pacific/Fiji',
+ 'Pacific/Funafuti',
+ 'Pacific/Galapagos',
+ 'Pacific/Gambier',
+ 'Pacific/Guadalcanal',
+ 'Pacific/Guam',
+ 'Pacific/Honolulu',
+ 'Pacific/Kanton',
+ 'Pacific/Kiritimati',
+ 'Pacific/Kosrae',
+ 'Pacific/Kwajalein',
+ 'Pacific/Majuro',
+ 'Pacific/Marquesas',
+ 'Pacific/Midway',
+ 'Pacific/Nauru',
+ 'Pacific/Niue',
+ 'Pacific/Norfolk',
+ 'Pacific/Noumea',
+ 'Pacific/Pago_Pago',
+ 'Pacific/Palau',
+ 'Pacific/Pitcairn',
+ 'Pacific/Pohnpei',
+ 'Pacific/Port_Moresby',
+ 'Pacific/Rarotonga',
+ 'Pacific/Saipan',
+ 'Pacific/Tahiti',
+ 'Pacific/Tarawa',
+ 'Pacific/Tongatapu',
+ 'Pacific/Wake',
+ 'Pacific/Wallis',
+ 'US/Alaska',
+ 'US/Arizona',
+ 'US/Central',
+ 'US/Eastern',
+ 'US/Hawaii',
+ 'US/Mountain',
+ 'US/Pacific',
+ 'UTC']
+common_timezones = LazyList(
+ tz for tz in common_timezones if tz in all_timezones)
+
+common_timezones_set = LazySet(common_timezones)
diff --git a/testcline/lib/python3.12/site-packages/pytz/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pytz/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..a83e704
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/__pycache__/exceptions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pytz/__pycache__/exceptions.cpython-312.pyc
new file mode 100644
index 0000000..7c3fa7b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/__pycache__/exceptions.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/__pycache__/lazy.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pytz/__pycache__/lazy.cpython-312.pyc
new file mode 100644
index 0000000..c5c6f3d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/__pycache__/lazy.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/__pycache__/reference.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pytz/__pycache__/reference.cpython-312.pyc
new file mode 100644
index 0000000..c8869c0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/__pycache__/reference.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/__pycache__/tzfile.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pytz/__pycache__/tzfile.cpython-312.pyc
new file mode 100644
index 0000000..97d1b43
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/__pycache__/tzfile.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/__pycache__/tzinfo.cpython-312.pyc b/testcline/lib/python3.12/site-packages/pytz/__pycache__/tzinfo.cpython-312.pyc
new file mode 100644
index 0000000..c39433d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/__pycache__/tzinfo.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/exceptions.py b/testcline/lib/python3.12/site-packages/pytz/exceptions.py
new file mode 100644
index 0000000..4b20bde
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/exceptions.py
@@ -0,0 +1,59 @@
+'''
+Custom exceptions raised by pytz.
+'''
+
+__all__ = [
+ 'UnknownTimeZoneError', 'InvalidTimeError', 'AmbiguousTimeError',
+ 'NonExistentTimeError',
+]
+
+
+class Error(Exception):
+ '''Base class for all exceptions raised by the pytz library'''
+
+
+class UnknownTimeZoneError(KeyError, Error):
+ '''Exception raised when pytz is passed an unknown timezone.
+
+ >>> isinstance(UnknownTimeZoneError(), LookupError)
+ True
+
+ This class is actually a subclass of KeyError to provide backwards
+ compatibility with code relying on the undocumented behavior of earlier
+ pytz releases.
+
+ >>> isinstance(UnknownTimeZoneError(), KeyError)
+ True
+
+ And also a subclass of pytz.exceptions.Error, as are other pytz
+ exceptions.
+
+ >>> isinstance(UnknownTimeZoneError(), Error)
+ True
+
+ '''
+ pass
+
+
+class InvalidTimeError(Error):
+ '''Base class for invalid time exceptions.'''
+
+
+class AmbiguousTimeError(InvalidTimeError):
+ '''Exception raised when attempting to create an ambiguous wallclock time.
+
+ At the end of a DST transition period, a particular wallclock time will
+ occur twice (once before the clocks are set back, once after). Both
+ possibilities may be correct, unless further information is supplied.
+
+ See DstTzInfo.normalize() for more info
+ '''
+
+
+class NonExistentTimeError(InvalidTimeError):
+ '''Exception raised when attempting to create a wallclock time that
+ cannot exist.
+
+ At the start of a DST transition period, the wallclock time jumps forward.
+ The instants jumped over never occur.
+ '''
diff --git a/testcline/lib/python3.12/site-packages/pytz/lazy.py b/testcline/lib/python3.12/site-packages/pytz/lazy.py
new file mode 100644
index 0000000..39344fc
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/lazy.py
@@ -0,0 +1,172 @@
+from threading import RLock
+try:
+ from collections.abc import Mapping as DictMixin
+except ImportError: # Python < 3.3
+ try:
+ from UserDict import DictMixin # Python 2
+ except ImportError: # Python 3.0-3.3
+ from collections import Mapping as DictMixin
+
+
+# With lazy loading, we might end up with multiple threads triggering
+# it at the same time. We need a lock.
+_fill_lock = RLock()
+
+
+class LazyDict(DictMixin):
+ """Dictionary populated on first use."""
+ data = None
+
+ def __getitem__(self, key):
+ if self.data is None:
+ _fill_lock.acquire()
+ try:
+ if self.data is None:
+ self._fill()
+ finally:
+ _fill_lock.release()
+ return self.data[key.upper()]
+
+ def __contains__(self, key):
+ if self.data is None:
+ _fill_lock.acquire()
+ try:
+ if self.data is None:
+ self._fill()
+ finally:
+ _fill_lock.release()
+ return key in self.data
+
+ def __iter__(self):
+ if self.data is None:
+ _fill_lock.acquire()
+ try:
+ if self.data is None:
+ self._fill()
+ finally:
+ _fill_lock.release()
+ return iter(self.data)
+
+ def __len__(self):
+ if self.data is None:
+ _fill_lock.acquire()
+ try:
+ if self.data is None:
+ self._fill()
+ finally:
+ _fill_lock.release()
+ return len(self.data)
+
+ def keys(self):
+ if self.data is None:
+ _fill_lock.acquire()
+ try:
+ if self.data is None:
+ self._fill()
+ finally:
+ _fill_lock.release()
+ return self.data.keys()
+
+
+class LazyList(list):
+ """List populated on first use."""
+
+ _props = [
+ '__str__', '__repr__', '__unicode__',
+ '__hash__', '__sizeof__', '__cmp__',
+ '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__',
+ 'append', 'count', 'index', 'extend', 'insert', 'pop', 'remove',
+ 'reverse', 'sort', '__add__', '__radd__', '__iadd__', '__mul__',
+ '__rmul__', '__imul__', '__contains__', '__len__', '__nonzero__',
+ '__getitem__', '__setitem__', '__delitem__', '__iter__',
+ '__reversed__', '__getslice__', '__setslice__', '__delslice__']
+
+ def __new__(cls, fill_iter=None):
+
+ if fill_iter is None:
+ return list()
+
+ # We need a new class as we will be dynamically messing with its
+ # methods.
+ class LazyList(list):
+ pass
+
+ fill_iter = [fill_iter]
+
+ def lazy(name):
+ def _lazy(self, *args, **kw):
+ _fill_lock.acquire()
+ try:
+ if len(fill_iter) > 0:
+ list.extend(self, fill_iter.pop())
+ for method_name in cls._props:
+ delattr(LazyList, method_name)
+ finally:
+ _fill_lock.release()
+ return getattr(list, name)(self, *args, **kw)
+ return _lazy
+
+ for name in cls._props:
+ setattr(LazyList, name, lazy(name))
+
+ new_list = LazyList()
+ return new_list
+
+# Not all versions of Python declare the same magic methods.
+# Filter out properties that don't exist in this version of Python
+# from the list.
+LazyList._props = [prop for prop in LazyList._props if hasattr(list, prop)]
+
+
+class LazySet(set):
+ """Set populated on first use."""
+
+ _props = (
+ '__str__', '__repr__', '__unicode__',
+ '__hash__', '__sizeof__', '__cmp__',
+ '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__',
+ '__contains__', '__len__', '__nonzero__',
+ '__getitem__', '__setitem__', '__delitem__', '__iter__',
+ '__sub__', '__and__', '__xor__', '__or__',
+ '__rsub__', '__rand__', '__rxor__', '__ror__',
+ '__isub__', '__iand__', '__ixor__', '__ior__',
+ 'add', 'clear', 'copy', 'difference', 'difference_update',
+ 'discard', 'intersection', 'intersection_update', 'isdisjoint',
+ 'issubset', 'issuperset', 'pop', 'remove',
+ 'symmetric_difference', 'symmetric_difference_update',
+ 'union', 'update')
+
+ def __new__(cls, fill_iter=None):
+
+ if fill_iter is None:
+ return set()
+
+ class LazySet(set):
+ pass
+
+ fill_iter = [fill_iter]
+
+ def lazy(name):
+ def _lazy(self, *args, **kw):
+ _fill_lock.acquire()
+ try:
+ if len(fill_iter) > 0:
+ for i in fill_iter.pop():
+ set.add(self, i)
+ for method_name in cls._props:
+ delattr(LazySet, method_name)
+ finally:
+ _fill_lock.release()
+ return getattr(set, name)(self, *args, **kw)
+ return _lazy
+
+ for name in cls._props:
+ setattr(LazySet, name, lazy(name))
+
+ new_set = LazySet()
+ return new_set
+
+# Not all versions of Python declare the same magic methods.
+# Filter out properties that don't exist in this version of Python
+# from the list.
+LazySet._props = [prop for prop in LazySet._props if hasattr(set, prop)]
diff --git a/testcline/lib/python3.12/site-packages/pytz/reference.py b/testcline/lib/python3.12/site-packages/pytz/reference.py
new file mode 100644
index 0000000..f765ca0
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/reference.py
@@ -0,0 +1,140 @@
+'''
+Reference tzinfo implementations from the Python docs.
+Used for testing against as they are only correct for the years
+1987 to 2006. Do not use these for real code.
+'''
+
+from datetime import tzinfo, timedelta, datetime
+from pytz import HOUR, ZERO, UTC
+
+__all__ = [
+ 'FixedOffset',
+ 'LocalTimezone',
+ 'USTimeZone',
+ 'Eastern',
+ 'Central',
+ 'Mountain',
+ 'Pacific',
+ 'UTC'
+]
+
+
+# A class building tzinfo objects for fixed-offset time zones.
+# Note that FixedOffset(0, "UTC") is a different way to build a
+# UTC tzinfo object.
+class FixedOffset(tzinfo):
+ """Fixed offset in minutes east from UTC."""
+
+ def __init__(self, offset, name):
+ self.__offset = timedelta(minutes=offset)
+ self.__name = name
+
+ def utcoffset(self, dt):
+ return self.__offset
+
+ def tzname(self, dt):
+ return self.__name
+
+ def dst(self, dt):
+ return ZERO
+
+
+import time as _time
+
+STDOFFSET = timedelta(seconds=-_time.timezone)
+if _time.daylight:
+ DSTOFFSET = timedelta(seconds=-_time.altzone)
+else:
+ DSTOFFSET = STDOFFSET
+
+DSTDIFF = DSTOFFSET - STDOFFSET
+
+
+# A class capturing the platform's idea of local time.
+class LocalTimezone(tzinfo):
+
+ def utcoffset(self, dt):
+ if self._isdst(dt):
+ return DSTOFFSET
+ else:
+ return STDOFFSET
+
+ def dst(self, dt):
+ if self._isdst(dt):
+ return DSTDIFF
+ else:
+ return ZERO
+
+ def tzname(self, dt):
+ return _time.tzname[self._isdst(dt)]
+
+ def _isdst(self, dt):
+ tt = (dt.year, dt.month, dt.day,
+ dt.hour, dt.minute, dt.second,
+ dt.weekday(), 0, -1)
+ stamp = _time.mktime(tt)
+ tt = _time.localtime(stamp)
+ return tt.tm_isdst > 0
+
+Local = LocalTimezone()
+
+
+def first_sunday_on_or_after(dt):
+ days_to_go = 6 - dt.weekday()
+ if days_to_go:
+ dt += timedelta(days_to_go)
+ return dt
+
+
+# In the US, DST starts at 2am (standard time) on the first Sunday in April.
+DSTSTART = datetime(1, 4, 1, 2)
+# and ends at 2am (DST time; 1am standard time) on the last Sunday of Oct.
+# which is the first Sunday on or after Oct 25.
+DSTEND = datetime(1, 10, 25, 1)
+
+
+# A complete implementation of current DST rules for major US time zones.
+class USTimeZone(tzinfo):
+
+ def __init__(self, hours, reprname, stdname, dstname):
+ self.stdoffset = timedelta(hours=hours)
+ self.reprname = reprname
+ self.stdname = stdname
+ self.dstname = dstname
+
+ def __repr__(self):
+ return self.reprname
+
+ def tzname(self, dt):
+ if self.dst(dt):
+ return self.dstname
+ else:
+ return self.stdname
+
+ def utcoffset(self, dt):
+ return self.stdoffset + self.dst(dt)
+
+ def dst(self, dt):
+ if dt is None or dt.tzinfo is None:
+ # An exception may be sensible here, in one or both cases.
+ # It depends on how you want to treat them. The default
+ # fromutc() implementation (called by the default astimezone()
+ # implementation) passes a datetime with dt.tzinfo is self.
+ return ZERO
+ assert dt.tzinfo is self
+
+ # Find first Sunday in April & the last in October.
+ start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
+ end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))
+
+ # Can't compare naive to aware objects, so strip the timezone from
+ # dt first.
+ if start <= dt.replace(tzinfo=None) < end:
+ return HOUR
+ else:
+ return ZERO
+
+Eastern = USTimeZone(-5, "Eastern", "EST", "EDT")
+Central = USTimeZone(-6, "Central", "CST", "CDT")
+Mountain = USTimeZone(-7, "Mountain", "MST", "MDT")
+Pacific = USTimeZone(-8, "Pacific", "PST", "PDT")
diff --git a/testcline/lib/python3.12/site-packages/pytz/tzfile.py b/testcline/lib/python3.12/site-packages/pytz/tzfile.py
new file mode 100644
index 0000000..99e7448
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/tzfile.py
@@ -0,0 +1,133 @@
+'''
+$Id: tzfile.py,v 1.8 2004/06/03 00:15:24 zenzen Exp $
+'''
+
+from datetime import datetime
+from struct import unpack, calcsize
+
+from pytz.tzinfo import StaticTzInfo, DstTzInfo, memorized_ttinfo
+from pytz.tzinfo import memorized_datetime, memorized_timedelta
+
+
+def _byte_string(s):
+ """Cast a string or byte string to an ASCII byte string."""
+ return s.encode('ASCII')
+
+_NULL = _byte_string('\0')
+
+
+def _std_string(s):
+ """Cast a string or byte string to an ASCII string."""
+ return str(s.decode('ASCII'))
+
+
+def build_tzinfo(zone, fp):
+ head_fmt = '>4s c 15x 6l'
+ head_size = calcsize(head_fmt)
+ (magic, format, ttisgmtcnt, ttisstdcnt, leapcnt, timecnt,
+ typecnt, charcnt) = unpack(head_fmt, fp.read(head_size))
+
+ # Make sure it is a tzfile(5) file
+ assert magic == _byte_string('TZif'), 'Got magic %s' % repr(magic)
+
+ # Read out the transition times, localtime indices and ttinfo structures.
+ data_fmt = '>%(timecnt)dl %(timecnt)dB %(ttinfo)s %(charcnt)ds' % dict(
+ timecnt=timecnt, ttinfo='lBB' * typecnt, charcnt=charcnt)
+ data_size = calcsize(data_fmt)
+ data = unpack(data_fmt, fp.read(data_size))
+
+ # make sure we unpacked the right number of values
+ assert len(data) == 2 * timecnt + 3 * typecnt + 1
+ transitions = [memorized_datetime(trans)
+ for trans in data[:timecnt]]
+ lindexes = list(data[timecnt:2 * timecnt])
+ ttinfo_raw = data[2 * timecnt:-1]
+ tznames_raw = data[-1]
+ del data
+
+ # Process ttinfo into separate structs
+ ttinfo = []
+ tznames = {}
+ i = 0
+ while i < len(ttinfo_raw):
+ # have we looked up this timezone name yet?
+ tzname_offset = ttinfo_raw[i + 2]
+ if tzname_offset not in tznames:
+ nul = tznames_raw.find(_NULL, tzname_offset)
+ if nul < 0:
+ nul = len(tznames_raw)
+ tznames[tzname_offset] = _std_string(
+ tznames_raw[tzname_offset:nul])
+ ttinfo.append((ttinfo_raw[i],
+ bool(ttinfo_raw[i + 1]),
+ tznames[tzname_offset]))
+ i += 3
+
+ # Now build the timezone object
+ if len(ttinfo) == 1 or len(transitions) == 0:
+ ttinfo[0][0], ttinfo[0][2]
+ cls = type(zone, (StaticTzInfo,), dict(
+ zone=zone,
+ _utcoffset=memorized_timedelta(ttinfo[0][0]),
+ _tzname=ttinfo[0][2]))
+ else:
+ # Early dates use the first standard time ttinfo
+ i = 0
+ while ttinfo[i][1]:
+ i += 1
+ if ttinfo[i] == ttinfo[lindexes[0]]:
+ transitions[0] = datetime.min
+ else:
+ transitions.insert(0, datetime.min)
+ lindexes.insert(0, i)
+
+ # calculate transition info
+ transition_info = []
+ for i in range(len(transitions)):
+ inf = ttinfo[lindexes[i]]
+ utcoffset = inf[0]
+ if not inf[1]:
+ dst = 0
+ else:
+ for j in range(i - 1, -1, -1):
+ prev_inf = ttinfo[lindexes[j]]
+ if not prev_inf[1]:
+ break
+ dst = inf[0] - prev_inf[0] # dst offset
+
+ # Bad dst? Look further. DST > 24 hours happens when
+ # a timzone has moved across the international dateline.
+ if dst <= 0 or dst > 3600 * 3:
+ for j in range(i + 1, len(transitions)):
+ stdinf = ttinfo[lindexes[j]]
+ if not stdinf[1]:
+ dst = inf[0] - stdinf[0]
+ if dst > 0:
+ break # Found a useful std time.
+
+ tzname = inf[2]
+
+ # Round utcoffset and dst to the nearest minute or the
+ # datetime library will complain. Conversions to these timezones
+ # might be up to plus or minus 30 seconds out, but it is
+ # the best we can do.
+ utcoffset = int((utcoffset + 30) // 60) * 60
+ dst = int((dst + 30) // 60) * 60
+ transition_info.append(memorized_ttinfo(utcoffset, dst, tzname))
+
+ cls = type(zone, (DstTzInfo,), dict(
+ zone=zone,
+ _utc_transition_times=transitions,
+ _transition_info=transition_info))
+
+ return cls()
+
+if __name__ == '__main__':
+ import os.path
+ from pprint import pprint
+ base = os.path.join(os.path.dirname(__file__), 'zoneinfo')
+ tz = build_tzinfo('Australia/Melbourne',
+ open(os.path.join(base, 'Australia', 'Melbourne'), 'rb'))
+ tz = build_tzinfo('US/Eastern',
+ open(os.path.join(base, 'US', 'Eastern'), 'rb'))
+ pprint(tz._utc_transition_times)
diff --git a/testcline/lib/python3.12/site-packages/pytz/tzinfo.py b/testcline/lib/python3.12/site-packages/pytz/tzinfo.py
new file mode 100644
index 0000000..49b5c3f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/tzinfo.py
@@ -0,0 +1,580 @@
+'''Base classes and helpers for building zone specific tzinfo classes'''
+
+from datetime import datetime, timedelta, tzinfo
+from bisect import bisect_right
+try:
+ set
+except NameError:
+ from sets import Set as set
+
+import pytz
+from pytz.exceptions import AmbiguousTimeError, NonExistentTimeError
+
+__all__ = []
+
+_timedelta_cache = {}
+
+
+def memorized_timedelta(seconds):
+ '''Create only one instance of each distinct timedelta'''
+ try:
+ return _timedelta_cache[seconds]
+ except KeyError:
+ delta = timedelta(seconds=seconds)
+ _timedelta_cache[seconds] = delta
+ return delta
+
+
+_epoch = datetime(1970, 1, 1, 0, 0) # datetime.utcfromtimestamp(0)
+_datetime_cache = {0: _epoch}
+
+
+def memorized_datetime(seconds):
+ '''Create only one instance of each distinct datetime'''
+ try:
+ return _datetime_cache[seconds]
+ except KeyError:
+ # NB. We can't just do datetime.fromtimestamp(seconds, tz=timezone.utc).replace(tzinfo=None)
+ # as this fails with negative values under Windows (Bug #90096)
+ dt = _epoch + timedelta(seconds=seconds)
+ _datetime_cache[seconds] = dt
+ return dt
+
+
+_ttinfo_cache = {}
+
+
+def memorized_ttinfo(*args):
+ '''Create only one instance of each distinct tuple'''
+ try:
+ return _ttinfo_cache[args]
+ except KeyError:
+ ttinfo = (
+ memorized_timedelta(args[0]),
+ memorized_timedelta(args[1]),
+ args[2]
+ )
+ _ttinfo_cache[args] = ttinfo
+ return ttinfo
+
+
+_notime = memorized_timedelta(0)
+
+
+def _to_seconds(td):
+ '''Convert a timedelta to seconds'''
+ return td.seconds + td.days * 24 * 60 * 60
+
+
+class BaseTzInfo(tzinfo):
+ # Overridden in subclass
+ _utcoffset = None
+ _tzname = None
+ zone = None
+
+ def __str__(self):
+ return self.zone
+
+
+class StaticTzInfo(BaseTzInfo):
+ '''A timezone that has a constant offset from UTC
+
+ These timezones are rare, as most locations have changed their
+ offset at some point in their history
+ '''
+ def fromutc(self, dt):
+ '''See datetime.tzinfo.fromutc'''
+ if dt.tzinfo is not None and dt.tzinfo is not self:
+ raise ValueError('fromutc: dt.tzinfo is not self')
+ return (dt + self._utcoffset).replace(tzinfo=self)
+
+ def utcoffset(self, dt, is_dst=None):
+ '''See datetime.tzinfo.utcoffset
+
+ is_dst is ignored for StaticTzInfo, and exists only to
+ retain compatibility with DstTzInfo.
+ '''
+ return self._utcoffset
+
+ def dst(self, dt, is_dst=None):
+ '''See datetime.tzinfo.dst
+
+ is_dst is ignored for StaticTzInfo, and exists only to
+ retain compatibility with DstTzInfo.
+ '''
+ return _notime
+
+ def tzname(self, dt, is_dst=None):
+ '''See datetime.tzinfo.tzname
+
+ is_dst is ignored for StaticTzInfo, and exists only to
+ retain compatibility with DstTzInfo.
+ '''
+ return self._tzname
+
+ def localize(self, dt, is_dst=False):
+ '''Convert naive time to local time'''
+ if dt.tzinfo is not None:
+ raise ValueError('Not naive datetime (tzinfo is already set)')
+ return dt.replace(tzinfo=self)
+
+ def normalize(self, dt, is_dst=False):
+ '''Correct the timezone information on the given datetime.
+
+ This is normally a no-op, as StaticTzInfo timezones never have
+ ambiguous cases to correct:
+
+ >>> from pytz import timezone
+ >>> gmt = timezone('GMT')
+ >>> isinstance(gmt, StaticTzInfo)
+ True
+ >>> dt = datetime(2011, 5, 8, 1, 2, 3, tzinfo=gmt)
+ >>> gmt.normalize(dt) is dt
+ True
+
+ The supported method of converting between timezones is to use
+ datetime.astimezone(). Currently normalize() also works:
+
+ >>> la = timezone('America/Los_Angeles')
+ >>> dt = la.localize(datetime(2011, 5, 7, 1, 2, 3))
+ >>> fmt = '%Y-%m-%d %H:%M:%S %Z (%z)'
+ >>> gmt.normalize(dt).strftime(fmt)
+ '2011-05-07 08:02:03 GMT (+0000)'
+ '''
+ if dt.tzinfo is self:
+ return dt
+ if dt.tzinfo is None:
+ raise ValueError('Naive time - no tzinfo set')
+ return dt.astimezone(self)
+
+ def __repr__(self):
+ return '' % (self.zone,)
+
+ def __reduce__(self):
+ # Special pickle to zone remains a singleton and to cope with
+ # database changes.
+ return pytz._p, (self.zone,)
+
+
+class DstTzInfo(BaseTzInfo):
+ '''A timezone that has a variable offset from UTC
+
+ The offset might change if daylight saving time comes into effect,
+ or at a point in history when the region decides to change their
+ timezone definition.
+ '''
+ # Overridden in subclass
+
+ # Sorted list of DST transition times, UTC
+ _utc_transition_times = None
+
+ # [(utcoffset, dstoffset, tzname)] corresponding to
+ # _utc_transition_times entries
+ _transition_info = None
+
+ zone = None
+
+ # Set in __init__
+
+ _tzinfos = None
+ _dst = None # DST offset
+
+ def __init__(self, _inf=None, _tzinfos=None):
+ if _inf:
+ self._tzinfos = _tzinfos
+ self._utcoffset, self._dst, self._tzname = _inf
+ else:
+ _tzinfos = {}
+ self._tzinfos = _tzinfos
+ self._utcoffset, self._dst, self._tzname = (
+ self._transition_info[0])
+ _tzinfos[self._transition_info[0]] = self
+ for inf in self._transition_info[1:]:
+ if inf not in _tzinfos:
+ _tzinfos[inf] = self.__class__(inf, _tzinfos)
+
+ def fromutc(self, dt):
+ '''See datetime.tzinfo.fromutc'''
+ if (dt.tzinfo is not None and
+ getattr(dt.tzinfo, '_tzinfos', None) is not self._tzinfos):
+ raise ValueError('fromutc: dt.tzinfo is not self')
+ dt = dt.replace(tzinfo=None)
+ idx = max(0, bisect_right(self._utc_transition_times, dt) - 1)
+ inf = self._transition_info[idx]
+ return (dt + inf[0]).replace(tzinfo=self._tzinfos[inf])
+
+ def normalize(self, dt):
+ '''Correct the timezone information on the given datetime
+
+ If date arithmetic crosses DST boundaries, the tzinfo
+ is not magically adjusted. This method normalizes the
+ tzinfo to the correct one.
+
+ To test, first we need to do some setup
+
+ >>> from pytz import timezone
+ >>> utc = timezone('UTC')
+ >>> eastern = timezone('US/Eastern')
+ >>> fmt = '%Y-%m-%d %H:%M:%S %Z (%z)'
+
+ We next create a datetime right on an end-of-DST transition point,
+ the instant when the wallclocks are wound back one hour.
+
+ >>> utc_dt = datetime(2002, 10, 27, 6, 0, 0, tzinfo=utc)
+ >>> loc_dt = utc_dt.astimezone(eastern)
+ >>> loc_dt.strftime(fmt)
+ '2002-10-27 01:00:00 EST (-0500)'
+
+ Now, if we subtract a few minutes from it, note that the timezone
+ information has not changed.
+
+ >>> before = loc_dt - timedelta(minutes=10)
+ >>> before.strftime(fmt)
+ '2002-10-27 00:50:00 EST (-0500)'
+
+ But we can fix that by calling the normalize method
+
+ >>> before = eastern.normalize(before)
+ >>> before.strftime(fmt)
+ '2002-10-27 01:50:00 EDT (-0400)'
+
+ The supported method of converting between timezones is to use
+ datetime.astimezone(). Currently, normalize() also works:
+
+ >>> th = timezone('Asia/Bangkok')
+ >>> am = timezone('Europe/Amsterdam')
+ >>> dt = th.localize(datetime(2011, 5, 7, 1, 2, 3))
+ >>> fmt = '%Y-%m-%d %H:%M:%S %Z (%z)'
+ >>> am.normalize(dt).strftime(fmt)
+ '2011-05-06 20:02:03 CEST (+0200)'
+ '''
+ if dt.tzinfo is None:
+ raise ValueError('Naive time - no tzinfo set')
+
+ # Convert dt in localtime to UTC
+ offset = dt.tzinfo._utcoffset
+ dt = dt.replace(tzinfo=None)
+ dt = dt - offset
+ # convert it back, and return it
+ return self.fromutc(dt)
+
+ def localize(self, dt, is_dst=False):
+ '''Convert naive time to local time.
+
+ This method should be used to construct localtimes, rather
+ than passing a tzinfo argument to a datetime constructor.
+
+ is_dst is used to determine the correct timezone in the ambigous
+ period at the end of daylight saving time.
+
+ >>> from pytz import timezone
+ >>> fmt = '%Y-%m-%d %H:%M:%S %Z (%z)'
+ >>> amdam = timezone('Europe/Amsterdam')
+ >>> dt = datetime(2004, 10, 31, 2, 0, 0)
+ >>> loc_dt1 = amdam.localize(dt, is_dst=True)
+ >>> loc_dt2 = amdam.localize(dt, is_dst=False)
+ >>> loc_dt1.strftime(fmt)
+ '2004-10-31 02:00:00 CEST (+0200)'
+ >>> loc_dt2.strftime(fmt)
+ '2004-10-31 02:00:00 CET (+0100)'
+ >>> str(loc_dt2 - loc_dt1)
+ '1:00:00'
+
+ Use is_dst=None to raise an AmbiguousTimeError for ambiguous
+ times at the end of daylight saving time
+
+ >>> try:
+ ... loc_dt1 = amdam.localize(dt, is_dst=None)
+ ... except AmbiguousTimeError:
+ ... print('Ambiguous')
+ Ambiguous
+
+ is_dst defaults to False
+
+ >>> amdam.localize(dt) == amdam.localize(dt, False)
+ True
+
+ is_dst is also used to determine the correct timezone in the
+ wallclock times jumped over at the start of daylight saving time.
+
+ >>> pacific = timezone('US/Pacific')
+ >>> dt = datetime(2008, 3, 9, 2, 0, 0)
+ >>> ploc_dt1 = pacific.localize(dt, is_dst=True)
+ >>> ploc_dt2 = pacific.localize(dt, is_dst=False)
+ >>> ploc_dt1.strftime(fmt)
+ '2008-03-09 02:00:00 PDT (-0700)'
+ >>> ploc_dt2.strftime(fmt)
+ '2008-03-09 02:00:00 PST (-0800)'
+ >>> str(ploc_dt2 - ploc_dt1)
+ '1:00:00'
+
+ Use is_dst=None to raise a NonExistentTimeError for these skipped
+ times.
+
+ >>> try:
+ ... loc_dt1 = pacific.localize(dt, is_dst=None)
+ ... except NonExistentTimeError:
+ ... print('Non-existent')
+ Non-existent
+ '''
+ if dt.tzinfo is not None:
+ raise ValueError('Not naive datetime (tzinfo is already set)')
+
+ # Find the two best possibilities.
+ possible_loc_dt = set()
+ for delta in [timedelta(days=-1), timedelta(days=1)]:
+ loc_dt = dt + delta
+ idx = max(0, bisect_right(
+ self._utc_transition_times, loc_dt) - 1)
+ inf = self._transition_info[idx]
+ tzinfo = self._tzinfos[inf]
+ loc_dt = tzinfo.normalize(dt.replace(tzinfo=tzinfo))
+ if loc_dt.replace(tzinfo=None) == dt:
+ possible_loc_dt.add(loc_dt)
+
+ if len(possible_loc_dt) == 1:
+ return possible_loc_dt.pop()
+
+ # If there are no possibly correct timezones, we are attempting
+ # to convert a time that never happened - the time period jumped
+ # during the start-of-DST transition period.
+ if len(possible_loc_dt) == 0:
+ # If we refuse to guess, raise an exception.
+ if is_dst is None:
+ raise NonExistentTimeError(dt)
+
+ # If we are forcing the pre-DST side of the DST transition, we
+ # obtain the correct timezone by winding the clock forward a few
+ # hours.
+ elif is_dst:
+ return self.localize(
+ dt + timedelta(hours=6), is_dst=True) - timedelta(hours=6)
+
+ # If we are forcing the post-DST side of the DST transition, we
+ # obtain the correct timezone by winding the clock back.
+ else:
+ return self.localize(
+ dt - timedelta(hours=6),
+ is_dst=False) + timedelta(hours=6)
+
+ # If we get this far, we have multiple possible timezones - this
+ # is an ambiguous case occurring during the end-of-DST transition.
+
+ # If told to be strict, raise an exception since we have an
+ # ambiguous case
+ if is_dst is None:
+ raise AmbiguousTimeError(dt)
+
+ # Filter out the possiblilities that don't match the requested
+ # is_dst
+ filtered_possible_loc_dt = [
+ p for p in possible_loc_dt if bool(p.tzinfo._dst) == is_dst
+ ]
+
+ # Hopefully we only have one possibility left. Return it.
+ if len(filtered_possible_loc_dt) == 1:
+ return filtered_possible_loc_dt[0]
+
+ if len(filtered_possible_loc_dt) == 0:
+ filtered_possible_loc_dt = list(possible_loc_dt)
+
+ # If we get this far, we have in a wierd timezone transition
+ # where the clocks have been wound back but is_dst is the same
+ # in both (eg. Europe/Warsaw 1915 when they switched to CET).
+ # At this point, we just have to guess unless we allow more
+ # hints to be passed in (such as the UTC offset or abbreviation),
+ # but that is just getting silly.
+ #
+ # Choose the earliest (by UTC) applicable timezone if is_dst=True
+ # Choose the latest (by UTC) applicable timezone if is_dst=False
+ # i.e., behave like end-of-DST transition
+ dates = {} # utc -> local
+ for local_dt in filtered_possible_loc_dt:
+ utc_time = (
+ local_dt.replace(tzinfo=None) - local_dt.tzinfo._utcoffset)
+ assert utc_time not in dates
+ dates[utc_time] = local_dt
+ return dates[[min, max][not is_dst](dates)]
+
+ def utcoffset(self, dt, is_dst=None):
+ '''See datetime.tzinfo.utcoffset
+
+ The is_dst parameter may be used to remove ambiguity during DST
+ transitions.
+
+ >>> from pytz import timezone
+ >>> tz = timezone('America/St_Johns')
+ >>> ambiguous = datetime(2009, 10, 31, 23, 30)
+
+ >>> str(tz.utcoffset(ambiguous, is_dst=False))
+ '-1 day, 20:30:00'
+
+ >>> str(tz.utcoffset(ambiguous, is_dst=True))
+ '-1 day, 21:30:00'
+
+ >>> try:
+ ... tz.utcoffset(ambiguous)
+ ... except AmbiguousTimeError:
+ ... print('Ambiguous')
+ Ambiguous
+
+ '''
+ if dt is None:
+ return None
+ elif dt.tzinfo is not self:
+ dt = self.localize(dt, is_dst)
+ return dt.tzinfo._utcoffset
+ else:
+ return self._utcoffset
+
+ def dst(self, dt, is_dst=None):
+ '''See datetime.tzinfo.dst
+
+ The is_dst parameter may be used to remove ambiguity during DST
+ transitions.
+
+ >>> from pytz import timezone
+ >>> tz = timezone('America/St_Johns')
+
+ >>> normal = datetime(2009, 9, 1)
+
+ >>> str(tz.dst(normal))
+ '1:00:00'
+ >>> str(tz.dst(normal, is_dst=False))
+ '1:00:00'
+ >>> str(tz.dst(normal, is_dst=True))
+ '1:00:00'
+
+ >>> ambiguous = datetime(2009, 10, 31, 23, 30)
+
+ >>> str(tz.dst(ambiguous, is_dst=False))
+ '0:00:00'
+ >>> str(tz.dst(ambiguous, is_dst=True))
+ '1:00:00'
+ >>> try:
+ ... tz.dst(ambiguous)
+ ... except AmbiguousTimeError:
+ ... print('Ambiguous')
+ Ambiguous
+
+ '''
+ if dt is None:
+ return None
+ elif dt.tzinfo is not self:
+ dt = self.localize(dt, is_dst)
+ return dt.tzinfo._dst
+ else:
+ return self._dst
+
+ def tzname(self, dt, is_dst=None):
+ '''See datetime.tzinfo.tzname
+
+ The is_dst parameter may be used to remove ambiguity during DST
+ transitions.
+
+ >>> from pytz import timezone
+ >>> tz = timezone('America/St_Johns')
+
+ >>> normal = datetime(2009, 9, 1)
+
+ >>> tz.tzname(normal)
+ 'NDT'
+ >>> tz.tzname(normal, is_dst=False)
+ 'NDT'
+ >>> tz.tzname(normal, is_dst=True)
+ 'NDT'
+
+ >>> ambiguous = datetime(2009, 10, 31, 23, 30)
+
+ >>> tz.tzname(ambiguous, is_dst=False)
+ 'NST'
+ >>> tz.tzname(ambiguous, is_dst=True)
+ 'NDT'
+ >>> try:
+ ... tz.tzname(ambiguous)
+ ... except AmbiguousTimeError:
+ ... print('Ambiguous')
+ Ambiguous
+ '''
+ if dt is None:
+ return self.zone
+ elif dt.tzinfo is not self:
+ dt = self.localize(dt, is_dst)
+ return dt.tzinfo._tzname
+ else:
+ return self._tzname
+
+ def __repr__(self):
+ if self._dst:
+ dst = 'DST'
+ else:
+ dst = 'STD'
+ if self._utcoffset > _notime:
+ return '' % (
+ self.zone, self._tzname, self._utcoffset, dst
+ )
+ else:
+ return '' % (
+ self.zone, self._tzname, self._utcoffset, dst
+ )
+
+ def __reduce__(self):
+ # Special pickle to zone remains a singleton and to cope with
+ # database changes.
+ return pytz._p, (
+ self.zone,
+ _to_seconds(self._utcoffset),
+ _to_seconds(self._dst),
+ self._tzname
+ )
+
+
+def unpickler(zone, utcoffset=None, dstoffset=None, tzname=None):
+ """Factory function for unpickling pytz tzinfo instances.
+
+ This is shared for both StaticTzInfo and DstTzInfo instances, because
+ database changes could cause a zones implementation to switch between
+ these two base classes and we can't break pickles on a pytz version
+ upgrade.
+ """
+ # Raises a KeyError if zone no longer exists, which should never happen
+ # and would be a bug.
+ tz = pytz.timezone(zone)
+
+ # A StaticTzInfo - just return it
+ if utcoffset is None:
+ return tz
+
+ # This pickle was created from a DstTzInfo. We need to
+ # determine which of the list of tzinfo instances for this zone
+ # to use in order to restore the state of any datetime instances using
+ # it correctly.
+ utcoffset = memorized_timedelta(utcoffset)
+ dstoffset = memorized_timedelta(dstoffset)
+ try:
+ return tz._tzinfos[(utcoffset, dstoffset, tzname)]
+ except KeyError:
+ # The particular state requested in this timezone no longer exists.
+ # This indicates a corrupt pickle, or the timezone database has been
+ # corrected violently enough to make this particular
+ # (utcoffset,dstoffset) no longer exist in the zone, or the
+ # abbreviation has been changed.
+ pass
+
+ # See if we can find an entry differing only by tzname. Abbreviations
+ # get changed from the initial guess by the database maintainers to
+ # match reality when this information is discovered.
+ for localized_tz in tz._tzinfos.values():
+ if (localized_tz._utcoffset == utcoffset and
+ localized_tz._dst == dstoffset):
+ return localized_tz
+
+ # This (utcoffset, dstoffset) information has been removed from the
+ # zone. Add it back. This might occur when the database maintainers have
+ # corrected incorrect information. datetime instances using this
+ # incorrect information will continue to do so, exactly as they were
+ # before being pickled. This is purely an overly paranoid safety net - I
+ # doubt this will ever been needed in real life.
+ inf = (utcoffset, dstoffset, tzname)
+ tz._tzinfos[inf] = tz.__class__(inf, tz._tzinfos)
+ return tz._tzinfos[inf]
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Abidjan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Abidjan
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Abidjan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Accra b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Accra
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Accra differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Addis_Ababa b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Addis_Ababa
new file mode 100644
index 0000000..9dcfc19
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Addis_Ababa differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Algiers b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Algiers
new file mode 100644
index 0000000..6cfd8a1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Algiers differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Asmara b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Asmara
new file mode 100644
index 0000000..9dcfc19
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Asmara differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Asmera b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Asmera
new file mode 100644
index 0000000..9dcfc19
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Asmera differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bamako b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bamako
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bamako differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bangui b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bangui
new file mode 100644
index 0000000..afb6a4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bangui differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Banjul b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Banjul
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Banjul differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bissau b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bissau
new file mode 100644
index 0000000..82ea5aa
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bissau differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Blantyre b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Blantyre
new file mode 100644
index 0000000..65f043f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Blantyre differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Brazzaville b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Brazzaville
new file mode 100644
index 0000000..afb6a4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Brazzaville differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bujumbura b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bujumbura
new file mode 100644
index 0000000..65f043f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Bujumbura differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Cairo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Cairo
new file mode 100644
index 0000000..dd538c6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Cairo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Casablanca b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Casablanca
new file mode 100644
index 0000000..d39016b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Casablanca differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Ceuta b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Ceuta
new file mode 100644
index 0000000..b41ec4f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Ceuta differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Conakry b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Conakry
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Conakry differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Dakar b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Dakar
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Dakar differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Dar_es_Salaam b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Dar_es_Salaam
new file mode 100644
index 0000000..9dcfc19
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Dar_es_Salaam differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Djibouti b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Djibouti
new file mode 100644
index 0000000..9dcfc19
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Djibouti differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Douala b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Douala
new file mode 100644
index 0000000..afb6a4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Douala differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/El_Aaiun b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/El_Aaiun
new file mode 100644
index 0000000..066fbed
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/El_Aaiun differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Freetown b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Freetown
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Freetown differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Gaborone b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Gaborone
new file mode 100644
index 0000000..65f043f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Gaborone differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Harare b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Harare
new file mode 100644
index 0000000..65f043f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Harare differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Johannesburg b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Johannesburg
new file mode 100644
index 0000000..b1c425d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Johannesburg differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Juba b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Juba
new file mode 100644
index 0000000..0648294
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Juba differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Kampala b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Kampala
new file mode 100644
index 0000000..9dcfc19
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Kampala differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Khartoum b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Khartoum
new file mode 100644
index 0000000..8ee8cb9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Khartoum differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Kigali b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Kigali
new file mode 100644
index 0000000..65f043f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Kigali differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Kinshasa b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Kinshasa
new file mode 100644
index 0000000..afb6a4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Kinshasa differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lagos b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lagos
new file mode 100644
index 0000000..afb6a4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lagos differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Libreville b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Libreville
new file mode 100644
index 0000000..afb6a4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Libreville differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lome b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lome
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lome differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Luanda b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Luanda
new file mode 100644
index 0000000..afb6a4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Luanda differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lubumbashi b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lubumbashi
new file mode 100644
index 0000000..65f043f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lubumbashi differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lusaka b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lusaka
new file mode 100644
index 0000000..65f043f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Lusaka differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Malabo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Malabo
new file mode 100644
index 0000000..afb6a4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Malabo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Maputo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Maputo
new file mode 100644
index 0000000..65f043f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Maputo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Maseru b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Maseru
new file mode 100644
index 0000000..b1c425d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Maseru differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Mbabane b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Mbabane
new file mode 100644
index 0000000..b1c425d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Mbabane differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Mogadishu b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Mogadishu
new file mode 100644
index 0000000..9dcfc19
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Mogadishu differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Monrovia b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Monrovia
new file mode 100644
index 0000000..6d68850
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Monrovia differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Nairobi b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Nairobi
new file mode 100644
index 0000000..9dcfc19
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Nairobi differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Ndjamena b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Ndjamena
new file mode 100644
index 0000000..a968845
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Ndjamena differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Niamey b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Niamey
new file mode 100644
index 0000000..afb6a4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Niamey differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Nouakchott b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Nouakchott
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Nouakchott differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Ouagadougou b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Ouagadougou
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Ouagadougou differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Porto-Novo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Porto-Novo
new file mode 100644
index 0000000..afb6a4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Porto-Novo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Sao_Tome b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Sao_Tome
new file mode 100644
index 0000000..59f3759
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Sao_Tome differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Timbuktu b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Timbuktu
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Timbuktu differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Tripoli b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Tripoli
new file mode 100644
index 0000000..07b393b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Tripoli differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Tunis b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Tunis
new file mode 100644
index 0000000..427fa56
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Tunis differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Windhoek b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Windhoek
new file mode 100644
index 0000000..abecd13
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Africa/Windhoek differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Adak b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Adak
new file mode 100644
index 0000000..4323649
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Adak differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Anchorage b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Anchorage
new file mode 100644
index 0000000..9bbb2fd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Anchorage differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Anguilla b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Anguilla
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Anguilla differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Antigua b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Antigua
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Antigua differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Araguaina b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Araguaina
new file mode 100644
index 0000000..919723d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Araguaina differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Buenos_Aires b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Buenos_Aires
new file mode 100644
index 0000000..cc82e69
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Buenos_Aires differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Catamarca b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Catamarca
new file mode 100644
index 0000000..7268eb3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Catamarca differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/ComodRivadavia b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/ComodRivadavia
new file mode 100644
index 0000000..7268eb3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/ComodRivadavia differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Cordoba b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Cordoba
new file mode 100644
index 0000000..2ad6ea5
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Cordoba differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Jujuy b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Jujuy
new file mode 100644
index 0000000..7ca0b46
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Jujuy differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/La_Rioja b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/La_Rioja
new file mode 100644
index 0000000..a6a6694
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/La_Rioja differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Mendoza b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Mendoza
new file mode 100644
index 0000000..3232c80
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Mendoza differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Rio_Gallegos b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Rio_Gallegos
new file mode 100644
index 0000000..8b1a281
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Rio_Gallegos differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Salta b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Salta
new file mode 100644
index 0000000..7072dec
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Salta differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/San_Juan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/San_Juan
new file mode 100644
index 0000000..f3e185c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/San_Juan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/San_Luis b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/San_Luis
new file mode 100644
index 0000000..2d1da3a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/San_Luis differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Tucuman b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Tucuman
new file mode 100644
index 0000000..c6449f5
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Tucuman differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Ushuaia b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Ushuaia
new file mode 100644
index 0000000..e74ce04
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Argentina/Ushuaia differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Aruba b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Aruba
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Aruba differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Asuncion b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Asuncion
new file mode 100644
index 0000000..9b07a80
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Asuncion differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Atikokan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Atikokan
new file mode 100644
index 0000000..9964b9a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Atikokan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Atka b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Atka
new file mode 100644
index 0000000..4323649
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Atka differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Bahia b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Bahia
new file mode 100644
index 0000000..0b65e49
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Bahia differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Bahia_Banderas b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Bahia_Banderas
new file mode 100644
index 0000000..3a493e3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Bahia_Banderas differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Barbados b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Barbados
new file mode 100644
index 0000000..00cd045
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Barbados differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Belem b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Belem
new file mode 100644
index 0000000..0ae1202
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Belem differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Belize b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Belize
new file mode 100644
index 0000000..e6f5dfa
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Belize differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Blanc-Sablon b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Blanc-Sablon
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Blanc-Sablon differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Boa_Vista b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Boa_Vista
new file mode 100644
index 0000000..08d518b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Boa_Vista differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Bogota b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Bogota
new file mode 100644
index 0000000..331a1b7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Bogota differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Boise b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Boise
new file mode 100644
index 0000000..aad1d99
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Boise differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Buenos_Aires b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Buenos_Aires
new file mode 100644
index 0000000..cc82e69
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Buenos_Aires differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cambridge_Bay b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cambridge_Bay
new file mode 100644
index 0000000..7e58a20
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cambridge_Bay differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Campo_Grande b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Campo_Grande
new file mode 100644
index 0000000..53b3330
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Campo_Grande differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cancun b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cancun
new file mode 100644
index 0000000..0f7771e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cancun differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Caracas b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Caracas
new file mode 100644
index 0000000..3f3ebc9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Caracas differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Catamarca b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Catamarca
new file mode 100644
index 0000000..7268eb3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Catamarca differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cayenne b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cayenne
new file mode 100644
index 0000000..e898594
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cayenne differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cayman b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cayman
new file mode 100644
index 0000000..9964b9a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cayman differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Chicago b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Chicago
new file mode 100644
index 0000000..c6981a0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Chicago differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Chihuahua b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Chihuahua
new file mode 100644
index 0000000..667a219
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Chihuahua differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Ciudad_Juarez b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Ciudad_Juarez
new file mode 100644
index 0000000..29af598
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Ciudad_Juarez differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Coral_Harbour b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Coral_Harbour
new file mode 100644
index 0000000..9964b9a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Coral_Harbour differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cordoba b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cordoba
new file mode 100644
index 0000000..2ad6ea5
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cordoba differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Costa_Rica b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Costa_Rica
new file mode 100644
index 0000000..37cb85e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Costa_Rica differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Coyhaique b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Coyhaique
new file mode 100644
index 0000000..e0c6832
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Coyhaique differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Creston b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Creston
new file mode 100644
index 0000000..ab37e84
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Creston differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cuiaba b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cuiaba
new file mode 100644
index 0000000..26e97f6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Cuiaba differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Curacao b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Curacao
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Curacao differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Danmarkshavn b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Danmarkshavn
new file mode 100644
index 0000000..9549adc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Danmarkshavn differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Dawson b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Dawson
new file mode 100644
index 0000000..343b632
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Dawson differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Dawson_Creek b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Dawson_Creek
new file mode 100644
index 0000000..db9e339
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Dawson_Creek differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Denver b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Denver
new file mode 100644
index 0000000..abb2b97
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Denver differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Detroit b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Detroit
new file mode 100644
index 0000000..e104faa
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Detroit differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Dominica b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Dominica
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Dominica differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Edmonton b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Edmonton
new file mode 100644
index 0000000..cd78a6f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Edmonton differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Eirunepe b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Eirunepe
new file mode 100644
index 0000000..d4c46e3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Eirunepe differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/El_Salvador b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/El_Salvador
new file mode 100644
index 0000000..e2f2230
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/El_Salvador differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Ensenada b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Ensenada
new file mode 100644
index 0000000..0fe7391
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Ensenada differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Fort_Nelson b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Fort_Nelson
new file mode 100644
index 0000000..5a0b7f1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Fort_Nelson differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Fort_Wayne b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Fort_Wayne
new file mode 100644
index 0000000..a84b6e9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Fort_Wayne differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Fortaleza b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Fortaleza
new file mode 100644
index 0000000..bee1a95
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Fortaleza differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Glace_Bay b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Glace_Bay
new file mode 100644
index 0000000..48412a4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Glace_Bay differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Godthab b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Godthab
new file mode 100644
index 0000000..29958cf
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Godthab differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Goose_Bay b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Goose_Bay
new file mode 100644
index 0000000..a3f2990
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Goose_Bay differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Grand_Turk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Grand_Turk
new file mode 100644
index 0000000..06da1a6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Grand_Turk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Grenada b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Grenada
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Grenada differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guadeloupe b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guadeloupe
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guadeloupe differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guatemala b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guatemala
new file mode 100644
index 0000000..407138c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guatemala differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guayaquil b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guayaquil
new file mode 100644
index 0000000..40831be
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guayaquil differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guyana b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guyana
new file mode 100644
index 0000000..9b70367
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Guyana differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Halifax b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Halifax
new file mode 100644
index 0000000..756099a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Halifax differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Havana b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Havana
new file mode 100644
index 0000000..b69ac45
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Havana differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Hermosillo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Hermosillo
new file mode 100644
index 0000000..441fe3f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Hermosillo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Indianapolis b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Indianapolis
new file mode 100644
index 0000000..a84b6e9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Indianapolis differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Knox b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Knox
new file mode 100644
index 0000000..025d132
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Knox differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Marengo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Marengo
new file mode 100644
index 0000000..677bbff
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Marengo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Petersburg b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Petersburg
new file mode 100644
index 0000000..3082de0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Petersburg differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Tell_City b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Tell_City
new file mode 100644
index 0000000..103c5cb
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Tell_City differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Vevay b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Vevay
new file mode 100644
index 0000000..315b4c4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Vevay differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Vincennes b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Vincennes
new file mode 100644
index 0000000..35a2413
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Vincennes differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Winamac b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Winamac
new file mode 100644
index 0000000..6d4e193
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indiana/Winamac differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indianapolis b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indianapolis
new file mode 100644
index 0000000..a84b6e9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Indianapolis differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Inuvik b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Inuvik
new file mode 100644
index 0000000..04c2df4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Inuvik differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Iqaluit b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Iqaluit
new file mode 100644
index 0000000..0b47b90
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Iqaluit differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Jamaica b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Jamaica
new file mode 100644
index 0000000..2a9b7fd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Jamaica differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Jujuy b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Jujuy
new file mode 100644
index 0000000..7ca0b46
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Jujuy differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Juneau b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Juneau
new file mode 100644
index 0000000..451f349
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Juneau differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Kentucky/Louisville b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Kentucky/Louisville
new file mode 100644
index 0000000..3a335b3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Kentucky/Louisville differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Kentucky/Monticello b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Kentucky/Monticello
new file mode 100644
index 0000000..576f16b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Kentucky/Monticello differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Knox_IN b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Knox_IN
new file mode 100644
index 0000000..025d132
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Knox_IN differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Kralendijk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Kralendijk
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Kralendijk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/La_Paz b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/La_Paz
new file mode 100644
index 0000000..374586e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/La_Paz differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Lima b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Lima
new file mode 100644
index 0000000..c13bb6b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Lima differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Los_Angeles b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Los_Angeles
new file mode 100644
index 0000000..610e7af
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Los_Angeles differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Louisville b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Louisville
new file mode 100644
index 0000000..3a335b3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Louisville differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Lower_Princes b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Lower_Princes
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Lower_Princes differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Maceio b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Maceio
new file mode 100644
index 0000000..437a473
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Maceio differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Managua b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Managua
new file mode 100644
index 0000000..e0242bf
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Managua differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Manaus b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Manaus
new file mode 100644
index 0000000..2708bae
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Manaus differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Marigot b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Marigot
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Marigot differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Martinique b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Martinique
new file mode 100644
index 0000000..8df43dc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Martinique differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Matamoros b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Matamoros
new file mode 100644
index 0000000..bbe04e8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Matamoros differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Mazatlan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Mazatlan
new file mode 100644
index 0000000..386616a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Mazatlan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Mendoza b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Mendoza
new file mode 100644
index 0000000..3232c80
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Mendoza differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Menominee b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Menominee
new file mode 100644
index 0000000..3146138
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Menominee differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Merida b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Merida
new file mode 100644
index 0000000..c4b9b4e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Merida differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Metlakatla b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Metlakatla
new file mode 100644
index 0000000..1e94be3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Metlakatla differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Mexico_City b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Mexico_City
new file mode 100644
index 0000000..ad70cf3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Mexico_City differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Miquelon b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Miquelon
new file mode 100644
index 0000000..f780ea9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Miquelon differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Moncton b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Moncton
new file mode 100644
index 0000000..9df8d0f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Moncton differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Monterrey b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Monterrey
new file mode 100644
index 0000000..2d7993a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Monterrey differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Montevideo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Montevideo
new file mode 100644
index 0000000..e7bbfbb
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Montevideo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Montreal b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Montreal
new file mode 100644
index 0000000..1701373
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Montreal differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Montserrat b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Montserrat
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Montserrat differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nassau b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nassau
new file mode 100644
index 0000000..1701373
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nassau differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/New_York b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/New_York
new file mode 100644
index 0000000..a8b9ab1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/New_York differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nipigon b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nipigon
new file mode 100644
index 0000000..1701373
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nipigon differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nome b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nome
new file mode 100644
index 0000000..10998df
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nome differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Noronha b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Noronha
new file mode 100644
index 0000000..73b4b33
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Noronha differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/North_Dakota/Beulah b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/North_Dakota/Beulah
new file mode 100644
index 0000000..33e317e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/North_Dakota/Beulah differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/North_Dakota/Center b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/North_Dakota/Center
new file mode 100644
index 0000000..17fe13b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/North_Dakota/Center differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/North_Dakota/New_Salem b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/North_Dakota/New_Salem
new file mode 100644
index 0000000..12dbe80
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/North_Dakota/New_Salem differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nuuk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nuuk
new file mode 100644
index 0000000..29958cf
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Nuuk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Ojinaga b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Ojinaga
new file mode 100644
index 0000000..45118a4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Ojinaga differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Panama b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Panama
new file mode 100644
index 0000000..9964b9a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Panama differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Pangnirtung b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Pangnirtung
new file mode 100644
index 0000000..0b47b90
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Pangnirtung differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Paramaribo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Paramaribo
new file mode 100644
index 0000000..f1b82b4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Paramaribo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Phoenix b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Phoenix
new file mode 100644
index 0000000..ab37e84
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Phoenix differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Port-au-Prince b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Port-au-Prince
new file mode 100644
index 0000000..287f143
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Port-au-Prince differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Port_of_Spain b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Port_of_Spain
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Port_of_Spain differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Porto_Acre b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Porto_Acre
new file mode 100644
index 0000000..cdda168
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Porto_Acre differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Porto_Velho b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Porto_Velho
new file mode 100644
index 0000000..e003986
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Porto_Velho differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Puerto_Rico b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Puerto_Rico
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Puerto_Rico differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Punta_Arenas b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Punta_Arenas
new file mode 100644
index 0000000..411a839
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Punta_Arenas differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rainy_River b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rainy_River
new file mode 100644
index 0000000..ac40299
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rainy_River differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rankin_Inlet b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rankin_Inlet
new file mode 100644
index 0000000..e271492
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rankin_Inlet differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Recife b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Recife
new file mode 100644
index 0000000..5bf6c21
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Recife differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Regina b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Regina
new file mode 100644
index 0000000..20c9c84
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Regina differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Resolute b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Resolute
new file mode 100644
index 0000000..1966890
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Resolute differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rio_Branco b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rio_Branco
new file mode 100644
index 0000000..cdda168
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rio_Branco differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rosario b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rosario
new file mode 100644
index 0000000..2ad6ea5
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Rosario differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santa_Isabel b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santa_Isabel
new file mode 100644
index 0000000..0fe7391
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santa_Isabel differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santarem b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santarem
new file mode 100644
index 0000000..001638c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santarem differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santiago b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santiago
new file mode 100644
index 0000000..010c6bd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santiago differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santo_Domingo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santo_Domingo
new file mode 100644
index 0000000..4fe36fd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Santo_Domingo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Sao_Paulo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Sao_Paulo
new file mode 100644
index 0000000..67935ff
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Sao_Paulo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Scoresbysund b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Scoresbysund
new file mode 100644
index 0000000..9bf411e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Scoresbysund differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Shiprock b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Shiprock
new file mode 100644
index 0000000..abb2b97
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Shiprock differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Sitka b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Sitka
new file mode 100644
index 0000000..31f7061
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Sitka differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Barthelemy b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Barthelemy
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Barthelemy differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Johns b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Johns
new file mode 100644
index 0000000..65a5b0c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Johns differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Kitts b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Kitts
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Kitts differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Lucia b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Lucia
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Lucia differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Thomas b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Thomas
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Thomas differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Vincent b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Vincent
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/St_Vincent differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Swift_Current b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Swift_Current
new file mode 100644
index 0000000..8e9ef25
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Swift_Current differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Tegucigalpa b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Tegucigalpa
new file mode 100644
index 0000000..2adacb2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Tegucigalpa differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Thule b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Thule
new file mode 100644
index 0000000..6f802f1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Thule differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Thunder_Bay b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Thunder_Bay
new file mode 100644
index 0000000..1701373
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Thunder_Bay differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Tijuana b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Tijuana
new file mode 100644
index 0000000..0fe7391
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Tijuana differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Toronto b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Toronto
new file mode 100644
index 0000000..1701373
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Toronto differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Tortola b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Tortola
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Tortola differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Vancouver b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Vancouver
new file mode 100644
index 0000000..bb60cbc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Vancouver differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Virgin b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Virgin
new file mode 100644
index 0000000..a662a57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Virgin differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Whitehorse b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Whitehorse
new file mode 100644
index 0000000..318c4a8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Whitehorse differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Winnipeg b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Winnipeg
new file mode 100644
index 0000000..ac40299
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Winnipeg differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Yakutat b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Yakutat
new file mode 100644
index 0000000..da209f9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Yakutat differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Yellowknife b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Yellowknife
new file mode 100644
index 0000000..cd78a6f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/America/Yellowknife differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Casey b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Casey
new file mode 100644
index 0000000..586a765
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Casey differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Davis b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Davis
new file mode 100644
index 0000000..d4d47b2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Davis differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/DumontDUrville b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/DumontDUrville
new file mode 100644
index 0000000..7be2474
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/DumontDUrville differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Macquarie b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Macquarie
new file mode 100644
index 0000000..9e7cc68
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Macquarie differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Mawson b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Mawson
new file mode 100644
index 0000000..6d93f6e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Mawson differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/McMurdo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/McMurdo
new file mode 100644
index 0000000..6575fdc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/McMurdo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Palmer b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Palmer
new file mode 100644
index 0000000..9c8fd31
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Palmer differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Rothera b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Rothera
new file mode 100644
index 0000000..241cc44
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Rothera differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/South_Pole b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/South_Pole
new file mode 100644
index 0000000..6575fdc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/South_Pole differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Syowa b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Syowa
new file mode 100644
index 0000000..8c80624
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Syowa differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Troll b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Troll
new file mode 100644
index 0000000..a1dcea1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Troll differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Vostok b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Vostok
new file mode 100644
index 0000000..016e06b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Antarctica/Vostok differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Arctic/Longyearbyen b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Arctic/Longyearbyen
new file mode 100644
index 0000000..7f6d958
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Arctic/Longyearbyen differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Aden b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Aden
new file mode 100644
index 0000000..8c80624
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Aden differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Almaty b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Almaty
new file mode 100644
index 0000000..855abbd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Almaty differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Amman b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Amman
new file mode 100644
index 0000000..0a8e350
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Amman differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Anadyr b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Anadyr
new file mode 100644
index 0000000..35c531c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Anadyr differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Aqtau b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Aqtau
new file mode 100644
index 0000000..0e1c16d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Aqtau differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Aqtobe b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Aqtobe
new file mode 100644
index 0000000..3b5d6eb
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Aqtobe differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ashgabat b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ashgabat
new file mode 100644
index 0000000..2bd1cb3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ashgabat differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ashkhabad b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ashkhabad
new file mode 100644
index 0000000..2bd1cb3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ashkhabad differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Atyrau b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Atyrau
new file mode 100644
index 0000000..e7ea9c5
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Atyrau differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Baghdad b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Baghdad
new file mode 100644
index 0000000..c0e6072
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Baghdad differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Bahrain b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Bahrain
new file mode 100644
index 0000000..098997e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Bahrain differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Baku b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Baku
new file mode 100644
index 0000000..ae0ce4e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Baku differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Bangkok b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Bangkok
new file mode 100644
index 0000000..fa799db
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Bangkok differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Barnaul b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Barnaul
new file mode 100644
index 0000000..2f6b810
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Barnaul differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Beirut b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Beirut
new file mode 100644
index 0000000..fb266ed
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Beirut differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Bishkek b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Bishkek
new file mode 100644
index 0000000..547fd5e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Bishkek differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Brunei b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Brunei
new file mode 100644
index 0000000..098c6a0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Brunei differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Calcutta b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Calcutta
new file mode 100644
index 0000000..0014046
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Calcutta differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Chita b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Chita
new file mode 100644
index 0000000..75b3d7b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Chita differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Choibalsan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Choibalsan
new file mode 100644
index 0000000..2aa5cc4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Choibalsan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Chongqing b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Chongqing
new file mode 100644
index 0000000..91f6f8b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Chongqing differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Chungking b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Chungking
new file mode 100644
index 0000000..91f6f8b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Chungking differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Colombo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Colombo
new file mode 100644
index 0000000..353fe2a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Colombo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dacca b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dacca
new file mode 100644
index 0000000..3cf597d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dacca differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Damascus b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Damascus
new file mode 100644
index 0000000..afd956c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Damascus differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dhaka b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dhaka
new file mode 100644
index 0000000..3cf597d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dhaka differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dili b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dili
new file mode 100644
index 0000000..4614e4f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dili differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dubai b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dubai
new file mode 100644
index 0000000..b3ac791
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dubai differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dushanbe b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dushanbe
new file mode 100644
index 0000000..89e875b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Dushanbe differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Famagusta b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Famagusta
new file mode 100644
index 0000000..653b146
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Famagusta differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Gaza b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Gaza
new file mode 100644
index 0000000..dd5781e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Gaza differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Harbin b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Harbin
new file mode 100644
index 0000000..91f6f8b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Harbin differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Hebron b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Hebron
new file mode 100644
index 0000000..a64fc9e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Hebron differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ho_Chi_Minh b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ho_Chi_Minh
new file mode 100644
index 0000000..9c45ed9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ho_Chi_Minh differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Hong_Kong b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Hong_Kong
new file mode 100644
index 0000000..f9f7b13
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Hong_Kong differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Hovd b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Hovd
new file mode 100644
index 0000000..8b9abca
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Hovd differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Irkutsk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Irkutsk
new file mode 100644
index 0000000..e74a4d3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Irkutsk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Istanbul b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Istanbul
new file mode 100644
index 0000000..7c2336d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Istanbul differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Jakarta b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Jakarta
new file mode 100644
index 0000000..ec4bd57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Jakarta differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Jayapura b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Jayapura
new file mode 100644
index 0000000..3002c82
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Jayapura differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Jerusalem b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Jerusalem
new file mode 100644
index 0000000..1ebd066
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Jerusalem differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kabul b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kabul
new file mode 100644
index 0000000..661efc8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kabul differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kamchatka b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kamchatka
new file mode 100644
index 0000000..99776f5
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kamchatka differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Karachi b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Karachi
new file mode 100644
index 0000000..ba65c0e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Karachi differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kashgar b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kashgar
new file mode 100644
index 0000000..62bdcac
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kashgar differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kathmandu b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kathmandu
new file mode 100644
index 0000000..751cf4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kathmandu differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Katmandu b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Katmandu
new file mode 100644
index 0000000..751cf4a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Katmandu differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Khandyga b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Khandyga
new file mode 100644
index 0000000..7cdc99a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Khandyga differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kolkata b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kolkata
new file mode 100644
index 0000000..0014046
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kolkata differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Krasnoyarsk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Krasnoyarsk
new file mode 100644
index 0000000..4c27b2d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Krasnoyarsk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kuala_Lumpur b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kuala_Lumpur
new file mode 100644
index 0000000..3d9f191
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kuala_Lumpur differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kuching b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kuching
new file mode 100644
index 0000000..098c6a0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kuching differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kuwait b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kuwait
new file mode 100644
index 0000000..8c80624
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Kuwait differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Macao b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Macao
new file mode 100644
index 0000000..cac6506
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Macao differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Macau b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Macau
new file mode 100644
index 0000000..cac6506
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Macau differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Magadan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Magadan
new file mode 100644
index 0000000..70c198b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Magadan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Makassar b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Makassar
new file mode 100644
index 0000000..556ba86
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Makassar differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Manila b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Manila
new file mode 100644
index 0000000..168f720
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Manila differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Muscat b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Muscat
new file mode 100644
index 0000000..b3ac791
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Muscat differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Nicosia b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Nicosia
new file mode 100644
index 0000000..f7f10ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Nicosia differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Novokuznetsk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Novokuznetsk
new file mode 100644
index 0000000..a5e1b79
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Novokuznetsk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Novosibirsk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Novosibirsk
new file mode 100644
index 0000000..4ac7582
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Novosibirsk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Omsk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Omsk
new file mode 100644
index 0000000..16c5f3c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Omsk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Oral b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Oral
new file mode 100644
index 0000000..3b9ecac
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Oral differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Phnom_Penh b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Phnom_Penh
new file mode 100644
index 0000000..fa799db
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Phnom_Penh differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Pontianak b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Pontianak
new file mode 100644
index 0000000..12ce24c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Pontianak differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Pyongyang b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Pyongyang
new file mode 100644
index 0000000..7ad7e0b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Pyongyang differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Qatar b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Qatar
new file mode 100644
index 0000000..098997e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Qatar differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Qostanay b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Qostanay
new file mode 100644
index 0000000..2ee9ef7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Qostanay differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Qyzylorda b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Qyzylorda
new file mode 100644
index 0000000..27b522a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Qyzylorda differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Rangoon b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Rangoon
new file mode 100644
index 0000000..eef37b4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Rangoon differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Riyadh b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Riyadh
new file mode 100644
index 0000000..8c80624
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Riyadh differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Saigon b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Saigon
new file mode 100644
index 0000000..9c45ed9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Saigon differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Sakhalin b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Sakhalin
new file mode 100644
index 0000000..beb77b4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Sakhalin differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Samarkand b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Samarkand
new file mode 100644
index 0000000..8a93767
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Samarkand differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Seoul b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Seoul
new file mode 100644
index 0000000..96199e7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Seoul differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Shanghai b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Shanghai
new file mode 100644
index 0000000..91f6f8b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Shanghai differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Singapore b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Singapore
new file mode 100644
index 0000000..3d9f191
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Singapore differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Srednekolymsk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Srednekolymsk
new file mode 100644
index 0000000..d21e7ee
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Srednekolymsk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Taipei b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Taipei
new file mode 100644
index 0000000..24c4344
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Taipei differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tashkent b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tashkent
new file mode 100644
index 0000000..a9f6cd9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tashkent differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tbilisi b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tbilisi
new file mode 100644
index 0000000..3b131bb
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tbilisi differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tehran b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tehran
new file mode 100644
index 0000000..78f28cc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tehran differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tel_Aviv b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tel_Aviv
new file mode 100644
index 0000000..1ebd066
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tel_Aviv differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Thimbu b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Thimbu
new file mode 100644
index 0000000..95a9de9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Thimbu differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Thimphu b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Thimphu
new file mode 100644
index 0000000..95a9de9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Thimphu differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tokyo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tokyo
new file mode 100644
index 0000000..26f4d34
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tokyo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tomsk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tomsk
new file mode 100644
index 0000000..a6e494a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Tomsk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ujung_Pandang b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ujung_Pandang
new file mode 100644
index 0000000..556ba86
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ujung_Pandang differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ulaanbaatar b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ulaanbaatar
new file mode 100644
index 0000000..2aa5cc4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ulaanbaatar differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ulan_Bator b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ulan_Bator
new file mode 100644
index 0000000..2aa5cc4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ulan_Bator differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Urumqi b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Urumqi
new file mode 100644
index 0000000..62bdcac
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Urumqi differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ust-Nera b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ust-Nera
new file mode 100644
index 0000000..d05726a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Ust-Nera differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Vientiane b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Vientiane
new file mode 100644
index 0000000..fa799db
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Vientiane differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Vladivostok b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Vladivostok
new file mode 100644
index 0000000..274a10b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Vladivostok differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yakutsk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yakutsk
new file mode 100644
index 0000000..ae65a5f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yakutsk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yangon b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yangon
new file mode 100644
index 0000000..eef37b4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yangon differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yekaterinburg b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yekaterinburg
new file mode 100644
index 0000000..d4d19cc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yekaterinburg differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yerevan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yerevan
new file mode 100644
index 0000000..0d5f685
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Asia/Yerevan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Azores b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Azores
new file mode 100644
index 0000000..dd2c235
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Azores differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Bermuda b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Bermuda
new file mode 100644
index 0000000..527524e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Bermuda differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Canary b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Canary
new file mode 100644
index 0000000..f319215
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Canary differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Cape_Verde b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Cape_Verde
new file mode 100644
index 0000000..0d0d31a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Cape_Verde differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Faeroe b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Faeroe
new file mode 100644
index 0000000..4dab7ef
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Faeroe differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Faroe b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Faroe
new file mode 100644
index 0000000..4dab7ef
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Faroe differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Jan_Mayen b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Jan_Mayen
new file mode 100644
index 0000000..7f6d958
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Jan_Mayen differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Madeira b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Madeira
new file mode 100644
index 0000000..6725a0f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Madeira differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Reykjavik b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Reykjavik
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Reykjavik differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/South_Georgia b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/South_Georgia
new file mode 100644
index 0000000..a2b59a9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/South_Georgia differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/St_Helena b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/St_Helena
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/St_Helena differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Stanley b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Stanley
new file mode 100644
index 0000000..1527d0e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Atlantic/Stanley differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/ACT b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/ACT
new file mode 100644
index 0000000..0aea4c3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/ACT differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Adelaide b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Adelaide
new file mode 100644
index 0000000..f5dedca
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Adelaide differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Brisbane b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Brisbane
new file mode 100644
index 0000000..7ff9949
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Brisbane differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Broken_Hill b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Broken_Hill
new file mode 100644
index 0000000..698c76e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Broken_Hill differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Canberra b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Canberra
new file mode 100644
index 0000000..0aea4c3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Canberra differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Currie b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Currie
new file mode 100644
index 0000000..3adb8e1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Currie differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Darwin b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Darwin
new file mode 100644
index 0000000..74a3087
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Darwin differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Eucla b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Eucla
new file mode 100644
index 0000000..1551e96
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Eucla differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Hobart b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Hobart
new file mode 100644
index 0000000..3adb8e1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Hobart differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/LHI b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/LHI
new file mode 100644
index 0000000..069a95a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/LHI differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Lindeman b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Lindeman
new file mode 100644
index 0000000..4ee1825
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Lindeman differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Lord_Howe b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Lord_Howe
new file mode 100644
index 0000000..069a95a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Lord_Howe differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Melbourne b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Melbourne
new file mode 100644
index 0000000..ee903f4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Melbourne differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/NSW b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/NSW
new file mode 100644
index 0000000..0aea4c3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/NSW differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/North b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/North
new file mode 100644
index 0000000..74a3087
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/North differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Perth b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Perth
new file mode 100644
index 0000000..f8ddbdf
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Perth differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Queensland b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Queensland
new file mode 100644
index 0000000..7ff9949
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Queensland differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/South b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/South
new file mode 100644
index 0000000..f5dedca
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/South differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Sydney b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Sydney
new file mode 100644
index 0000000..0aea4c3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Sydney differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Tasmania b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Tasmania
new file mode 100644
index 0000000..3adb8e1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Tasmania differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Victoria b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Victoria
new file mode 100644
index 0000000..ee903f4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Victoria differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/West b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/West
new file mode 100644
index 0000000..f8ddbdf
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/West differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Yancowinna b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Yancowinna
new file mode 100644
index 0000000..698c76e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Australia/Yancowinna differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/Acre b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/Acre
new file mode 100644
index 0000000..cdda168
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/Acre differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/DeNoronha b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/DeNoronha
new file mode 100644
index 0000000..73b4b33
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/DeNoronha differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/East b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/East
new file mode 100644
index 0000000..67935ff
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/East differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/West b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/West
new file mode 100644
index 0000000..2708bae
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Brazil/West differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/CET b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/CET
new file mode 100644
index 0000000..40d7124
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/CET differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/CST6CDT b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/CST6CDT
new file mode 100644
index 0000000..c6981a0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/CST6CDT differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Atlantic b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Atlantic
new file mode 100644
index 0000000..756099a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Atlantic differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Central b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Central
new file mode 100644
index 0000000..ac40299
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Central differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Eastern b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Eastern
new file mode 100644
index 0000000..1701373
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Eastern differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Mountain b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Mountain
new file mode 100644
index 0000000..cd78a6f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Mountain differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Newfoundland b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Newfoundland
new file mode 100644
index 0000000..65a5b0c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Newfoundland differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Pacific b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Pacific
new file mode 100644
index 0000000..bb60cbc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Pacific differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Saskatchewan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Saskatchewan
new file mode 100644
index 0000000..20c9c84
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Saskatchewan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Yukon b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Yukon
new file mode 100644
index 0000000..318c4a8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Canada/Yukon differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Chile/Continental b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Chile/Continental
new file mode 100644
index 0000000..010c6bd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Chile/Continental differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Chile/EasterIsland b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Chile/EasterIsland
new file mode 100644
index 0000000..184cb6a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Chile/EasterIsland differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Cuba b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Cuba
new file mode 100644
index 0000000..b69ac45
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Cuba differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/EET b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/EET
new file mode 100644
index 0000000..9f3a067
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/EET differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/EST b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/EST
new file mode 100644
index 0000000..9964b9a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/EST differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/EST5EDT b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/EST5EDT
new file mode 100644
index 0000000..a8b9ab1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/EST5EDT differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Egypt b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Egypt
new file mode 100644
index 0000000..dd538c6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Egypt differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Eire b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Eire
new file mode 100644
index 0000000..c729def
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Eire differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT
new file mode 100644
index 0000000..c634746
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+0 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+0
new file mode 100644
index 0000000..c634746
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+0 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+1 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+1
new file mode 100644
index 0000000..4dab6f9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+1 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+10 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+10
new file mode 100644
index 0000000..c749290
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+10 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+11 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+11
new file mode 100644
index 0000000..d969982
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+11 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+12 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+12
new file mode 100644
index 0000000..cdeec90
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+12 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+2 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+2
new file mode 100644
index 0000000..fbd2a94
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+2 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+3 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+3
new file mode 100644
index 0000000..ee246ef
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+3 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+4 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+4
new file mode 100644
index 0000000..5a25ff2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+4 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+5 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+5
new file mode 100644
index 0000000..c0b745f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+5 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+6 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+6
new file mode 100644
index 0000000..06e777d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+6 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+7 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+7
new file mode 100644
index 0000000..4e0b53a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+7 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+8 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+8
new file mode 100644
index 0000000..714b0c5
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+8 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+9 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+9
new file mode 100644
index 0000000..78b9daa
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT+9 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-0 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-0
new file mode 100644
index 0000000..c634746
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-0 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-1 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-1
new file mode 100644
index 0000000..a838beb
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-1 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-10 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-10
new file mode 100644
index 0000000..68ff77d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-10 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-11 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-11
new file mode 100644
index 0000000..66af5a4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-11 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-12 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-12
new file mode 100644
index 0000000..17ba505
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-12 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-13 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-13
new file mode 100644
index 0000000..5f3706c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-13 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-14 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-14
new file mode 100644
index 0000000..7e9f9c4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-14 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-2 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-2
new file mode 100644
index 0000000..fcef6d9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-2 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-3 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-3
new file mode 100644
index 0000000..27973bc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-3 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-4 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-4
new file mode 100644
index 0000000..1efd841
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-4 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-5 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-5
new file mode 100644
index 0000000..1f76184
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-5 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-6 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-6
new file mode 100644
index 0000000..952681e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-6 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-7 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-7
new file mode 100644
index 0000000..cefc912
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-7 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-8 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-8
new file mode 100644
index 0000000..afb093d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-8 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-9 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-9
new file mode 100644
index 0000000..9265fb7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT-9 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT0 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT0
new file mode 100644
index 0000000..c634746
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/GMT0 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/Greenwich b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/Greenwich
new file mode 100644
index 0000000..c634746
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/Greenwich differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/UCT b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/UCT
new file mode 100644
index 0000000..91558be
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/UCT differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/UTC b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/UTC
new file mode 100644
index 0000000..91558be
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/UTC differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/Universal b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/Universal
new file mode 100644
index 0000000..91558be
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/Universal differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/Zulu b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/Zulu
new file mode 100644
index 0000000..91558be
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Etc/Zulu differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Amsterdam b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Amsterdam
new file mode 100644
index 0000000..40d7124
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Amsterdam differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Andorra b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Andorra
new file mode 100644
index 0000000..5962550
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Andorra differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Astrakhan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Astrakhan
new file mode 100644
index 0000000..a41624f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Astrakhan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Athens b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Athens
new file mode 100644
index 0000000..9f3a067
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Athens differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Belfast b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Belfast
new file mode 100644
index 0000000..5ad7422
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Belfast differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Belgrade b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Belgrade
new file mode 100644
index 0000000..27de456
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Belgrade differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Berlin b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Berlin
new file mode 100644
index 0000000..7f6d958
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Berlin differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Bratislava b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Bratislava
new file mode 100644
index 0000000..ce8f433
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Bratislava differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Brussels b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Brussels
new file mode 100644
index 0000000..40d7124
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Brussels differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Bucharest b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Bucharest
new file mode 100644
index 0000000..4303b90
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Bucharest differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Budapest b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Budapest
new file mode 100644
index 0000000..b76c873
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Budapest differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Busingen b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Busingen
new file mode 100644
index 0000000..ad6cf59
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Busingen differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Chisinau b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Chisinau
new file mode 100644
index 0000000..5ee23fe
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Chisinau differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Copenhagen b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Copenhagen
new file mode 100644
index 0000000..7f6d958
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Copenhagen differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Dublin b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Dublin
new file mode 100644
index 0000000..c729def
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Dublin differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Gibraltar b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Gibraltar
new file mode 100644
index 0000000..a38f11f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Gibraltar differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Guernsey b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Guernsey
new file mode 100644
index 0000000..5ad7422
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Guernsey differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Helsinki b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Helsinki
new file mode 100644
index 0000000..b4f8f9c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Helsinki differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Isle_of_Man b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Isle_of_Man
new file mode 100644
index 0000000..5ad7422
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Isle_of_Man differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Istanbul b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Istanbul
new file mode 100644
index 0000000..7c2336d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Istanbul differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Jersey b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Jersey
new file mode 100644
index 0000000..5ad7422
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Jersey differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kaliningrad b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kaliningrad
new file mode 100644
index 0000000..cc99bea
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kaliningrad differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kiev b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kiev
new file mode 100644
index 0000000..52efea8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kiev differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kirov b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kirov
new file mode 100644
index 0000000..0cfb956
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kirov differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kyiv b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kyiv
new file mode 100644
index 0000000..52efea8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Kyiv differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Lisbon b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Lisbon
new file mode 100644
index 0000000..616de16
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Lisbon differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Ljubljana b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Ljubljana
new file mode 100644
index 0000000..27de456
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Ljubljana differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/London b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/London
new file mode 100644
index 0000000..5ad7422
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/London differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Luxembourg b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Luxembourg
new file mode 100644
index 0000000..40d7124
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Luxembourg differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Madrid b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Madrid
new file mode 100644
index 0000000..53f4cd1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Madrid differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Malta b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Malta
new file mode 100644
index 0000000..1d1a7bc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Malta differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Mariehamn b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Mariehamn
new file mode 100644
index 0000000..b4f8f9c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Mariehamn differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Minsk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Minsk
new file mode 100644
index 0000000..3731e40
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Minsk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Monaco b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Monaco
new file mode 100644
index 0000000..7d366c6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Monaco differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Moscow b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Moscow
new file mode 100644
index 0000000..ddb3f4e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Moscow differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Nicosia b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Nicosia
new file mode 100644
index 0000000..f7f10ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Nicosia differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Oslo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Oslo
new file mode 100644
index 0000000..7f6d958
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Oslo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Paris b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Paris
new file mode 100644
index 0000000..7d366c6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Paris differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Podgorica b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Podgorica
new file mode 100644
index 0000000..27de456
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Podgorica differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Prague b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Prague
new file mode 100644
index 0000000..ce8f433
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Prague differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Riga b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Riga
new file mode 100644
index 0000000..8db477d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Riga differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Rome b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Rome
new file mode 100644
index 0000000..32b2899
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Rome differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Samara b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Samara
new file mode 100644
index 0000000..d0ea2f2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Samara differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/San_Marino b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/San_Marino
new file mode 100644
index 0000000..32b2899
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/San_Marino differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Sarajevo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Sarajevo
new file mode 100644
index 0000000..27de456
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Sarajevo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Saratov b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Saratov
new file mode 100644
index 0000000..a863913
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Saratov differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Simferopol b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Simferopol
new file mode 100644
index 0000000..4bf24de
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Simferopol differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Skopje b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Skopje
new file mode 100644
index 0000000..27de456
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Skopje differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Sofia b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Sofia
new file mode 100644
index 0000000..0e4d879
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Sofia differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Stockholm b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Stockholm
new file mode 100644
index 0000000..7f6d958
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Stockholm differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Tallinn b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Tallinn
new file mode 100644
index 0000000..b5acca3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Tallinn differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Tirane b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Tirane
new file mode 100644
index 0000000..0b86017
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Tirane differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Tiraspol b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Tiraspol
new file mode 100644
index 0000000..5ee23fe
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Tiraspol differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Ulyanovsk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Ulyanovsk
new file mode 100644
index 0000000..d668233
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Ulyanovsk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Uzhgorod b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Uzhgorod
new file mode 100644
index 0000000..52efea8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Uzhgorod differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vaduz b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vaduz
new file mode 100644
index 0000000..ad6cf59
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vaduz differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vatican b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vatican
new file mode 100644
index 0000000..32b2899
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vatican differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vienna b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vienna
new file mode 100644
index 0000000..3582bb1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vienna differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vilnius b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vilnius
new file mode 100644
index 0000000..7abd63f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Vilnius differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Volgograd b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Volgograd
new file mode 100644
index 0000000..9d51a38
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Volgograd differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Warsaw b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Warsaw
new file mode 100644
index 0000000..e33cf67
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Warsaw differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Zagreb b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Zagreb
new file mode 100644
index 0000000..27de456
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Zagreb differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Zaporozhye b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Zaporozhye
new file mode 100644
index 0000000..52efea8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Zaporozhye differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Zurich b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Zurich
new file mode 100644
index 0000000..ad6cf59
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Europe/Zurich differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Factory b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Factory
new file mode 100644
index 0000000..60aa2a0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Factory differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GB b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GB
new file mode 100644
index 0000000..5ad7422
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GB differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GB-Eire b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GB-Eire
new file mode 100644
index 0000000..5ad7422
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GB-Eire differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT
new file mode 100644
index 0000000..c634746
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT+0 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT+0
new file mode 100644
index 0000000..c634746
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT+0 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT-0 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT-0
new file mode 100644
index 0000000..c634746
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT-0 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT0 b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT0
new file mode 100644
index 0000000..c634746
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/GMT0 differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Greenwich b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Greenwich
new file mode 100644
index 0000000..c634746
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Greenwich differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/HST b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/HST
new file mode 100644
index 0000000..c7cd060
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/HST differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Hongkong b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Hongkong
new file mode 100644
index 0000000..f9f7b13
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Hongkong differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Iceland b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Iceland
new file mode 100644
index 0000000..28b32ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Iceland differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Antananarivo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Antananarivo
new file mode 100644
index 0000000..9dcfc19
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Antananarivo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Chagos b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Chagos
new file mode 100644
index 0000000..a555481
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Chagos differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Christmas b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Christmas
new file mode 100644
index 0000000..fa799db
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Christmas differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Cocos b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Cocos
new file mode 100644
index 0000000..eef37b4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Cocos differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Comoro b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Comoro
new file mode 100644
index 0000000..9dcfc19
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Comoro differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Kerguelen b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Kerguelen
new file mode 100644
index 0000000..555728b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Kerguelen differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Mahe b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Mahe
new file mode 100644
index 0000000..b3ac791
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Mahe differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Maldives b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Maldives
new file mode 100644
index 0000000..555728b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Maldives differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Mauritius b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Mauritius
new file mode 100644
index 0000000..212d4b2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Mauritius differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Mayotte b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Mayotte
new file mode 100644
index 0000000..9dcfc19
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Mayotte differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Reunion b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Reunion
new file mode 100644
index 0000000..b3ac791
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Indian/Reunion differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Iran b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Iran
new file mode 100644
index 0000000..78f28cc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Iran differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Israel b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Israel
new file mode 100644
index 0000000..1ebd066
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Israel differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Jamaica b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Jamaica
new file mode 100644
index 0000000..2a9b7fd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Jamaica differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Japan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Japan
new file mode 100644
index 0000000..26f4d34
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Japan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Kwajalein b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Kwajalein
new file mode 100644
index 0000000..1887a60
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Kwajalein differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Libya b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Libya
new file mode 100644
index 0000000..07b393b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Libya differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/MET b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/MET
new file mode 100644
index 0000000..40d7124
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/MET differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/MST b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/MST
new file mode 100644
index 0000000..ab37e84
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/MST differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/MST7MDT b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/MST7MDT
new file mode 100644
index 0000000..abb2b97
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/MST7MDT differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Mexico/BajaNorte b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Mexico/BajaNorte
new file mode 100644
index 0000000..0fe7391
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Mexico/BajaNorte differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Mexico/BajaSur b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Mexico/BajaSur
new file mode 100644
index 0000000..386616a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Mexico/BajaSur differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Mexico/General b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Mexico/General
new file mode 100644
index 0000000..ad70cf3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Mexico/General differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/NZ b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/NZ
new file mode 100644
index 0000000..6575fdc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/NZ differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/NZ-CHAT b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/NZ-CHAT
new file mode 100644
index 0000000..bde46cf
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/NZ-CHAT differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Navajo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Navajo
new file mode 100644
index 0000000..abb2b97
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Navajo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/PRC b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/PRC
new file mode 100644
index 0000000..91f6f8b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/PRC differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/PST8PDT b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/PST8PDT
new file mode 100644
index 0000000..610e7af
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/PST8PDT differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Apia b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Apia
new file mode 100644
index 0000000..e592a68
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Apia differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Auckland b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Auckland
new file mode 100644
index 0000000..6575fdc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Auckland differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Bougainville b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Bougainville
new file mode 100644
index 0000000..c535acd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Bougainville differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Chatham b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Chatham
new file mode 100644
index 0000000..bde46cf
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Chatham differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Chuuk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Chuuk
new file mode 100644
index 0000000..7be2474
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Chuuk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Easter b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Easter
new file mode 100644
index 0000000..184cb6a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Easter differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Efate b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Efate
new file mode 100644
index 0000000..777325f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Efate differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Enderbury b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Enderbury
new file mode 100644
index 0000000..b1c4b07
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Enderbury differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Fakaofo b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Fakaofo
new file mode 100644
index 0000000..4905ea7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Fakaofo differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Fiji b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Fiji
new file mode 100644
index 0000000..acf8091
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Fiji differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Funafuti b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Funafuti
new file mode 100644
index 0000000..47661d4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Funafuti differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Galapagos b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Galapagos
new file mode 100644
index 0000000..40051dd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Galapagos differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Gambier b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Gambier
new file mode 100644
index 0000000..84acaf4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Gambier differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Guadalcanal b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Guadalcanal
new file mode 100644
index 0000000..1ab8353
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Guadalcanal differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Guam b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Guam
new file mode 100644
index 0000000..66490d2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Guam differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Honolulu b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Honolulu
new file mode 100644
index 0000000..c7cd060
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Honolulu differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Johnston b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Johnston
new file mode 100644
index 0000000..c7cd060
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Johnston differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kanton b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kanton
new file mode 100644
index 0000000..b1c4b07
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kanton differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kiritimati b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kiritimati
new file mode 100644
index 0000000..b4c6037
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kiritimati differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kosrae b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kosrae
new file mode 100644
index 0000000..0666fb0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kosrae differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kwajalein b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kwajalein
new file mode 100644
index 0000000..1887a60
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Kwajalein differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Majuro b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Majuro
new file mode 100644
index 0000000..47661d4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Majuro differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Marquesas b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Marquesas
new file mode 100644
index 0000000..f546c03
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Marquesas differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Midway b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Midway
new file mode 100644
index 0000000..cb56709
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Midway differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Nauru b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Nauru
new file mode 100644
index 0000000..3339b6c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Nauru differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Niue b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Niue
new file mode 100644
index 0000000..f76972f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Niue differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Norfolk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Norfolk
new file mode 100644
index 0000000..3b4186d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Norfolk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Noumea b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Noumea
new file mode 100644
index 0000000..959cc8c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Noumea differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Pago_Pago b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Pago_Pago
new file mode 100644
index 0000000..cb56709
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Pago_Pago differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Palau b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Palau
new file mode 100644
index 0000000..1cbebe2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Palau differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Pitcairn b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Pitcairn
new file mode 100644
index 0000000..5ee90e7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Pitcairn differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Pohnpei b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Pohnpei
new file mode 100644
index 0000000..1ab8353
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Pohnpei differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Ponape b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Ponape
new file mode 100644
index 0000000..1ab8353
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Ponape differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Port_Moresby b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Port_Moresby
new file mode 100644
index 0000000..7be2474
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Port_Moresby differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Rarotonga b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Rarotonga
new file mode 100644
index 0000000..184a87c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Rarotonga differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Saipan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Saipan
new file mode 100644
index 0000000..66490d2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Saipan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Samoa b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Samoa
new file mode 100644
index 0000000..cb56709
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Samoa differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Tahiti b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Tahiti
new file mode 100644
index 0000000..481edd3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Tahiti differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Tarawa b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Tarawa
new file mode 100644
index 0000000..47661d4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Tarawa differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Tongatapu b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Tongatapu
new file mode 100644
index 0000000..c8824ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Tongatapu differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Truk b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Truk
new file mode 100644
index 0000000..7be2474
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Truk differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Wake b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Wake
new file mode 100644
index 0000000..47661d4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Wake differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Wallis b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Wallis
new file mode 100644
index 0000000..47661d4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Wallis differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Yap b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Yap
new file mode 100644
index 0000000..7be2474
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Pacific/Yap differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Poland b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Poland
new file mode 100644
index 0000000..e33cf67
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Poland differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Portugal b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Portugal
new file mode 100644
index 0000000..616de16
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Portugal differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/ROC b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/ROC
new file mode 100644
index 0000000..24c4344
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/ROC differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/ROK b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/ROK
new file mode 100644
index 0000000..96199e7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/ROK differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Singapore b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Singapore
new file mode 100644
index 0000000..3d9f191
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Singapore differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Turkey b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Turkey
new file mode 100644
index 0000000..7c2336d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Turkey differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/UCT b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/UCT
new file mode 100644
index 0000000..91558be
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/UCT differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Alaska b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Alaska
new file mode 100644
index 0000000..9bbb2fd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Alaska differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Aleutian b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Aleutian
new file mode 100644
index 0000000..4323649
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Aleutian differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Arizona b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Arizona
new file mode 100644
index 0000000..ab37e84
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Arizona differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Central b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Central
new file mode 100644
index 0000000..c6981a0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Central differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/East-Indiana b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/East-Indiana
new file mode 100644
index 0000000..a84b6e9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/East-Indiana differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Eastern b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Eastern
new file mode 100644
index 0000000..a8b9ab1
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Eastern differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Hawaii b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Hawaii
new file mode 100644
index 0000000..c7cd060
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Hawaii differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Indiana-Starke b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Indiana-Starke
new file mode 100644
index 0000000..025d132
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Indiana-Starke differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Michigan b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Michigan
new file mode 100644
index 0000000..e104faa
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Michigan differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Mountain b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Mountain
new file mode 100644
index 0000000..abb2b97
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Mountain differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Pacific b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Pacific
new file mode 100644
index 0000000..610e7af
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Pacific differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Samoa b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Samoa
new file mode 100644
index 0000000..cb56709
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/US/Samoa differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/UTC b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/UTC
new file mode 100644
index 0000000..91558be
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/UTC differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Universal b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Universal
new file mode 100644
index 0000000..91558be
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Universal differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/W-SU b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/W-SU
new file mode 100644
index 0000000..ddb3f4e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/W-SU differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/WET b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/WET
new file mode 100644
index 0000000..616de16
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/WET differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Zulu b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Zulu
new file mode 100644
index 0000000..91558be
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/Zulu differ
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/iso3166.tab b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/iso3166.tab
new file mode 100644
index 0000000..402c015
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/iso3166.tab
@@ -0,0 +1,279 @@
+# ISO 3166 alpha-2 country codes
+#
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
+#
+# From Paul Eggert (2023-09-06):
+# This file contains a table of two-letter country codes. Columns are
+# separated by a single tab. Lines beginning with '#' are comments.
+# All text uses UTF-8 encoding. The columns of the table are as follows:
+#
+# 1. ISO 3166-1 alpha-2 country code, current as of
+# ISO/TC 46 N1108 (2023-04-05). See: ISO/TC 46 Documents
+# https://www.iso.org/committee/48750.html?view=documents
+# 2. The usual English name for the coded region. This sometimes
+# departs from ISO-listed names, sometimes so that sorted subsets
+# of names are useful (e.g., "Samoa (American)" and "Samoa
+# (western)" rather than "American Samoa" and "Samoa"),
+# sometimes to avoid confusion among non-experts (e.g.,
+# "Czech Republic" and "Turkey" rather than "Czechia" and "Türkiye"),
+# and sometimes to omit needless detail or churn (e.g., "Netherlands"
+# rather than "Netherlands (the)" or "Netherlands (Kingdom of the)").
+#
+# The table is sorted by country code.
+#
+# This table is intended as an aid for users, to help them select time
+# zone data appropriate for their practical needs. It is not intended
+# to take or endorse any position on legal or territorial claims.
+#
+#country-
+#code name of country, territory, area, or subdivision
+AD Andorra
+AE United Arab Emirates
+AF Afghanistan
+AG Antigua & Barbuda
+AI Anguilla
+AL Albania
+AM Armenia
+AO Angola
+AQ Antarctica
+AR Argentina
+AS Samoa (American)
+AT Austria
+AU Australia
+AW Aruba
+AX Åland Islands
+AZ Azerbaijan
+BA Bosnia & Herzegovina
+BB Barbados
+BD Bangladesh
+BE Belgium
+BF Burkina Faso
+BG Bulgaria
+BH Bahrain
+BI Burundi
+BJ Benin
+BL St Barthelemy
+BM Bermuda
+BN Brunei
+BO Bolivia
+BQ Caribbean NL
+BR Brazil
+BS Bahamas
+BT Bhutan
+BV Bouvet Island
+BW Botswana
+BY Belarus
+BZ Belize
+CA Canada
+CC Cocos (Keeling) Islands
+CD Congo (Dem. Rep.)
+CF Central African Rep.
+CG Congo (Rep.)
+CH Switzerland
+CI Côte d'Ivoire
+CK Cook Islands
+CL Chile
+CM Cameroon
+CN China
+CO Colombia
+CR Costa Rica
+CU Cuba
+CV Cape Verde
+CW Curaçao
+CX Christmas Island
+CY Cyprus
+CZ Czech Republic
+DE Germany
+DJ Djibouti
+DK Denmark
+DM Dominica
+DO Dominican Republic
+DZ Algeria
+EC Ecuador
+EE Estonia
+EG Egypt
+EH Western Sahara
+ER Eritrea
+ES Spain
+ET Ethiopia
+FI Finland
+FJ Fiji
+FK Falkland Islands
+FM Micronesia
+FO Faroe Islands
+FR France
+GA Gabon
+GB Britain (UK)
+GD Grenada
+GE Georgia
+GF French Guiana
+GG Guernsey
+GH Ghana
+GI Gibraltar
+GL Greenland
+GM Gambia
+GN Guinea
+GP Guadeloupe
+GQ Equatorial Guinea
+GR Greece
+GS South Georgia & the South Sandwich Islands
+GT Guatemala
+GU Guam
+GW Guinea-Bissau
+GY Guyana
+HK Hong Kong
+HM Heard Island & McDonald Islands
+HN Honduras
+HR Croatia
+HT Haiti
+HU Hungary
+ID Indonesia
+IE Ireland
+IL Israel
+IM Isle of Man
+IN India
+IO British Indian Ocean Territory
+IQ Iraq
+IR Iran
+IS Iceland
+IT Italy
+JE Jersey
+JM Jamaica
+JO Jordan
+JP Japan
+KE Kenya
+KG Kyrgyzstan
+KH Cambodia
+KI Kiribati
+KM Comoros
+KN St Kitts & Nevis
+KP Korea (North)
+KR Korea (South)
+KW Kuwait
+KY Cayman Islands
+KZ Kazakhstan
+LA Laos
+LB Lebanon
+LC St Lucia
+LI Liechtenstein
+LK Sri Lanka
+LR Liberia
+LS Lesotho
+LT Lithuania
+LU Luxembourg
+LV Latvia
+LY Libya
+MA Morocco
+MC Monaco
+MD Moldova
+ME Montenegro
+MF St Martin (French)
+MG Madagascar
+MH Marshall Islands
+MK North Macedonia
+ML Mali
+MM Myanmar (Burma)
+MN Mongolia
+MO Macau
+MP Northern Mariana Islands
+MQ Martinique
+MR Mauritania
+MS Montserrat
+MT Malta
+MU Mauritius
+MV Maldives
+MW Malawi
+MX Mexico
+MY Malaysia
+MZ Mozambique
+NA Namibia
+NC New Caledonia
+NE Niger
+NF Norfolk Island
+NG Nigeria
+NI Nicaragua
+NL Netherlands
+NO Norway
+NP Nepal
+NR Nauru
+NU Niue
+NZ New Zealand
+OM Oman
+PA Panama
+PE Peru
+PF French Polynesia
+PG Papua New Guinea
+PH Philippines
+PK Pakistan
+PL Poland
+PM St Pierre & Miquelon
+PN Pitcairn
+PR Puerto Rico
+PS Palestine
+PT Portugal
+PW Palau
+PY Paraguay
+QA Qatar
+RE Réunion
+RO Romania
+RS Serbia
+RU Russia
+RW Rwanda
+SA Saudi Arabia
+SB Solomon Islands
+SC Seychelles
+SD Sudan
+SE Sweden
+SG Singapore
+SH St Helena
+SI Slovenia
+SJ Svalbard & Jan Mayen
+SK Slovakia
+SL Sierra Leone
+SM San Marino
+SN Senegal
+SO Somalia
+SR Suriname
+SS South Sudan
+ST Sao Tome & Principe
+SV El Salvador
+SX St Maarten (Dutch)
+SY Syria
+SZ Eswatini (Swaziland)
+TC Turks & Caicos Is
+TD Chad
+TF French S. Terr.
+TG Togo
+TH Thailand
+TJ Tajikistan
+TK Tokelau
+TL East Timor
+TM Turkmenistan
+TN Tunisia
+TO Tonga
+TR Turkey
+TT Trinidad & Tobago
+TV Tuvalu
+TW Taiwan
+TZ Tanzania
+UA Ukraine
+UG Uganda
+UM US minor outlying islands
+US United States
+UY Uruguay
+UZ Uzbekistan
+VA Vatican City
+VC St Vincent
+VE Venezuela
+VG Virgin Islands (UK)
+VI Virgin Islands (US)
+VN Vietnam
+VU Vanuatu
+WF Wallis & Futuna
+WS Samoa (western)
+YE Yemen
+YT Mayotte
+ZA South Africa
+ZM Zambia
+ZW Zimbabwe
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/leapseconds b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/leapseconds
new file mode 100644
index 0000000..76f7714
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/leapseconds
@@ -0,0 +1,79 @@
+# Allowance for leap seconds added to each time zone file.
+
+# This file is in the public domain.
+
+# This file is generated automatically from the data in the public-domain
+# NIST/IERS format leap-seconds.list file, which can be copied from
+#
+# or, in a variant with different comments, from
+# .
+# For more about leap-seconds.list, please see
+# The NTP Timescale and Leap Seconds
+# .
+
+# The rules for leap seconds are specified in Annex 1 (Time scales) of:
+# Standard-frequency and time-signal emissions.
+# International Telecommunication Union - Radiocommunication Sector
+# (ITU-R) Recommendation TF.460-6 (02/2002)
+# .
+# The International Earth Rotation and Reference Systems Service (IERS)
+# periodically uses leap seconds to keep UTC to within 0.9 s of UT1
+# (a proxy for Earth's angle in space as measured by astronomers)
+# and publishes leap second data in a copyrighted file
+# .
+# See: Levine J. Coordinated Universal Time and the leap second.
+# URSI Radio Sci Bull. 2016;89(4):30-6. doi:10.23919/URSIRSB.2016.7909995
+# .
+
+# There were no leap seconds before 1972, as no official mechanism
+# accounted for the discrepancy between atomic time (TAI) and the earth's
+# rotation. The first ("1 Jan 1972") data line in leap-seconds.list
+# does not denote a leap second; it denotes the start of the current definition
+# of UTC.
+
+# All leap-seconds are Stationary (S) at the given UTC time.
+# The correction (+ or -) is made at the given time, so in the unlikely
+# event of a negative leap second, a line would look like this:
+# Leap YEAR MON DAY 23:59:59 - S
+# Typical lines look like this:
+# Leap YEAR MON DAY 23:59:60 + S
+Leap 1972 Jun 30 23:59:60 + S
+Leap 1972 Dec 31 23:59:60 + S
+Leap 1973 Dec 31 23:59:60 + S
+Leap 1974 Dec 31 23:59:60 + S
+Leap 1975 Dec 31 23:59:60 + S
+Leap 1976 Dec 31 23:59:60 + S
+Leap 1977 Dec 31 23:59:60 + S
+Leap 1978 Dec 31 23:59:60 + S
+Leap 1979 Dec 31 23:59:60 + S
+Leap 1981 Jun 30 23:59:60 + S
+Leap 1982 Jun 30 23:59:60 + S
+Leap 1983 Jun 30 23:59:60 + S
+Leap 1985 Jun 30 23:59:60 + S
+Leap 1987 Dec 31 23:59:60 + S
+Leap 1989 Dec 31 23:59:60 + S
+Leap 1990 Dec 31 23:59:60 + S
+Leap 1992 Jun 30 23:59:60 + S
+Leap 1993 Jun 30 23:59:60 + S
+Leap 1994 Jun 30 23:59:60 + S
+Leap 1995 Dec 31 23:59:60 + S
+Leap 1997 Jun 30 23:59:60 + S
+Leap 1998 Dec 31 23:59:60 + S
+Leap 2005 Dec 31 23:59:60 + S
+Leap 2008 Dec 31 23:59:60 + S
+Leap 2012 Jun 30 23:59:60 + S
+Leap 2015 Jun 30 23:59:60 + S
+Leap 2016 Dec 31 23:59:60 + S
+
+# UTC timestamp when this leap second list expires.
+# Any additional leap seconds will come after this.
+# This Expires line is commented out for now,
+# so that pre-2020a zic implementations do not reject this file.
+#Expires 2025 Dec 28 00:00:00
+
+# POSIX timestamps for the data in this file:
+#updated 1736208000 (2025-01-07 00:00:00 UTC)
+#expires 1766880000 (2025-12-28 00:00:00 UTC)
+
+# Updated through IERS Bulletin C (https://hpiers.obspm.fr/iers/bul/bulc/bulletinc.dat)
+# File expires on 28 December 2025
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/tzdata.zi b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/tzdata.zi
new file mode 100644
index 0000000..0bcae52
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/tzdata.zi
@@ -0,0 +1,4300 @@
+# version unknown
+# This zic input file is in the public domain.
+R d 1916 o - Jun 14 23s 1 S
+R d 1916 1919 - O Su>=1 23s 0 -
+R d 1917 o - Mar 24 23s 1 S
+R d 1918 o - Mar 9 23s 1 S
+R d 1919 o - Mar 1 23s 1 S
+R d 1920 o - F 14 23s 1 S
+R d 1920 o - O 23 23s 0 -
+R d 1921 o - Mar 14 23s 1 S
+R d 1921 o - Jun 21 23s 0 -
+R d 1939 o - S 11 23s 1 S
+R d 1939 o - N 19 1 0 -
+R d 1944 1945 - Ap M>=1 2 1 S
+R d 1944 o - O 8 2 0 -
+R d 1945 o - S 16 1 0 -
+R d 1971 o - Ap 25 23s 1 S
+R d 1971 o - S 26 23s 0 -
+R d 1977 o - May 6 0 1 S
+R d 1977 o - O 21 0 0 -
+R d 1978 o - Mar 24 1 1 S
+R d 1978 o - S 22 3 0 -
+R d 1980 o - Ap 25 0 1 S
+R d 1980 o - O 31 2 0 -
+R K 1940 o - Jul 15 0 1 S
+R K 1940 o - O 1 0 0 -
+R K 1941 o - Ap 15 0 1 S
+R K 1941 o - S 16 0 0 -
+R K 1942 1944 - Ap 1 0 1 S
+R K 1942 o - O 27 0 0 -
+R K 1943 1945 - N 1 0 0 -
+R K 1945 o - Ap 16 0 1 S
+R K 1957 o - May 10 0 1 S
+R K 1957 1958 - O 1 0 0 -
+R K 1958 o - May 1 0 1 S
+R K 1959 1981 - May 1 1 1 S
+R K 1959 1965 - S 30 3 0 -
+R K 1966 1994 - O 1 3 0 -
+R K 1982 o - Jul 25 1 1 S
+R K 1983 o - Jul 12 1 1 S
+R K 1984 1988 - May 1 1 1 S
+R K 1989 o - May 6 1 1 S
+R K 1990 1994 - May 1 1 1 S
+R K 1995 2010 - Ap lastF 0s 1 S
+R K 1995 2005 - S lastTh 24 0 -
+R K 2006 o - S 21 24 0 -
+R K 2007 o - S Th>=1 24 0 -
+R K 2008 o - Au lastTh 24 0 -
+R K 2009 o - Au 20 24 0 -
+R K 2010 o - Au 10 24 0 -
+R K 2010 o - S 9 24 1 S
+R K 2010 o - S lastTh 24 0 -
+R K 2014 o - May 15 24 1 S
+R K 2014 o - Jun 26 24 0 -
+R K 2014 o - Jul 31 24 1 S
+R K 2014 o - S lastTh 24 0 -
+R K 2023 ma - Ap lastF 0 1 S
+R K 2023 ma - O lastTh 24 0 -
+R L 1951 o - O 14 2 1 S
+R L 1952 o - Ja 1 0 0 -
+R L 1953 o - O 9 2 1 S
+R L 1954 o - Ja 1 0 0 -
+R L 1955 o - S 30 0 1 S
+R L 1956 o - Ja 1 0 0 -
+R L 1982 1984 - Ap 1 0 1 S
+R L 1982 1985 - O 1 0 0 -
+R L 1985 o - Ap 6 0 1 S
+R L 1986 o - Ap 4 0 1 S
+R L 1986 o - O 3 0 0 -
+R L 1987 1989 - Ap 1 0 1 S
+R L 1987 1989 - O 1 0 0 -
+R L 1997 o - Ap 4 0 1 S
+R L 1997 o - O 4 0 0 -
+R L 2013 o - Mar lastF 1 1 S
+R L 2013 o - O lastF 2 0 -
+R MU 1982 o - O 10 0 1 -
+R MU 1983 o - Mar 21 0 0 -
+R MU 2008 o - O lastSu 2 1 -
+R MU 2009 o - Mar lastSu 2 0 -
+R M 1939 o - S 12 0 1 -
+R M 1939 o - N 19 0 0 -
+R M 1940 o - F 25 0 1 -
+R M 1945 o - N 18 0 0 -
+R M 1950 o - Jun 11 0 1 -
+R M 1950 o - O 29 0 0 -
+R M 1967 o - Jun 3 12 1 -
+R M 1967 o - O 1 0 0 -
+R M 1974 o - Jun 24 0 1 -
+R M 1974 o - S 1 0 0 -
+R M 1976 1977 - May 1 0 1 -
+R M 1976 o - Au 1 0 0 -
+R M 1977 o - S 28 0 0 -
+R M 1978 o - Jun 1 0 1 -
+R M 1978 o - Au 4 0 0 -
+R M 2008 o - Jun 1 0 1 -
+R M 2008 o - S 1 0 0 -
+R M 2009 o - Jun 1 0 1 -
+R M 2009 o - Au 21 0 0 -
+R M 2010 o - May 2 0 1 -
+R M 2010 o - Au 8 0 0 -
+R M 2011 o - Ap 3 0 1 -
+R M 2011 o - Jul 31 0 0 -
+R M 2012 2013 - Ap lastSu 2 1 -
+R M 2012 o - Jul 20 3 0 -
+R M 2012 o - Au 20 2 1 -
+R M 2012 o - S 30 3 0 -
+R M 2013 o - Jul 7 3 0 -
+R M 2013 o - Au 10 2 1 -
+R M 2013 2018 - O lastSu 3 0 -
+R M 2014 2018 - Mar lastSu 2 1 -
+R M 2014 o - Jun 28 3 0 -
+R M 2014 o - Au 2 2 1 -
+R M 2015 o - Jun 14 3 0 -
+R M 2015 o - Jul 19 2 1 -
+R M 2016 o - Jun 5 3 0 -
+R M 2016 o - Jul 10 2 1 -
+R M 2017 o - May 21 3 0 -
+R M 2017 o - Jul 2 2 1 -
+R M 2018 o - May 13 3 0 -
+R M 2018 o - Jun 17 2 1 -
+R M 2019 o - May 5 3 -1 -
+R M 2019 o - Jun 9 2 0 -
+R M 2020 o - Ap 19 3 -1 -
+R M 2020 o - May 31 2 0 -
+R M 2021 o - Ap 11 3 -1 -
+R M 2021 o - May 16 2 0 -
+R M 2022 o - Mar 27 3 -1 -
+R M 2022 o - May 8 2 0 -
+R M 2023 o - Mar 19 3 -1 -
+R M 2023 o - Ap 23 2 0 -
+R M 2024 o - Mar 10 3 -1 -
+R M 2024 o - Ap 14 2 0 -
+R M 2025 o - F 23 3 -1 -
+R M 2025 o - Ap 6 2 0 -
+R M 2026 o - F 15 3 -1 -
+R M 2026 o - Mar 22 2 0 -
+R M 2027 o - F 7 3 -1 -
+R M 2027 o - Mar 14 2 0 -
+R M 2028 o - Ja 23 3 -1 -
+R M 2028 o - Mar 5 2 0 -
+R M 2029 o - Ja 14 3 -1 -
+R M 2029 o - F 18 2 0 -
+R M 2029 o - D 30 3 -1 -
+R M 2030 o - F 10 2 0 -
+R M 2030 o - D 22 3 -1 -
+R M 2031 o - Ja 26 2 0 -
+R M 2031 o - D 14 3 -1 -
+R M 2032 o - Ja 18 2 0 -
+R M 2032 o - N 28 3 -1 -
+R M 2033 o - Ja 9 2 0 -
+R M 2033 o - N 20 3 -1 -
+R M 2033 o - D 25 2 0 -
+R M 2034 o - N 5 3 -1 -
+R M 2034 o - D 17 2 0 -
+R M 2035 o - O 28 3 -1 -
+R M 2035 o - D 9 2 0 -
+R M 2036 o - O 19 3 -1 -
+R M 2036 o - N 23 2 0 -
+R M 2037 o - O 4 3 -1 -
+R M 2037 o - N 15 2 0 -
+R M 2038 o - S 26 3 -1 -
+R M 2038 o - O 31 2 0 -
+R M 2039 o - S 18 3 -1 -
+R M 2039 o - O 23 2 0 -
+R M 2040 o - S 2 3 -1 -
+R M 2040 o - O 14 2 0 -
+R M 2041 o - Au 25 3 -1 -
+R M 2041 o - S 29 2 0 -
+R M 2042 o - Au 10 3 -1 -
+R M 2042 o - S 21 2 0 -
+R M 2043 o - Au 2 3 -1 -
+R M 2043 o - S 13 2 0 -
+R M 2044 o - Jul 24 3 -1 -
+R M 2044 o - Au 28 2 0 -
+R M 2045 o - Jul 9 3 -1 -
+R M 2045 o - Au 20 2 0 -
+R M 2046 o - Jul 1 3 -1 -
+R M 2046 o - Au 5 2 0 -
+R M 2047 o - Jun 23 3 -1 -
+R M 2047 o - Jul 28 2 0 -
+R M 2048 o - Jun 7 3 -1 -
+R M 2048 o - Jul 19 2 0 -
+R M 2049 o - May 30 3 -1 -
+R M 2049 o - Jul 4 2 0 -
+R M 2050 o - May 15 3 -1 -
+R M 2050 o - Jun 26 2 0 -
+R M 2051 o - May 7 3 -1 -
+R M 2051 o - Jun 18 2 0 -
+R M 2052 o - Ap 28 3 -1 -
+R M 2052 o - Jun 2 2 0 -
+R M 2053 o - Ap 13 3 -1 -
+R M 2053 o - May 25 2 0 -
+R M 2054 o - Ap 5 3 -1 -
+R M 2054 o - May 10 2 0 -
+R M 2055 o - Mar 28 3 -1 -
+R M 2055 o - May 2 2 0 -
+R M 2056 o - Mar 12 3 -1 -
+R M 2056 o - Ap 23 2 0 -
+R M 2057 o - Mar 4 3 -1 -
+R M 2057 o - Ap 8 2 0 -
+R M 2058 o - F 17 3 -1 -
+R M 2058 o - Mar 31 2 0 -
+R M 2059 o - F 9 3 -1 -
+R M 2059 o - Mar 23 2 0 -
+R M 2060 o - F 1 3 -1 -
+R M 2060 o - Mar 7 2 0 -
+R M 2061 o - Ja 16 3 -1 -
+R M 2061 o - F 27 2 0 -
+R M 2062 o - Ja 8 3 -1 -
+R M 2062 o - F 12 2 0 -
+R M 2062 o - D 31 3 -1 -
+R M 2063 o - F 4 2 0 -
+R M 2063 o - D 16 3 -1 -
+R M 2064 o - Ja 27 2 0 -
+R M 2064 o - D 7 3 -1 -
+R M 2065 o - Ja 11 2 0 -
+R M 2065 o - N 22 3 -1 -
+R M 2066 o - Ja 3 2 0 -
+R M 2066 o - N 14 3 -1 -
+R M 2066 o - D 26 2 0 -
+R M 2067 o - N 6 3 -1 -
+R M 2067 o - D 11 2 0 -
+R M 2068 o - O 21 3 -1 -
+R M 2068 o - D 2 2 0 -
+R M 2069 o - O 13 3 -1 -
+R M 2069 o - N 17 2 0 -
+R M 2070 o - O 5 3 -1 -
+R M 2070 o - N 9 2 0 -
+R M 2071 o - S 20 3 -1 -
+R M 2071 o - N 1 2 0 -
+R M 2072 o - S 11 3 -1 -
+R M 2072 o - O 16 2 0 -
+R M 2073 o - Au 27 3 -1 -
+R M 2073 o - O 8 2 0 -
+R M 2074 o - Au 19 3 -1 -
+R M 2074 o - S 30 2 0 -
+R M 2075 o - Au 11 3 -1 -
+R M 2075 o - S 15 2 0 -
+R M 2076 o - Jul 26 3 -1 -
+R M 2076 o - S 6 2 0 -
+R M 2077 o - Jul 18 3 -1 -
+R M 2077 o - Au 22 2 0 -
+R M 2078 o - Jul 10 3 -1 -
+R M 2078 o - Au 14 2 0 -
+R M 2079 o - Jun 25 3 -1 -
+R M 2079 o - Au 6 2 0 -
+R M 2080 o - Jun 16 3 -1 -
+R M 2080 o - Jul 21 2 0 -
+R M 2081 o - Jun 1 3 -1 -
+R M 2081 o - Jul 13 2 0 -
+R M 2082 o - May 24 3 -1 -
+R M 2082 o - Jun 28 2 0 -
+R M 2083 o - May 16 3 -1 -
+R M 2083 o - Jun 20 2 0 -
+R M 2084 o - Ap 30 3 -1 -
+R M 2084 o - Jun 11 2 0 -
+R M 2085 o - Ap 22 3 -1 -
+R M 2085 o - May 27 2 0 -
+R M 2086 o - Ap 14 3 -1 -
+R M 2086 o - May 19 2 0 -
+R M 2087 o - Mar 30 3 -1 -
+R M 2087 o - May 11 2 0 -
+R NA 1994 o - Mar 21 0 -1 WAT
+R NA 1994 2017 - S Su>=1 2 0 CAT
+R NA 1995 2017 - Ap Su>=1 2 -1 WAT
+R SA 1942 1943 - S Su>=15 2 1 -
+R SA 1943 1944 - Mar Su>=15 2 0 -
+R SD 1970 o - May 1 0 1 S
+R SD 1970 1985 - O 15 0 0 -
+R SD 1971 o - Ap 30 0 1 S
+R SD 1972 1985 - Ap lastSu 0 1 S
+R n 1939 o - Ap 15 23s 1 S
+R n 1939 o - N 18 23s 0 -
+R n 1940 o - F 25 23s 1 S
+R n 1941 o - O 6 0 0 -
+R n 1942 o - Mar 9 0 1 S
+R n 1942 o - N 2 3 0 -
+R n 1943 o - Mar 29 2 1 S
+R n 1943 o - Ap 17 2 0 -
+R n 1943 o - Ap 25 2 1 S
+R n 1943 o - O 4 2 0 -
+R n 1944 1945 - Ap M>=1 2 1 S
+R n 1944 o - O 8 0 0 -
+R n 1945 o - S 16 0 0 -
+R n 1977 o - Ap 30 0s 1 S
+R n 1977 o - S 24 0s 0 -
+R n 1978 o - May 1 0s 1 S
+R n 1978 o - O 1 0s 0 -
+R n 1988 o - Jun 1 0s 1 S
+R n 1988 1990 - S lastSu 0s 0 -
+R n 1989 o - Mar 26 0s 1 S
+R n 1990 o - May 1 0s 1 S
+R n 2005 o - May 1 0s 1 S
+R n 2005 o - S 30 1s 0 -
+R n 2006 2008 - Mar lastSu 2s 1 S
+R n 2006 2008 - O lastSu 2s 0 -
+R Tr 2005 ma - Mar lastSu 1u 2 +02
+R Tr 2004 ma - O lastSu 1u 0 +00
+R AM 2011 o - Mar lastSu 2s 1 -
+R AM 2011 o - O lastSu 2s 0 -
+R AZ 1997 2015 - Mar lastSu 4 1 -
+R AZ 1997 2015 - O lastSu 5 0 -
+R BD 2009 o - Jun 19 23 1 -
+R BD 2009 o - D 31 24 0 -
+R Sh 1919 o - Ap 12 24 1 D
+R Sh 1919 o - S 30 24 0 S
+R Sh 1940 o - Jun 1 0 1 D
+R Sh 1940 o - O 12 24 0 S
+R Sh 1941 o - Mar 15 0 1 D
+R Sh 1941 o - N 1 24 0 S
+R Sh 1942 o - Ja 31 0 1 D
+R Sh 1945 o - S 1 24 0 S
+R Sh 1946 o - May 15 0 1 D
+R Sh 1946 o - S 30 24 0 S
+R Sh 1947 o - Ap 15 0 1 D
+R Sh 1947 o - O 31 24 0 S
+R Sh 1948 1949 - May 1 0 1 D
+R Sh 1948 1949 - S 30 24 0 S
+R CN 1986 o - May 4 2 1 D
+R CN 1986 1991 - S Su>=11 2 0 S
+R CN 1987 1991 - Ap Su>=11 2 1 D
+R HK 1946 o - Ap 21 0 1 S
+R HK 1946 o - D 1 3:30s 0 -
+R HK 1947 o - Ap 13 3:30s 1 S
+R HK 1947 o - N 30 3:30s 0 -
+R HK 1948 o - May 2 3:30s 1 S
+R HK 1948 1952 - O Su>=28 3:30s 0 -
+R HK 1949 1953 - Ap Su>=1 3:30 1 S
+R HK 1953 1964 - O Su>=31 3:30 0 -
+R HK 1954 1964 - Mar Su>=18 3:30 1 S
+R HK 1965 1976 - Ap Su>=16 3:30 1 S
+R HK 1965 1976 - O Su>=16 3:30 0 -
+R HK 1973 o - D 30 3:30 1 S
+R HK 1979 o - May 13 3:30 1 S
+R HK 1979 o - O 21 3:30 0 -
+R f 1946 o - May 15 0 1 D
+R f 1946 o - O 1 0 0 S
+R f 1947 o - Ap 15 0 1 D
+R f 1947 o - N 1 0 0 S
+R f 1948 1951 - May 1 0 1 D
+R f 1948 1951 - O 1 0 0 S
+R f 1952 o - Mar 1 0 1 D
+R f 1952 1954 - N 1 0 0 S
+R f 1953 1959 - Ap 1 0 1 D
+R f 1955 1961 - O 1 0 0 S
+R f 1960 1961 - Jun 1 0 1 D
+R f 1974 1975 - Ap 1 0 1 D
+R f 1974 1975 - O 1 0 0 S
+R f 1979 o - Jul 1 0 1 D
+R f 1979 o - O 1 0 0 S
+R _ 1942 1943 - Ap 30 23 1 -
+R _ 1942 o - N 17 23 0 -
+R _ 1943 o - S 30 23 0 S
+R _ 1946 o - Ap 30 23s 1 D
+R _ 1946 o - S 30 23s 0 S
+R _ 1947 o - Ap 19 23s 1 D
+R _ 1947 o - N 30 23s 0 S
+R _ 1948 o - May 2 23s 1 D
+R _ 1948 o - O 31 23s 0 S
+R _ 1949 1950 - Ap Sa>=1 23s 1 D
+R _ 1949 1950 - O lastSa 23s 0 S
+R _ 1951 o - Mar 31 23s 1 D
+R _ 1951 o - O 28 23s 0 S
+R _ 1952 1953 - Ap Sa>=1 23s 1 D
+R _ 1952 o - N 1 23s 0 S
+R _ 1953 1954 - O lastSa 23s 0 S
+R _ 1954 1956 - Mar Sa>=17 23s 1 D
+R _ 1955 o - N 5 23s 0 S
+R _ 1956 1964 - N Su>=1 3:30 0 S
+R _ 1957 1964 - Mar Su>=18 3:30 1 D
+R _ 1965 1973 - Ap Su>=16 3:30 1 D
+R _ 1965 1966 - O Su>=16 2:30 0 S
+R _ 1967 1976 - O Su>=16 3:30 0 S
+R _ 1973 o - D 30 3:30 1 D
+R _ 1975 1976 - Ap Su>=16 3:30 1 D
+R _ 1979 o - May 13 3:30 1 D
+R _ 1979 o - O Su>=16 3:30 0 S
+R CY 1975 o - Ap 13 0 1 S
+R CY 1975 o - O 12 0 0 -
+R CY 1976 o - May 15 0 1 S
+R CY 1976 o - O 11 0 0 -
+R CY 1977 1980 - Ap Su>=1 0 1 S
+R CY 1977 o - S 25 0 0 -
+R CY 1978 o - O 2 0 0 -
+R CY 1979 1997 - S lastSu 0 0 -
+R CY 1981 1998 - Mar lastSu 0 1 S
+R i 1910 o - Ja 1 0 0 -
+R i 1977 o - Mar 21 23 1 -
+R i 1977 o - O 20 24 0 -
+R i 1978 o - Mar 24 24 1 -
+R i 1978 o - Au 5 1 0 -
+R i 1979 o - May 26 24 1 -
+R i 1979 o - S 18 24 0 -
+R i 1980 o - Mar 20 24 1 -
+R i 1980 o - S 22 24 0 -
+R i 1991 o - May 2 24 1 -
+R i 1992 1995 - Mar 21 24 1 -
+R i 1991 1995 - S 21 24 0 -
+R i 1996 o - Mar 20 24 1 -
+R i 1996 o - S 20 24 0 -
+R i 1997 1999 - Mar 21 24 1 -
+R i 1997 1999 - S 21 24 0 -
+R i 2000 o - Mar 20 24 1 -
+R i 2000 o - S 20 24 0 -
+R i 2001 2003 - Mar 21 24 1 -
+R i 2001 2003 - S 21 24 0 -
+R i 2004 o - Mar 20 24 1 -
+R i 2004 o - S 20 24 0 -
+R i 2005 o - Mar 21 24 1 -
+R i 2005 o - S 21 24 0 -
+R i 2008 o - Mar 20 24 1 -
+R i 2008 o - S 20 24 0 -
+R i 2009 2011 - Mar 21 24 1 -
+R i 2009 2011 - S 21 24 0 -
+R i 2012 o - Mar 20 24 1 -
+R i 2012 o - S 20 24 0 -
+R i 2013 2015 - Mar 21 24 1 -
+R i 2013 2015 - S 21 24 0 -
+R i 2016 o - Mar 20 24 1 -
+R i 2016 o - S 20 24 0 -
+R i 2017 2019 - Mar 21 24 1 -
+R i 2017 2019 - S 21 24 0 -
+R i 2020 o - Mar 20 24 1 -
+R i 2020 o - S 20 24 0 -
+R i 2021 2022 - Mar 21 24 1 -
+R i 2021 2022 - S 21 24 0 -
+R IQ 1982 o - May 1 0 1 -
+R IQ 1982 1984 - O 1 0 0 -
+R IQ 1983 o - Mar 31 0 1 -
+R IQ 1984 1985 - Ap 1 0 1 -
+R IQ 1985 1990 - S lastSu 1s 0 -
+R IQ 1986 1990 - Mar lastSu 1s 1 -
+R IQ 1991 2007 - Ap 1 3s 1 -
+R IQ 1991 2007 - O 1 3s 0 -
+R Z 1940 o - May 31 24u 1 D
+R Z 1940 o - S 30 24u 0 S
+R Z 1940 o - N 16 24u 1 D
+R Z 1942 1946 - O 31 24u 0 S
+R Z 1943 1944 - Mar 31 24u 1 D
+R Z 1945 1946 - Ap 15 24u 1 D
+R Z 1948 o - May 22 24u 2 DD
+R Z 1948 o - Au 31 24u 1 D
+R Z 1948 1949 - O 31 24u 0 S
+R Z 1949 o - Ap 30 24u 1 D
+R Z 1950 o - Ap 15 24u 1 D
+R Z 1950 o - S 14 24u 0 S
+R Z 1951 o - Mar 31 24u 1 D
+R Z 1951 o - N 10 24u 0 S
+R Z 1952 o - Ap 19 24u 1 D
+R Z 1952 o - O 18 24u 0 S
+R Z 1953 o - Ap 11 24u 1 D
+R Z 1953 o - S 12 24u 0 S
+R Z 1954 o - Jun 12 24u 1 D
+R Z 1954 o - S 11 24u 0 S
+R Z 1955 o - Jun 11 24u 1 D
+R Z 1955 o - S 10 24u 0 S
+R Z 1956 o - Jun 2 24u 1 D
+R Z 1956 o - S 29 24u 0 S
+R Z 1957 o - Ap 27 24u 1 D
+R Z 1957 o - S 21 24u 0 S
+R Z 1974 o - Jul 6 24 1 D
+R Z 1974 o - O 12 24 0 S
+R Z 1975 o - Ap 19 24 1 D
+R Z 1975 o - Au 30 24 0 S
+R Z 1980 o - Au 2 24s 1 D
+R Z 1980 o - S 13 24s 0 S
+R Z 1984 o - May 5 24s 1 D
+R Z 1984 o - Au 25 24s 0 S
+R Z 1985 o - Ap 13 24 1 D
+R Z 1985 o - Au 31 24 0 S
+R Z 1986 o - May 17 24 1 D
+R Z 1986 o - S 6 24 0 S
+R Z 1987 o - Ap 14 24 1 D
+R Z 1987 o - S 12 24 0 S
+R Z 1988 o - Ap 9 24 1 D
+R Z 1988 o - S 3 24 0 S
+R Z 1989 o - Ap 29 24 1 D
+R Z 1989 o - S 2 24 0 S
+R Z 1990 o - Mar 24 24 1 D
+R Z 1990 o - Au 25 24 0 S
+R Z 1991 o - Mar 23 24 1 D
+R Z 1991 o - Au 31 24 0 S
+R Z 1992 o - Mar 28 24 1 D
+R Z 1992 o - S 5 24 0 S
+R Z 1993 o - Ap 2 0 1 D
+R Z 1993 o - S 5 0 0 S
+R Z 1994 o - Ap 1 0 1 D
+R Z 1994 o - Au 28 0 0 S
+R Z 1995 o - Mar 31 0 1 D
+R Z 1995 o - S 3 0 0 S
+R Z 1996 o - Mar 14 24 1 D
+R Z 1996 o - S 15 24 0 S
+R Z 1997 o - Mar 20 24 1 D
+R Z 1997 o - S 13 24 0 S
+R Z 1998 o - Mar 20 0 1 D
+R Z 1998 o - S 6 0 0 S
+R Z 1999 o - Ap 2 2 1 D
+R Z 1999 o - S 3 2 0 S
+R Z 2000 o - Ap 14 2 1 D
+R Z 2000 o - O 6 1 0 S
+R Z 2001 o - Ap 9 1 1 D
+R Z 2001 o - S 24 1 0 S
+R Z 2002 o - Mar 29 1 1 D
+R Z 2002 o - O 7 1 0 S
+R Z 2003 o - Mar 28 1 1 D
+R Z 2003 o - O 3 1 0 S
+R Z 2004 o - Ap 7 1 1 D
+R Z 2004 o - S 22 1 0 S
+R Z 2005 2012 - Ap F<=1 2 1 D
+R Z 2005 o - O 9 2 0 S
+R Z 2006 o - O 1 2 0 S
+R Z 2007 o - S 16 2 0 S
+R Z 2008 o - O 5 2 0 S
+R Z 2009 o - S 27 2 0 S
+R Z 2010 o - S 12 2 0 S
+R Z 2011 o - O 2 2 0 S
+R Z 2012 o - S 23 2 0 S
+R Z 2013 ma - Mar F>=23 2 1 D
+R Z 2013 ma - O lastSu 2 0 S
+R JP 1948 o - May Sa>=1 24 1 D
+R JP 1948 1951 - S Sa>=8 25 0 S
+R JP 1949 o - Ap Sa>=1 24 1 D
+R JP 1950 1951 - May Sa>=1 24 1 D
+R J 1973 o - Jun 6 0 1 S
+R J 1973 1975 - O 1 0 0 -
+R J 1974 1977 - May 1 0 1 S
+R J 1976 o - N 1 0 0 -
+R J 1977 o - O 1 0 0 -
+R J 1978 o - Ap 30 0 1 S
+R J 1978 o - S 30 0 0 -
+R J 1985 o - Ap 1 0 1 S
+R J 1985 o - O 1 0 0 -
+R J 1986 1988 - Ap F>=1 0 1 S
+R J 1986 1990 - O F>=1 0 0 -
+R J 1989 o - May 8 0 1 S
+R J 1990 o - Ap 27 0 1 S
+R J 1991 o - Ap 17 0 1 S
+R J 1991 o - S 27 0 0 -
+R J 1992 o - Ap 10 0 1 S
+R J 1992 1993 - O F>=1 0 0 -
+R J 1993 1998 - Ap F>=1 0 1 S
+R J 1994 o - S F>=15 0 0 -
+R J 1995 1998 - S F>=15 0s 0 -
+R J 1999 o - Jul 1 0s 1 S
+R J 1999 2002 - S lastF 0s 0 -
+R J 2000 2001 - Mar lastTh 0s 1 S
+R J 2002 2012 - Mar lastTh 24 1 S
+R J 2003 o - O 24 0s 0 -
+R J 2004 o - O 15 0s 0 -
+R J 2005 o - S lastF 0s 0 -
+R J 2006 2011 - O lastF 0s 0 -
+R J 2013 o - D 20 0 0 -
+R J 2014 2021 - Mar lastTh 24 1 S
+R J 2014 2022 - O lastF 0s 0 -
+R J 2022 o - F lastTh 24 1 S
+R KG 1992 1996 - Ap Su>=7 0s 1 -
+R KG 1992 1996 - S lastSu 0 0 -
+R KG 1997 2005 - Mar lastSu 2:30 1 -
+R KG 1997 2004 - O lastSu 2:30 0 -
+R KR 1948 o - Jun 1 0 1 D
+R KR 1948 o - S 12 24 0 S
+R KR 1949 o - Ap 3 0 1 D
+R KR 1949 1951 - S Sa>=7 24 0 S
+R KR 1950 o - Ap 1 0 1 D
+R KR 1951 o - May 6 0 1 D
+R KR 1955 o - May 5 0 1 D
+R KR 1955 o - S 8 24 0 S
+R KR 1956 o - May 20 0 1 D
+R KR 1956 o - S 29 24 0 S
+R KR 1957 1960 - May Su>=1 0 1 D
+R KR 1957 1960 - S Sa>=17 24 0 S
+R KR 1987 1988 - May Su>=8 2 1 D
+R KR 1987 1988 - O Su>=8 3 0 S
+R l 1920 o - Mar 28 0 1 S
+R l 1920 o - O 25 0 0 -
+R l 1921 o - Ap 3 0 1 S
+R l 1921 o - O 3 0 0 -
+R l 1922 o - Mar 26 0 1 S
+R l 1922 o - O 8 0 0 -
+R l 1923 o - Ap 22 0 1 S
+R l 1923 o - S 16 0 0 -
+R l 1957 1961 - May 1 0 1 S
+R l 1957 1961 - O 1 0 0 -
+R l 1972 o - Jun 22 0 1 S
+R l 1972 1977 - O 1 0 0 -
+R l 1973 1977 - May 1 0 1 S
+R l 1978 o - Ap 30 0 1 S
+R l 1978 o - S 30 0 0 -
+R l 1984 1987 - May 1 0 1 S
+R l 1984 1991 - O 16 0 0 -
+R l 1988 o - Jun 1 0 1 S
+R l 1989 o - May 10 0 1 S
+R l 1990 1992 - May 1 0 1 S
+R l 1992 o - O 4 0 0 -
+R l 1993 ma - Mar lastSu 0 1 S
+R l 1993 1998 - S lastSu 0 0 -
+R l 1999 ma - O lastSu 0 0 -
+R NB 1935 1941 - S 14 0 0:20 -
+R NB 1935 1941 - D 14 0 0 -
+R X 1983 1984 - Ap 1 0 1 -
+R X 1983 o - O 1 0 0 -
+R X 1985 1998 - Mar lastSu 0 1 -
+R X 1984 1998 - S lastSu 0 0 -
+R X 2001 o - Ap lastSa 2 1 -
+R X 2001 2006 - S lastSa 2 0 -
+R X 2002 2006 - Mar lastSa 2 1 -
+R X 2015 2016 - Mar lastSa 2 1 -
+R X 2015 2016 - S lastSa 0 0 -
+R PK 2002 o - Ap Su>=2 0 1 S
+R PK 2002 o - O Su>=2 0 0 -
+R PK 2008 o - Jun 1 0 1 S
+R PK 2008 2009 - N 1 0 0 -
+R PK 2009 o - Ap 15 0 1 S
+R P 1999 2005 - Ap F>=15 0 1 S
+R P 1999 2003 - O F>=15 0 0 -
+R P 2004 o - O 1 1 0 -
+R P 2005 o - O 4 2 0 -
+R P 2006 2007 - Ap 1 0 1 S
+R P 2006 o - S 22 0 0 -
+R P 2007 o - S 13 2 0 -
+R P 2008 2009 - Mar lastF 0 1 S
+R P 2008 o - S 1 0 0 -
+R P 2009 o - S 4 1 0 -
+R P 2010 o - Mar 26 0 1 S
+R P 2010 o - Au 11 0 0 -
+R P 2011 o - Ap 1 0:1 1 S
+R P 2011 o - Au 1 0 0 -
+R P 2011 o - Au 30 0 1 S
+R P 2011 o - S 30 0 0 -
+R P 2012 2014 - Mar lastTh 24 1 S
+R P 2012 o - S 21 1 0 -
+R P 2013 o - S 27 0 0 -
+R P 2014 o - O 24 0 0 -
+R P 2015 o - Mar 28 0 1 S
+R P 2015 o - O 23 1 0 -
+R P 2016 2018 - Mar Sa<=30 1 1 S
+R P 2016 2018 - O Sa<=30 1 0 -
+R P 2019 o - Mar 29 0 1 S
+R P 2019 o - O Sa<=30 0 0 -
+R P 2020 2021 - Mar Sa<=30 0 1 S
+R P 2020 o - O 24 1 0 -
+R P 2021 o - O 29 1 0 -
+R P 2022 o - Mar 27 0 1 S
+R P 2022 2035 - O Sa<=30 2 0 -
+R P 2023 o - Ap 29 2 1 S
+R P 2024 o - Ap 20 2 1 S
+R P 2025 o - Ap 12 2 1 S
+R P 2026 2054 - Mar Sa<=30 2 1 S
+R P 2036 o - O 18 2 0 -
+R P 2037 o - O 10 2 0 -
+R P 2038 o - S 25 2 0 -
+R P 2039 o - S 17 2 0 -
+R P 2040 o - S 1 2 0 -
+R P 2040 o - O 20 2 1 S
+R P 2040 2067 - O Sa<=30 2 0 -
+R P 2041 o - Au 24 2 0 -
+R P 2041 o - O 5 2 1 S
+R P 2042 o - Au 16 2 0 -
+R P 2042 o - S 27 2 1 S
+R P 2043 o - Au 1 2 0 -
+R P 2043 o - S 19 2 1 S
+R P 2044 o - Jul 23 2 0 -
+R P 2044 o - S 3 2 1 S
+R P 2045 o - Jul 15 2 0 -
+R P 2045 o - Au 26 2 1 S
+R P 2046 o - Jun 30 2 0 -
+R P 2046 o - Au 18 2 1 S
+R P 2047 o - Jun 22 2 0 -
+R P 2047 o - Au 3 2 1 S
+R P 2048 o - Jun 6 2 0 -
+R P 2048 o - Jul 25 2 1 S
+R P 2049 o - May 29 2 0 -
+R P 2049 o - Jul 10 2 1 S
+R P 2050 o - May 21 2 0 -
+R P 2050 o - Jul 2 2 1 S
+R P 2051 o - May 6 2 0 -
+R P 2051 o - Jun 24 2 1 S
+R P 2052 o - Ap 27 2 0 -
+R P 2052 o - Jun 8 2 1 S
+R P 2053 o - Ap 12 2 0 -
+R P 2053 o - May 31 2 1 S
+R P 2054 o - Ap 4 2 0 -
+R P 2054 o - May 23 2 1 S
+R P 2055 o - May 8 2 1 S
+R P 2056 o - Ap 29 2 1 S
+R P 2057 o - Ap 14 2 1 S
+R P 2058 o - Ap 6 2 1 S
+R P 2059 ma - Mar Sa<=30 2 1 S
+R P 2068 o - O 20 2 0 -
+R P 2069 o - O 12 2 0 -
+R P 2070 o - O 4 2 0 -
+R P 2071 o - S 19 2 0 -
+R P 2072 o - S 10 2 0 -
+R P 2072 o - O 22 2 1 S
+R P 2072 ma - O Sa<=30 2 0 -
+R P 2073 o - S 2 2 0 -
+R P 2073 o - O 14 2 1 S
+R P 2074 o - Au 18 2 0 -
+R P 2074 o - O 6 2 1 S
+R P 2075 o - Au 10 2 0 -
+R P 2075 o - S 21 2 1 S
+R P 2076 o - Jul 25 2 0 -
+R P 2076 o - S 12 2 1 S
+R P 2077 o - Jul 17 2 0 -
+R P 2077 o - S 4 2 1 S
+R P 2078 o - Jul 9 2 0 -
+R P 2078 o - Au 20 2 1 S
+R P 2079 o - Jun 24 2 0 -
+R P 2079 o - Au 12 2 1 S
+R P 2080 o - Jun 15 2 0 -
+R P 2080 o - Jul 27 2 1 S
+R P 2081 o - Jun 7 2 0 -
+R P 2081 o - Jul 19 2 1 S
+R P 2082 o - May 23 2 0 -
+R P 2082 o - Jul 11 2 1 S
+R P 2083 o - May 15 2 0 -
+R P 2083 o - Jun 26 2 1 S
+R P 2084 o - Ap 29 2 0 -
+R P 2084 o - Jun 17 2 1 S
+R P 2085 o - Ap 21 2 0 -
+R P 2085 o - Jun 9 2 1 S
+R P 2086 o - Ap 13 2 0 -
+R P 2086 o - May 25 2 1 S
+R PH 1936 o - O 31 24 1 D
+R PH 1937 o - Ja 15 24 0 S
+R PH 1941 o - D 15 24 1 D
+R PH 1945 o - N 30 24 0 S
+R PH 1954 o - Ap 11 24 1 D
+R PH 1954 o - Jun 4 24 0 S
+R PH 1977 o - Mar 27 24 1 D
+R PH 1977 o - S 21 24 0 S
+R PH 1990 o - May 21 0 1 D
+R PH 1990 o - Jul 28 24 0 S
+R S 1920 1923 - Ap Su>=15 2 1 S
+R S 1920 1923 - O Su>=1 2 0 -
+R S 1962 o - Ap 29 2 1 S
+R S 1962 o - O 1 2 0 -
+R S 1963 1965 - May 1 2 1 S
+R S 1963 o - S 30 2 0 -
+R S 1964 o - O 1 2 0 -
+R S 1965 o - S 30 2 0 -
+R S 1966 o - Ap 24 2 1 S
+R S 1966 1976 - O 1 2 0 -
+R S 1967 1978 - May 1 2 1 S
+R S 1977 1978 - S 1 2 0 -
+R S 1983 1984 - Ap 9 2 1 S
+R S 1983 1984 - O 1 2 0 -
+R S 1986 o - F 16 2 1 S
+R S 1986 o - O 9 2 0 -
+R S 1987 o - Mar 1 2 1 S
+R S 1987 1988 - O 31 2 0 -
+R S 1988 o - Mar 15 2 1 S
+R S 1989 o - Mar 31 2 1 S
+R S 1989 o - O 1 2 0 -
+R S 1990 o - Ap 1 2 1 S
+R S 1990 o - S 30 2 0 -
+R S 1991 o - Ap 1 0 1 S
+R S 1991 1992 - O 1 0 0 -
+R S 1992 o - Ap 8 0 1 S
+R S 1993 o - Mar 26 0 1 S
+R S 1993 o - S 25 0 0 -
+R S 1994 1996 - Ap 1 0 1 S
+R S 1994 2005 - O 1 0 0 -
+R S 1997 1998 - Mar lastM 0 1 S
+R S 1999 2006 - Ap 1 0 1 S
+R S 2006 o - S 22 0 0 -
+R S 2007 o - Mar lastF 0 1 S
+R S 2007 o - N F>=1 0 0 -
+R S 2008 o - Ap F>=1 0 1 S
+R S 2008 o - N 1 0 0 -
+R S 2009 o - Mar lastF 0 1 S
+R S 2010 2011 - Ap F>=1 0 1 S
+R S 2012 2022 - Mar lastF 0 1 S
+R S 2009 2022 - O lastF 0 0 -
+R AU 1917 o - Ja 1 2s 1 D
+R AU 1917 o - Mar lastSu 2s 0 S
+R AU 1942 o - Ja 1 2s 1 D
+R AU 1942 o - Mar lastSu 2s 0 S
+R AU 1942 o - S 27 2s 1 D
+R AU 1943 1944 - Mar lastSu 2s 0 S
+R AU 1943 o - O 3 2s 1 D
+R AW 1974 o - O lastSu 2s 1 D
+R AW 1975 o - Mar Su>=1 2s 0 S
+R AW 1983 o - O lastSu 2s 1 D
+R AW 1984 o - Mar Su>=1 2s 0 S
+R AW 1991 o - N 17 2s 1 D
+R AW 1992 o - Mar Su>=1 2s 0 S
+R AW 2006 o - D 3 2s 1 D
+R AW 2007 2009 - Mar lastSu 2s 0 S
+R AW 2007 2008 - O lastSu 2s 1 D
+R AQ 1971 o - O lastSu 2s 1 D
+R AQ 1972 o - F lastSu 2s 0 S
+R AQ 1989 1991 - O lastSu 2s 1 D
+R AQ 1990 1992 - Mar Su>=1 2s 0 S
+R Ho 1992 1993 - O lastSu 2s 1 D
+R Ho 1993 1994 - Mar Su>=1 2s 0 S
+R AS 1971 1985 - O lastSu 2s 1 D
+R AS 1986 o - O 19 2s 1 D
+R AS 1987 2007 - O lastSu 2s 1 D
+R AS 1972 o - F 27 2s 0 S
+R AS 1973 1985 - Mar Su>=1 2s 0 S
+R AS 1986 1990 - Mar Su>=15 2s 0 S
+R AS 1991 o - Mar 3 2s 0 S
+R AS 1992 o - Mar 22 2s 0 S
+R AS 1993 o - Mar 7 2s 0 S
+R AS 1994 o - Mar 20 2s 0 S
+R AS 1995 2005 - Mar lastSu 2s 0 S
+R AS 2006 o - Ap 2 2s 0 S
+R AS 2007 o - Mar lastSu 2s 0 S
+R AS 2008 ma - Ap Su>=1 2s 0 S
+R AS 2008 ma - O Su>=1 2s 1 D
+R AT 1916 o - O Su>=1 2s 1 D
+R AT 1917 o - Mar lastSu 2s 0 S
+R AT 1917 1918 - O Su>=22 2s 1 D
+R AT 1918 1919 - Mar Su>=1 2s 0 S
+R AT 1967 o - O Su>=1 2s 1 D
+R AT 1968 o - Mar Su>=29 2s 0 S
+R AT 1968 1985 - O lastSu 2s 1 D
+R AT 1969 1971 - Mar Su>=8 2s 0 S
+R AT 1972 o - F lastSu 2s 0 S
+R AT 1973 1981 - Mar Su>=1 2s 0 S
+R AT 1982 1983 - Mar lastSu 2s 0 S
+R AT 1984 1986 - Mar Su>=1 2s 0 S
+R AT 1986 o - O Su>=15 2s 1 D
+R AT 1987 1990 - Mar Su>=15 2s 0 S
+R AT 1987 o - O Su>=22 2s 1 D
+R AT 1988 1990 - O lastSu 2s 1 D
+R AT 1991 1999 - O Su>=1 2s 1 D
+R AT 1991 2005 - Mar lastSu 2s 0 S
+R AT 2000 o - Au lastSu 2s 1 D
+R AT 2001 ma - O Su>=1 2s 1 D
+R AT 2006 o - Ap Su>=1 2s 0 S
+R AT 2007 o - Mar lastSu 2s 0 S
+R AT 2008 ma - Ap Su>=1 2s 0 S
+R AV 1971 1985 - O lastSu 2s 1 D
+R AV 1972 o - F lastSu 2s 0 S
+R AV 1973 1985 - Mar Su>=1 2s 0 S
+R AV 1986 1990 - Mar Su>=15 2s 0 S
+R AV 1986 1987 - O Su>=15 2s 1 D
+R AV 1988 1999 - O lastSu 2s 1 D
+R AV 1991 1994 - Mar Su>=1 2s 0 S
+R AV 1995 2005 - Mar lastSu 2s 0 S
+R AV 2000 o - Au lastSu 2s 1 D
+R AV 2001 2007 - O lastSu 2s 1 D
+R AV 2006 o - Ap Su>=1 2s 0 S
+R AV 2007 o - Mar lastSu 2s 0 S
+R AV 2008 ma - Ap Su>=1 2s 0 S
+R AV 2008 ma - O Su>=1 2s 1 D
+R AN 1971 1985 - O lastSu 2s 1 D
+R AN 1972 o - F 27 2s 0 S
+R AN 1973 1981 - Mar Su>=1 2s 0 S
+R AN 1982 o - Ap Su>=1 2s 0 S
+R AN 1983 1985 - Mar Su>=1 2s 0 S
+R AN 1986 1989 - Mar Su>=15 2s 0 S
+R AN 1986 o - O 19 2s 1 D
+R AN 1987 1999 - O lastSu 2s 1 D
+R AN 1990 1995 - Mar Su>=1 2s 0 S
+R AN 1996 2005 - Mar lastSu 2s 0 S
+R AN 2000 o - Au lastSu 2s 1 D
+R AN 2001 2007 - O lastSu 2s 1 D
+R AN 2006 o - Ap Su>=1 2s 0 S
+R AN 2007 o - Mar lastSu 2s 0 S
+R AN 2008 ma - Ap Su>=1 2s 0 S
+R AN 2008 ma - O Su>=1 2s 1 D
+R LH 1981 1984 - O lastSu 2 1 -
+R LH 1982 1985 - Mar Su>=1 2 0 -
+R LH 1985 o - O lastSu 2 0:30 -
+R LH 1986 1989 - Mar Su>=15 2 0 -
+R LH 1986 o - O 19 2 0:30 -
+R LH 1987 1999 - O lastSu 2 0:30 -
+R LH 1990 1995 - Mar Su>=1 2 0 -
+R LH 1996 2005 - Mar lastSu 2 0 -
+R LH 2000 o - Au lastSu 2 0:30 -
+R LH 2001 2007 - O lastSu 2 0:30 -
+R LH 2006 o - Ap Su>=1 2 0 -
+R LH 2007 o - Mar lastSu 2 0 -
+R LH 2008 ma - Ap Su>=1 2 0 -
+R LH 2008 ma - O Su>=1 2 0:30 -
+R FJ 1998 1999 - N Su>=1 2 1 -
+R FJ 1999 2000 - F lastSu 3 0 -
+R FJ 2009 o - N 29 2 1 -
+R FJ 2010 o - Mar lastSu 3 0 -
+R FJ 2010 2013 - O Su>=21 2 1 -
+R FJ 2011 o - Mar Su>=1 3 0 -
+R FJ 2012 2013 - Ja Su>=18 3 0 -
+R FJ 2014 o - Ja Su>=18 2 0 -
+R FJ 2014 2018 - N Su>=1 2 1 -
+R FJ 2015 2021 - Ja Su>=12 3 0 -
+R FJ 2019 o - N Su>=8 2 1 -
+R FJ 2020 o - D 20 2 1 -
+R Gu 1959 o - Jun 27 2 1 D
+R Gu 1961 o - Ja 29 2 0 S
+R Gu 1967 o - S 1 2 1 D
+R Gu 1969 o - Ja 26 0:1 0 S
+R Gu 1969 o - Jun 22 2 1 D
+R Gu 1969 o - Au 31 2 0 S
+R Gu 1970 1971 - Ap lastSu 2 1 D
+R Gu 1970 1971 - S Su>=1 2 0 S
+R Gu 1973 o - D 16 2 1 D
+R Gu 1974 o - F 24 2 0 S
+R Gu 1976 o - May 26 2 1 D
+R Gu 1976 o - Au 22 2:1 0 S
+R Gu 1977 o - Ap 24 2 1 D
+R Gu 1977 o - Au 28 2 0 S
+R NC 1977 1978 - D Su>=1 0 1 -
+R NC 1978 1979 - F 27 0 0 -
+R NC 1996 o - D 1 2s 1 -
+R NC 1997 o - Mar 2 2s 0 -
+R NZ 1927 o - N 6 2 1 S
+R NZ 1928 o - Mar 4 2 0 M
+R NZ 1928 1933 - O Su>=8 2 0:30 S
+R NZ 1929 1933 - Mar Su>=15 2 0 M
+R NZ 1934 1940 - Ap lastSu 2 0 M
+R NZ 1934 1940 - S lastSu 2 0:30 S
+R NZ 1946 o - Ja 1 0 0 S
+R NZ 1974 o - N Su>=1 2s 1 D
+R k 1974 o - N Su>=1 2:45s 1 -
+R NZ 1975 o - F lastSu 2s 0 S
+R k 1975 o - F lastSu 2:45s 0 -
+R NZ 1975 1988 - O lastSu 2s 1 D
+R k 1975 1988 - O lastSu 2:45s 1 -
+R NZ 1976 1989 - Mar Su>=1 2s 0 S
+R k 1976 1989 - Mar Su>=1 2:45s 0 -
+R NZ 1989 o - O Su>=8 2s 1 D
+R k 1989 o - O Su>=8 2:45s 1 -
+R NZ 1990 2006 - O Su>=1 2s 1 D
+R k 1990 2006 - O Su>=1 2:45s 1 -
+R NZ 1990 2007 - Mar Su>=15 2s 0 S
+R k 1990 2007 - Mar Su>=15 2:45s 0 -
+R NZ 2007 ma - S lastSu 2s 1 D
+R k 2007 ma - S lastSu 2:45s 1 -
+R NZ 2008 ma - Ap Su>=1 2s 0 S
+R k 2008 ma - Ap Su>=1 2:45s 0 -
+R CK 1978 o - N 12 0 0:30 -
+R CK 1979 1991 - Mar Su>=1 0 0 -
+R CK 1979 1990 - O lastSu 0 0:30 -
+R WS 2010 o - S lastSu 0 1 -
+R WS 2011 o - Ap Sa>=1 4 0 -
+R WS 2011 o - S lastSa 3 1 -
+R WS 2012 2021 - Ap Su>=1 4 0 -
+R WS 2012 2020 - S lastSu 3 1 -
+R TO 1999 o - O 7 2s 1 -
+R TO 2000 o - Mar 19 2s 0 -
+R TO 2000 2001 - N Su>=1 2 1 -
+R TO 2001 2002 - Ja lastSu 2 0 -
+R TO 2016 o - N Su>=1 2 1 -
+R TO 2017 o - Ja Su>=15 3 0 -
+R VU 1973 o - D 22 12u 1 -
+R VU 1974 o - Mar 30 12u 0 -
+R VU 1983 1991 - S Sa>=22 24 1 -
+R VU 1984 1991 - Mar Sa>=22 24 0 -
+R VU 1992 1993 - Ja Sa>=22 24 0 -
+R VU 1992 o - O Sa>=22 24 1 -
+R G 1916 o - May 21 2s 1 BST
+R G 1916 o - O 1 2s 0 GMT
+R G 1917 o - Ap 8 2s 1 BST
+R G 1917 o - S 17 2s 0 GMT
+R G 1918 o - Mar 24 2s 1 BST
+R G 1918 o - S 30 2s 0 GMT
+R G 1919 o - Mar 30 2s 1 BST
+R G 1919 o - S 29 2s 0 GMT
+R G 1920 o - Mar 28 2s 1 BST
+R G 1920 o - O 25 2s 0 GMT
+R G 1921 o - Ap 3 2s 1 BST
+R G 1921 o - O 3 2s 0 GMT
+R G 1922 o - Mar 26 2s 1 BST
+R G 1922 o - O 8 2s 0 GMT
+R G 1923 o - Ap Su>=16 2s 1 BST
+R G 1923 1924 - S Su>=16 2s 0 GMT
+R G 1924 o - Ap Su>=9 2s 1 BST
+R G 1925 1926 - Ap Su>=16 2s 1 BST
+R G 1925 1938 - O Su>=2 2s 0 GMT
+R G 1927 o - Ap Su>=9 2s 1 BST
+R G 1928 1929 - Ap Su>=16 2s 1 BST
+R G 1930 o - Ap Su>=9 2s 1 BST
+R G 1931 1932 - Ap Su>=16 2s 1 BST
+R G 1933 o - Ap Su>=9 2s 1 BST
+R G 1934 o - Ap Su>=16 2s 1 BST
+R G 1935 o - Ap Su>=9 2s 1 BST
+R G 1936 1937 - Ap Su>=16 2s 1 BST
+R G 1938 o - Ap Su>=9 2s 1 BST
+R G 1939 o - Ap Su>=16 2s 1 BST
+R G 1939 o - N Su>=16 2s 0 GMT
+R G 1940 o - F Su>=23 2s 1 BST
+R G 1941 o - May Su>=2 1s 2 BDST
+R G 1941 1943 - Au Su>=9 1s 1 BST
+R G 1942 1944 - Ap Su>=2 1s 2 BDST
+R G 1944 o - S Su>=16 1s 1 BST
+R G 1945 o - Ap M>=2 1s 2 BDST
+R G 1945 o - Jul Su>=9 1s 1 BST
+R G 1945 1946 - O Su>=2 2s 0 GMT
+R G 1946 o - Ap Su>=9 2s 1 BST
+R G 1947 o - Mar 16 2s 1 BST
+R G 1947 o - Ap 13 1s 2 BDST
+R G 1947 o - Au 10 1s 1 BST
+R G 1947 o - N 2 2s 0 GMT
+R G 1948 o - Mar 14 2s 1 BST
+R G 1948 o - O 31 2s 0 GMT
+R G 1949 o - Ap 3 2s 1 BST
+R G 1949 o - O 30 2s 0 GMT
+R G 1950 1952 - Ap Su>=14 2s 1 BST
+R G 1950 1952 - O Su>=21 2s 0 GMT
+R G 1953 o - Ap Su>=16 2s 1 BST
+R G 1953 1960 - O Su>=2 2s 0 GMT
+R G 1954 o - Ap Su>=9 2s 1 BST
+R G 1955 1956 - Ap Su>=16 2s 1 BST
+R G 1957 o - Ap Su>=9 2s 1 BST
+R G 1958 1959 - Ap Su>=16 2s 1 BST
+R G 1960 o - Ap Su>=9 2s 1 BST
+R G 1961 1963 - Mar lastSu 2s 1 BST
+R G 1961 1968 - O Su>=23 2s 0 GMT
+R G 1964 1967 - Mar Su>=19 2s 1 BST
+R G 1968 o - F 18 2s 1 BST
+R G 1972 1980 - Mar Su>=16 2s 1 BST
+R G 1972 1980 - O Su>=23 2s 0 GMT
+R G 1981 1995 - Mar lastSu 1u 1 BST
+R G 1981 1989 - O Su>=23 1u 0 GMT
+R G 1990 1995 - O Su>=22 1u 0 GMT
+R IE 1971 o - O 31 2u -1 -
+R IE 1972 1980 - Mar Su>=16 2u 0 -
+R IE 1972 1980 - O Su>=23 2u -1 -
+R IE 1981 ma - Mar lastSu 1u 0 -
+R IE 1981 1989 - O Su>=23 1u -1 -
+R IE 1990 1995 - O Su>=22 1u -1 -
+R IE 1996 ma - O lastSu 1u -1 -
+R E 1977 1980 - Ap Su>=1 1u 1 S
+R E 1977 o - S lastSu 1u 0 -
+R E 1978 o - O 1 1u 0 -
+R E 1979 1995 - S lastSu 1u 0 -
+R E 1981 ma - Mar lastSu 1u 1 S
+R E 1996 ma - O lastSu 1u 0 -
+R W- 1977 1980 - Ap Su>=1 1s 1 S
+R W- 1977 o - S lastSu 1s 0 -
+R W- 1978 o - O 1 1s 0 -
+R W- 1979 1995 - S lastSu 1s 0 -
+R W- 1981 ma - Mar lastSu 1s 1 S
+R W- 1996 ma - O lastSu 1s 0 -
+R c 1916 o - Ap 30 23 1 S
+R c 1916 o - O 1 1 0 -
+R c 1917 1918 - Ap M>=15 2s 1 S
+R c 1917 1918 - S M>=15 2s 0 -
+R c 1940 o - Ap 1 2s 1 S
+R c 1942 o - N 2 2s 0 -
+R c 1943 o - Mar 29 2s 1 S
+R c 1943 o - O 4 2s 0 -
+R c 1944 1945 - Ap M>=1 2s 1 S
+R c 1944 o - O 2 2s 0 -
+R c 1945 o - S 16 2s 0 -
+R c 1977 1980 - Ap Su>=1 2s 1 S
+R c 1977 o - S lastSu 2s 0 -
+R c 1978 o - O 1 2s 0 -
+R c 1979 1995 - S lastSu 2s 0 -
+R c 1981 ma - Mar lastSu 2s 1 S
+R c 1996 ma - O lastSu 2s 0 -
+R e 1977 1980 - Ap Su>=1 0 1 S
+R e 1977 o - S lastSu 0 0 -
+R e 1978 o - O 1 0 0 -
+R e 1979 1995 - S lastSu 0 0 -
+R e 1981 ma - Mar lastSu 0 1 S
+R e 1996 ma - O lastSu 0 0 -
+R R 1917 o - Jul 1 23 1 MST
+R R 1917 o - D 28 0 0 MMT
+R R 1918 o - May 31 22 2 MDST
+R R 1918 o - S 16 1 1 MST
+R R 1919 o - May 31 23 2 MDST
+R R 1919 o - Jul 1 0u 1 MSD
+R R 1919 o - Au 16 0 0 MSK
+R R 1921 o - F 14 23 1 MSD
+R R 1921 o - Mar 20 23 2 +05
+R R 1921 o - S 1 0 1 MSD
+R R 1921 o - O 1 0 0 -
+R R 1981 1984 - Ap 1 0 1 S
+R R 1981 1983 - O 1 0 0 -
+R R 1984 1995 - S lastSu 2s 0 -
+R R 1985 2010 - Mar lastSu 2s 1 S
+R R 1996 2010 - O lastSu 2s 0 -
+R q 1940 o - Jun 16 0 1 S
+R q 1942 o - N 2 3 0 -
+R q 1943 o - Mar 29 2 1 S
+R q 1943 o - Ap 10 3 0 -
+R q 1974 o - May 4 0 1 S
+R q 1974 o - O 2 0 0 -
+R q 1975 o - May 1 0 1 S
+R q 1975 o - O 2 0 0 -
+R q 1976 o - May 2 0 1 S
+R q 1976 o - O 3 0 0 -
+R q 1977 o - May 8 0 1 S
+R q 1977 o - O 2 0 0 -
+R q 1978 o - May 6 0 1 S
+R q 1978 o - O 1 0 0 -
+R q 1979 o - May 5 0 1 S
+R q 1979 o - S 30 0 0 -
+R q 1980 o - May 3 0 1 S
+R q 1980 o - O 4 0 0 -
+R q 1981 o - Ap 26 0 1 S
+R q 1981 o - S 27 0 0 -
+R q 1982 o - May 2 0 1 S
+R q 1982 o - O 3 0 0 -
+R q 1983 o - Ap 18 0 1 S
+R q 1983 o - O 1 0 0 -
+R q 1984 o - Ap 1 0 1 S
+R a 1920 o - Ap 5 2s 1 S
+R a 1920 o - S 13 2s 0 -
+R a 1946 o - Ap 14 2s 1 S
+R a 1946 o - O 7 2s 0 -
+R a 1947 1948 - O Su>=1 2s 0 -
+R a 1947 o - Ap 6 2s 1 S
+R a 1948 o - Ap 18 2s 1 S
+R a 1980 o - Ap 6 0 1 S
+R a 1980 o - S 28 0 0 -
+R b 1918 o - Mar 9 0s 1 S
+R b 1918 1919 - O Sa>=1 23s 0 -
+R b 1919 o - Mar 1 23s 1 S
+R b 1920 o - F 14 23s 1 S
+R b 1920 o - O 23 23s 0 -
+R b 1921 o - Mar 14 23s 1 S
+R b 1921 o - O 25 23s 0 -
+R b 1922 o - Mar 25 23s 1 S
+R b 1922 1927 - O Sa>=1 23s 0 -
+R b 1923 o - Ap 21 23s 1 S
+R b 1924 o - Mar 29 23s 1 S
+R b 1925 o - Ap 4 23s 1 S
+R b 1926 o - Ap 17 23s 1 S
+R b 1927 o - Ap 9 23s 1 S
+R b 1928 o - Ap 14 23s 1 S
+R b 1928 1938 - O Su>=2 2s 0 -
+R b 1929 o - Ap 21 2s 1 S
+R b 1930 o - Ap 13 2s 1 S
+R b 1931 o - Ap 19 2s 1 S
+R b 1932 o - Ap 3 2s 1 S
+R b 1933 o - Mar 26 2s 1 S
+R b 1934 o - Ap 8 2s 1 S
+R b 1935 o - Mar 31 2s 1 S
+R b 1936 o - Ap 19 2s 1 S
+R b 1937 o - Ap 4 2s 1 S
+R b 1938 o - Mar 27 2s 1 S
+R b 1939 o - Ap 16 2s 1 S
+R b 1939 o - N 19 2s 0 -
+R b 1940 o - F 25 2s 1 S
+R b 1944 o - S 17 2s 0 -
+R b 1945 o - Ap 2 2s 1 S
+R b 1945 o - S 16 2s 0 -
+R b 1946 o - May 19 2s 1 S
+R b 1946 o - O 7 2s 0 -
+R BG 1979 o - Mar 31 23 1 S
+R BG 1979 o - O 1 1 0 -
+R BG 1980 1982 - Ap Sa>=1 23 1 S
+R BG 1980 o - S 29 1 0 -
+R BG 1981 o - S 27 2 0 -
+R CZ 1945 o - Ap M>=1 2s 1 S
+R CZ 1945 o - O 1 2s 0 -
+R CZ 1946 o - May 6 2s 1 S
+R CZ 1946 1949 - O Su>=1 2s 0 -
+R CZ 1947 1948 - Ap Su>=15 2s 1 S
+R CZ 1949 o - Ap 9 2s 1 S
+R Th 1991 1992 - Mar lastSu 2 1 D
+R Th 1991 1992 - S lastSu 2 0 S
+R Th 1993 2006 - Ap Su>=1 2 1 D
+R Th 1993 2006 - O lastSu 2 0 S
+R Th 2007 ma - Mar Su>=8 2 1 D
+R Th 2007 ma - N Su>=1 2 0 S
+R FI 1942 o - Ap 2 24 1 S
+R FI 1942 o - O 4 1 0 -
+R FI 1981 1982 - Mar lastSu 2 1 S
+R FI 1981 1982 - S lastSu 3 0 -
+R F 1916 o - Jun 14 23s 1 S
+R F 1916 1919 - O Su>=1 23s 0 -
+R F 1917 o - Mar 24 23s 1 S
+R F 1918 o - Mar 9 23s 1 S
+R F 1919 o - Mar 1 23s 1 S
+R F 1920 o - F 14 23s 1 S
+R F 1920 o - O 23 23s 0 -
+R F 1921 o - Mar 14 23s 1 S
+R F 1921 o - O 25 23s 0 -
+R F 1922 o - Mar 25 23s 1 S
+R F 1922 1938 - O Sa>=1 23s 0 -
+R F 1923 o - May 26 23s 1 S
+R F 1924 o - Mar 29 23s 1 S
+R F 1925 o - Ap 4 23s 1 S
+R F 1926 o - Ap 17 23s 1 S
+R F 1927 o - Ap 9 23s 1 S
+R F 1928 o - Ap 14 23s 1 S
+R F 1929 o - Ap 20 23s 1 S
+R F 1930 o - Ap 12 23s 1 S
+R F 1931 o - Ap 18 23s 1 S
+R F 1932 o - Ap 2 23s 1 S
+R F 1933 o - Mar 25 23s 1 S
+R F 1934 o - Ap 7 23s 1 S
+R F 1935 o - Mar 30 23s 1 S
+R F 1936 o - Ap 18 23s 1 S
+R F 1937 o - Ap 3 23s 1 S
+R F 1938 o - Mar 26 23s 1 S
+R F 1939 o - Ap 15 23s 1 S
+R F 1939 o - N 18 23s 0 -
+R F 1940 o - F 25 2 1 S
+R F 1941 o - May 5 0 2 M
+R F 1941 o - O 6 0 1 S
+R F 1942 o - Mar 9 0 2 M
+R F 1942 o - N 2 3 1 S
+R F 1943 o - Mar 29 2 2 M
+R F 1943 o - O 4 3 1 S
+R F 1944 o - Ap 3 2 2 M
+R F 1944 o - O 8 1 1 S
+R F 1945 o - Ap 2 2 2 M
+R F 1945 o - S 16 3 0 -
+R F 1976 o - Mar 28 1 1 S
+R F 1976 o - S 26 1 0 -
+R DE 1946 o - Ap 14 2s 1 S
+R DE 1946 o - O 7 2s 0 -
+R DE 1947 1949 - O Su>=1 2s 0 -
+R DE 1947 o - Ap 6 3s 1 S
+R DE 1947 o - May 11 2s 2 M
+R DE 1947 o - Jun 29 3 1 S
+R DE 1948 o - Ap 18 2s 1 S
+R DE 1949 o - Ap 10 2s 1 S
+R So 1945 o - May 24 2 2 M
+R So 1945 o - S 24 3 1 S
+R So 1945 o - N 18 2s 0 -
+R g 1932 o - Jul 7 0 1 S
+R g 1932 o - S 1 0 0 -
+R g 1941 o - Ap 7 0 1 S
+R g 1942 o - N 2 3 0 -
+R g 1943 o - Mar 30 0 1 S
+R g 1943 o - O 4 0 0 -
+R g 1952 o - Jul 1 0 1 S
+R g 1952 o - N 2 0 0 -
+R g 1975 o - Ap 12 0s 1 S
+R g 1975 o - N 26 0s 0 -
+R g 1976 o - Ap 11 2s 1 S
+R g 1976 o - O 10 2s 0 -
+R g 1977 1978 - Ap Su>=1 2s 1 S
+R g 1977 o - S 26 2s 0 -
+R g 1978 o - S 24 4 0 -
+R g 1979 o - Ap 1 9 1 S
+R g 1979 o - S 29 2 0 -
+R g 1980 o - Ap 1 0 1 S
+R g 1980 o - S 28 0 0 -
+R h 1918 1919 - Ap 15 2 1 S
+R h 1918 1920 - S M>=15 3 0 -
+R h 1920 o - Ap 5 2 1 S
+R h 1945 o - May 1 23 1 S
+R h 1945 o - N 1 1 0 -
+R h 1946 o - Mar 31 2s 1 S
+R h 1946 o - O 7 2 0 -
+R h 1947 1949 - Ap Su>=4 2s 1 S
+R h 1947 1949 - O Su>=1 2s 0 -
+R h 1954 o - May 23 0 1 S
+R h 1954 o - O 3 0 0 -
+R h 1955 o - May 22 2 1 S
+R h 1955 o - O 2 3 0 -
+R h 1956 1957 - Jun Su>=1 2 1 S
+R h 1956 1957 - S lastSu 3 0 -
+R h 1980 o - Ap 6 0 1 S
+R h 1980 o - S 28 1 0 -
+R h 1981 1983 - Mar lastSu 0 1 S
+R h 1981 1983 - S lastSu 1 0 -
+R I 1916 o - Jun 3 24 1 S
+R I 1916 1917 - S 30 24 0 -
+R I 1917 o - Mar 31 24 1 S
+R I 1918 o - Mar 9 24 1 S
+R I 1918 o - O 6 24 0 -
+R I 1919 o - Mar 1 24 1 S
+R I 1919 o - O 4 24 0 -
+R I 1920 o - Mar 20 24 1 S
+R I 1920 o - S 18 24 0 -
+R I 1940 o - Jun 14 24 1 S
+R I 1942 o - N 2 2s 0 -
+R I 1943 o - Mar 29 2s 1 S
+R I 1943 o - O 4 2s 0 -
+R I 1944 o - Ap 2 2s 1 S
+R I 1944 o - S 17 2s 0 -
+R I 1945 o - Ap 2 2 1 S
+R I 1945 o - S 15 1 0 -
+R I 1946 o - Mar 17 2s 1 S
+R I 1946 o - O 6 2s 0 -
+R I 1947 o - Mar 16 0s 1 S
+R I 1947 o - O 5 0s 0 -
+R I 1948 o - F 29 2s 1 S
+R I 1948 o - O 3 2s 0 -
+R I 1966 1968 - May Su>=22 0s 1 S
+R I 1966 o - S 24 24 0 -
+R I 1967 1969 - S Su>=22 0s 0 -
+R I 1969 o - Jun 1 0s 1 S
+R I 1970 o - May 31 0s 1 S
+R I 1970 o - S lastSu 0s 0 -
+R I 1971 1972 - May Su>=22 0s 1 S
+R I 1971 o - S lastSu 0s 0 -
+R I 1972 o - O 1 0s 0 -
+R I 1973 o - Jun 3 0s 1 S
+R I 1973 1974 - S lastSu 0s 0 -
+R I 1974 o - May 26 0s 1 S
+R I 1975 o - Jun 1 0s 1 S
+R I 1975 1977 - S lastSu 0s 0 -
+R I 1976 o - May 30 0s 1 S
+R I 1977 1979 - May Su>=22 0s 1 S
+R I 1978 o - O 1 0s 0 -
+R I 1979 o - S 30 0s 0 -
+R LV 1989 1996 - Mar lastSu 2s 1 S
+R LV 1989 1996 - S lastSu 2s 0 -
+R MT 1973 o - Mar 31 0s 1 S
+R MT 1973 o - S 29 0s 0 -
+R MT 1974 o - Ap 21 0s 1 S
+R MT 1974 o - S 16 0s 0 -
+R MT 1975 1979 - Ap Su>=15 2 1 S
+R MT 1975 1980 - S Su>=15 2 0 -
+R MT 1980 o - Mar 31 2 1 S
+R MD 1997 ma - Mar lastSu 2 1 S
+R MD 1997 ma - O lastSu 3 0 -
+R O 1918 1919 - S 16 2s 0 -
+R O 1919 o - Ap 15 2s 1 S
+R O 1944 o - Ap 3 2s 1 S
+R O 1944 o - O 4 2 0 -
+R O 1945 o - Ap 29 0 1 S
+R O 1945 o - N 1 0 0 -
+R O 1946 o - Ap 14 0s 1 S
+R O 1946 o - O 7 2s 0 -
+R O 1947 o - May 4 2s 1 S
+R O 1947 1949 - O Su>=1 2s 0 -
+R O 1948 o - Ap 18 2s 1 S
+R O 1949 o - Ap 10 2s 1 S
+R O 1957 o - Jun 2 1s 1 S
+R O 1957 1958 - S lastSu 1s 0 -
+R O 1958 o - Mar 30 1s 1 S
+R O 1959 o - May 31 1s 1 S
+R O 1959 1961 - O Su>=1 1s 0 -
+R O 1960 o - Ap 3 1s 1 S
+R O 1961 1964 - May lastSu 1s 1 S
+R O 1962 1964 - S lastSu 1s 0 -
+R p 1916 o - Jun 17 23 1 S
+R p 1916 o - N 1 1 0 -
+R p 1917 1921 - Mar 1 0 1 S
+R p 1917 1921 - O 14 24 0 -
+R p 1924 o - Ap 16 23s 1 S
+R p 1924 o - O 4 23s 0 -
+R p 1926 o - Ap 17 23s 1 S
+R p 1926 1929 - O Sa>=1 23s 0 -
+R p 1927 o - Ap 9 23s 1 S
+R p 1928 o - Ap 14 23s 1 S
+R p 1929 o - Ap 20 23s 1 S
+R p 1931 o - Ap 18 23s 1 S
+R p 1931 1932 - O Sa>=1 23s 0 -
+R p 1932 o - Ap 2 23s 1 S
+R p 1934 o - Ap 7 23s 1 S
+R p 1934 1938 - O Sa>=1 23s 0 -
+R p 1935 o - Mar 30 23s 1 S
+R p 1936 o - Ap 18 23s 1 S
+R p 1937 o - Ap 3 23s 1 S
+R p 1938 o - Mar 26 23s 1 S
+R p 1939 o - Ap 15 23s 1 S
+R p 1939 o - N 18 23s 0 -
+R p 1940 o - F 24 23s 1 S
+R p 1940 o - O 7 23s 0 -
+R p 1941 o - Ap 5 23s 1 S
+R p 1941 o - O 5 23s 0 -
+R p 1942 1945 - Mar Sa>=8 23s 1 S
+R p 1942 o - Ap 25 22s 2 M
+R p 1942 o - Au 15 22s 1 S
+R p 1942 1945 - O Sa>=24 23s 0 -
+R p 1943 o - Ap 17 22s 2 M
+R p 1943 1945 - Au Sa>=25 22s 1 S
+R p 1944 1945 - Ap Sa>=21 22s 2 M
+R p 1946 o - Ap Sa>=1 23s 1 S
+R p 1946 o - O Sa>=1 23s 0 -
+R p 1947 1966 - Ap Su>=1 2s 1 S
+R p 1947 1965 - O Su>=1 2s 0 -
+R p 1976 o - S lastSu 1 0 -
+R p 1977 o - Mar lastSu 0s 1 S
+R p 1977 o - S lastSu 0s 0 -
+R p 1978 1980 - Ap Su>=1 1s 1 S
+R p 1978 o - O 1 1s 0 -
+R p 1979 1980 - S lastSu 1s 0 -
+R p 1981 1986 - Mar lastSu 0s 1 S
+R p 1981 1985 - S lastSu 0s 0 -
+R z 1932 o - May 21 0s 1 S
+R z 1932 1939 - O Su>=1 0s 0 -
+R z 1933 1939 - Ap Su>=2 0s 1 S
+R z 1979 o - May 27 0 1 S
+R z 1979 o - S lastSu 0 0 -
+R z 1980 o - Ap 5 23 1 S
+R z 1980 o - S lastSu 1 0 -
+R z 1991 1993 - Mar lastSu 0s 1 S
+R z 1991 1993 - S lastSu 0s 0 -
+R s 1918 o - Ap 15 23 1 S
+R s 1918 1919 - O 6 24s 0 -
+R s 1919 o - Ap 6 23 1 S
+R s 1924 o - Ap 16 23 1 S
+R s 1924 o - O 4 24s 0 -
+R s 1926 o - Ap 17 23 1 S
+R s 1926 1929 - O Sa>=1 24s 0 -
+R s 1927 o - Ap 9 23 1 S
+R s 1928 o - Ap 15 0 1 S
+R s 1929 o - Ap 20 23 1 S
+R s 1937 o - Jun 16 23 1 S
+R s 1937 o - O 2 24s 0 -
+R s 1938 o - Ap 2 23 1 S
+R s 1938 o - Ap 30 23 2 M
+R s 1938 o - O 2 24 1 S
+R s 1939 o - O 7 24s 0 -
+R s 1942 o - May 2 23 1 S
+R s 1942 o - S 1 1 0 -
+R s 1943 1946 - Ap Sa>=13 23 1 S
+R s 1943 1944 - O Su>=1 1 0 -
+R s 1945 1946 - S lastSu 1 0 -
+R s 1949 o - Ap 30 23 1 S
+R s 1949 o - O 2 1 0 -
+R s 1974 1975 - Ap Sa>=12 23 1 S
+R s 1974 1975 - O Su>=1 1 0 -
+R s 1976 o - Mar 27 23 1 S
+R s 1976 1977 - S lastSu 1 0 -
+R s 1977 o - Ap 2 23 1 S
+R s 1978 o - Ap 2 2s 1 S
+R s 1978 o - O 1 2s 0 -
+R Sp 1967 o - Jun 3 12 1 S
+R Sp 1967 o - O 1 0 0 -
+R Sp 1974 o - Jun 24 0 1 S
+R Sp 1974 o - S 1 0 0 -
+R Sp 1976 1977 - May 1 0 1 S
+R Sp 1976 o - Au 1 0 0 -
+R Sp 1977 o - S 28 0 0 -
+R Sp 1978 o - Jun 1 0 1 S
+R Sp 1978 o - Au 4 0 0 -
+R CH 1941 1942 - May M>=1 1 1 S
+R CH 1941 1942 - O M>=1 2 0 -
+R T 1916 o - May 1 0 1 S
+R T 1916 o - O 1 0 0 -
+R T 1920 o - Mar 28 0 1 S
+R T 1920 o - O 25 0 0 -
+R T 1921 o - Ap 3 0 1 S
+R T 1921 o - O 3 0 0 -
+R T 1922 o - Mar 26 0 1 S
+R T 1922 o - O 8 0 0 -
+R T 1924 o - May 13 0 1 S
+R T 1924 1925 - O 1 0 0 -
+R T 1925 o - May 1 0 1 S
+R T 1940 o - Jul 1 0 1 S
+R T 1940 o - O 6 0 0 -
+R T 1940 o - D 1 0 1 S
+R T 1941 o - S 21 0 0 -
+R T 1942 o - Ap 1 0 1 S
+R T 1945 o - O 8 0 0 -
+R T 1946 o - Jun 1 0 1 S
+R T 1946 o - O 1 0 0 -
+R T 1947 1948 - Ap Su>=16 0 1 S
+R T 1947 1951 - O Su>=2 0 0 -
+R T 1949 o - Ap 10 0 1 S
+R T 1950 o - Ap 16 0 1 S
+R T 1951 o - Ap 22 0 1 S
+R T 1962 o - Jul 15 0 1 S
+R T 1963 o - O 30 0 0 -
+R T 1964 o - May 15 0 1 S
+R T 1964 o - O 1 0 0 -
+R T 1973 o - Jun 3 1 1 S
+R T 1973 1976 - O Su>=31 2 0 -
+R T 1974 o - Mar 31 2 1 S
+R T 1975 o - Mar 22 2 1 S
+R T 1976 o - Mar 21 2 1 S
+R T 1977 1978 - Ap Su>=1 2 1 S
+R T 1977 1978 - O Su>=15 2 0 -
+R T 1978 o - Jun 29 0 0 -
+R T 1983 o - Jul 31 2 1 S
+R T 1983 o - O 2 2 0 -
+R T 1985 o - Ap 20 1s 1 S
+R T 1985 o - S 28 1s 0 -
+R T 1986 1993 - Mar lastSu 1s 1 S
+R T 1986 1995 - S lastSu 1s 0 -
+R T 1994 o - Mar 20 1s 1 S
+R T 1995 2006 - Mar lastSu 1s 1 S
+R T 1996 2006 - O lastSu 1s 0 -
+R u 1918 1919 - Mar lastSu 2 1 D
+R u 1918 1919 - O lastSu 2 0 S
+R u 1942 o - F 9 2 1 W
+R u 1945 o - Au 14 23u 1 P
+R u 1945 o - S 30 2 0 S
+R u 1967 2006 - O lastSu 2 0 S
+R u 1967 1973 - Ap lastSu 2 1 D
+R u 1974 o - Ja 6 2 1 D
+R u 1975 o - F lastSu 2 1 D
+R u 1976 1986 - Ap lastSu 2 1 D
+R u 1987 2006 - Ap Su>=1 2 1 D
+R u 2007 ma - Mar Su>=8 2 1 D
+R u 2007 ma - N Su>=1 2 0 S
+R NY 1920 o - Mar lastSu 2 1 D
+R NY 1920 o - O lastSu 2 0 S
+R NY 1921 1966 - Ap lastSu 2 1 D
+R NY 1921 1954 - S lastSu 2 0 S
+R NY 1955 1966 - O lastSu 2 0 S
+R Ch 1920 o - Jun 13 2 1 D
+R Ch 1920 1921 - O lastSu 2 0 S
+R Ch 1921 o - Mar lastSu 2 1 D
+R Ch 1922 1966 - Ap lastSu 2 1 D
+R Ch 1922 1954 - S lastSu 2 0 S
+R Ch 1955 1966 - O lastSu 2 0 S
+R De 1920 1921 - Mar lastSu 2 1 D
+R De 1920 o - O lastSu 2 0 S
+R De 1921 o - May 22 2 0 S
+R De 1965 1966 - Ap lastSu 2 1 D
+R De 1965 1966 - O lastSu 2 0 S
+R CA 1948 o - Mar 14 2:1 1 D
+R CA 1949 o - Ja 1 2 0 S
+R CA 1950 1966 - Ap lastSu 1 1 D
+R CA 1950 1961 - S lastSu 2 0 S
+R CA 1962 1966 - O lastSu 2 0 S
+R In 1941 o - Jun 22 2 1 D
+R In 1941 1954 - S lastSu 2 0 S
+R In 1946 1954 - Ap lastSu 2 1 D
+R Ma 1951 o - Ap lastSu 2 1 D
+R Ma 1951 o - S lastSu 2 0 S
+R Ma 1954 1960 - Ap lastSu 2 1 D
+R Ma 1954 1960 - S lastSu 2 0 S
+R V 1946 o - Ap lastSu 2 1 D
+R V 1946 o - S lastSu 2 0 S
+R V 1953 1954 - Ap lastSu 2 1 D
+R V 1953 1959 - S lastSu 2 0 S
+R V 1955 o - May 1 0 1 D
+R V 1956 1963 - Ap lastSu 2 1 D
+R V 1960 o - O lastSu 2 0 S
+R V 1961 o - S lastSu 2 0 S
+R V 1962 1963 - O lastSu 2 0 S
+R Pe 1955 o - May 1 0 1 D
+R Pe 1955 1960 - S lastSu 2 0 S
+R Pe 1956 1963 - Ap lastSu 2 1 D
+R Pe 1961 1963 - O lastSu 2 0 S
+R Pi 1955 o - May 1 0 1 D
+R Pi 1955 1960 - S lastSu 2 0 S
+R Pi 1956 1964 - Ap lastSu 2 1 D
+R Pi 1961 1964 - O lastSu 2 0 S
+R St 1947 1961 - Ap lastSu 2 1 D
+R St 1947 1954 - S lastSu 2 0 S
+R St 1955 1956 - O lastSu 2 0 S
+R St 1957 1958 - S lastSu 2 0 S
+R St 1959 1961 - O lastSu 2 0 S
+R Pu 1946 1960 - Ap lastSu 2 1 D
+R Pu 1946 1954 - S lastSu 2 0 S
+R Pu 1955 1956 - O lastSu 2 0 S
+R Pu 1957 1960 - S lastSu 2 0 S
+R v 1921 o - May 1 2 1 D
+R v 1921 o - S 1 2 0 S
+R v 1941 o - Ap lastSu 2 1 D
+R v 1941 o - S lastSu 2 0 S
+R v 1946 o - Ap lastSu 0:1 1 D
+R v 1946 o - Jun 2 2 0 S
+R v 1950 1961 - Ap lastSu 2 1 D
+R v 1950 1955 - S lastSu 2 0 S
+R v 1956 1961 - O lastSu 2 0 S
+R Dt 1948 o - Ap lastSu 2 1 D
+R Dt 1948 o - S lastSu 2 0 S
+R Me 1946 o - Ap lastSu 2 1 D
+R Me 1946 o - S lastSu 2 0 S
+R Me 1966 o - Ap lastSu 2 1 D
+R Me 1966 o - O lastSu 2 0 S
+R C 1918 o - Ap 14 2 1 D
+R C 1918 o - O 27 2 0 S
+R C 1942 o - F 9 2 1 W
+R C 1945 o - Au 14 23u 1 P
+R C 1945 o - S 30 2 0 S
+R C 1974 1986 - Ap lastSu 2 1 D
+R C 1974 2006 - O lastSu 2 0 S
+R C 1987 2006 - Ap Su>=1 2 1 D
+R C 2007 ma - Mar Su>=8 2 1 D
+R C 2007 ma - N Su>=1 2 0 S
+R j 1917 o - Ap 8 2 1 D
+R j 1917 o - S 17 2 0 S
+R j 1919 o - May 5 23 1 D
+R j 1919 o - Au 12 23 0 S
+R j 1920 1935 - May Su>=1 23 1 D
+R j 1920 1935 - O lastSu 23 0 S
+R j 1936 1941 - May M>=9 0 1 D
+R j 1936 1941 - O M>=2 0 0 S
+R j 1946 1950 - May Su>=8 2 1 D
+R j 1946 1950 - O Su>=2 2 0 S
+R j 1951 1986 - Ap lastSu 2 1 D
+R j 1951 1959 - S lastSu 2 0 S
+R j 1960 1986 - O lastSu 2 0 S
+R j 1987 o - Ap Su>=1 0:1 1 D
+R j 1987 2006 - O lastSu 0:1 0 S
+R j 1988 o - Ap Su>=1 0:1 2 DD
+R j 1989 2006 - Ap Su>=1 0:1 1 D
+R j 2007 2011 - Mar Su>=8 0:1 1 D
+R j 2007 2010 - N Su>=1 0:1 0 S
+R H 1916 o - Ap 1 0 1 D
+R H 1916 o - O 1 0 0 S
+R H 1920 o - May 9 0 1 D
+R H 1920 o - Au 29 0 0 S
+R H 1921 o - May 6 0 1 D
+R H 1921 1922 - S 5 0 0 S
+R H 1922 o - Ap 30 0 1 D
+R H 1923 1925 - May Su>=1 0 1 D
+R H 1923 o - S 4 0 0 S
+R H 1924 o - S 15 0 0 S
+R H 1925 o - S 28 0 0 S
+R H 1926 o - May 16 0 1 D
+R H 1926 o - S 13 0 0 S
+R H 1927 o - May 1 0 1 D
+R H 1927 o - S 26 0 0 S
+R H 1928 1931 - May Su>=8 0 1 D
+R H 1928 o - S 9 0 0 S
+R H 1929 o - S 3 0 0 S
+R H 1930 o - S 15 0 0 S
+R H 1931 1932 - S M>=24 0 0 S
+R H 1932 o - May 1 0 1 D
+R H 1933 o - Ap 30 0 1 D
+R H 1933 o - O 2 0 0 S
+R H 1934 o - May 20 0 1 D
+R H 1934 o - S 16 0 0 S
+R H 1935 o - Jun 2 0 1 D
+R H 1935 o - S 30 0 0 S
+R H 1936 o - Jun 1 0 1 D
+R H 1936 o - S 14 0 0 S
+R H 1937 1938 - May Su>=1 0 1 D
+R H 1937 1941 - S M>=24 0 0 S
+R H 1939 o - May 28 0 1 D
+R H 1940 1941 - May Su>=1 0 1 D
+R H 1946 1949 - Ap lastSu 2 1 D
+R H 1946 1949 - S lastSu 2 0 S
+R H 1951 1954 - Ap lastSu 2 1 D
+R H 1951 1954 - S lastSu 2 0 S
+R H 1956 1959 - Ap lastSu 2 1 D
+R H 1956 1959 - S lastSu 2 0 S
+R H 1962 1973 - Ap lastSu 2 1 D
+R H 1962 1973 - O lastSu 2 0 S
+R o 1933 1935 - Jun Su>=8 1 1 D
+R o 1933 1935 - S Su>=8 1 0 S
+R o 1936 1938 - Jun Su>=1 1 1 D
+R o 1936 1938 - S Su>=1 1 0 S
+R o 1939 o - May 27 1 1 D
+R o 1939 1941 - S Sa>=21 1 0 S
+R o 1940 o - May 19 1 1 D
+R o 1941 o - May 4 1 1 D
+R o 1946 1972 - Ap lastSu 2 1 D
+R o 1946 1956 - S lastSu 2 0 S
+R o 1957 1972 - O lastSu 2 0 S
+R o 1993 2006 - Ap Su>=1 0:1 1 D
+R o 1993 2006 - O lastSu 0:1 0 S
+R t 1919 o - Mar 30 23:30 1 D
+R t 1919 o - O 26 0 0 S
+R t 1920 o - May 2 2 1 D
+R t 1920 o - S 26 0 0 S
+R t 1921 o - May 15 2 1 D
+R t 1921 o - S 15 2 0 S
+R t 1922 1923 - May Su>=8 2 1 D
+R t 1922 1926 - S Su>=15 2 0 S
+R t 1924 1927 - May Su>=1 2 1 D
+R t 1927 1937 - S Su>=25 2 0 S
+R t 1928 1937 - Ap Su>=25 2 1 D
+R t 1938 1940 - Ap lastSu 2 1 D
+R t 1938 1939 - S lastSu 2 0 S
+R t 1945 1948 - S lastSu 2 0 S
+R t 1946 1973 - Ap lastSu 2 1 D
+R t 1949 1950 - N lastSu 2 0 S
+R t 1951 1956 - S lastSu 2 0 S
+R t 1957 1973 - O lastSu 2 0 S
+R W 1916 o - Ap 23 0 1 D
+R W 1916 o - S 17 0 0 S
+R W 1918 o - Ap 14 2 1 D
+R W 1918 o - O 27 2 0 S
+R W 1937 o - May 16 2 1 D
+R W 1937 o - S 26 2 0 S
+R W 1942 o - F 9 2 1 W
+R W 1945 o - Au 14 23u 1 P
+R W 1945 o - S lastSu 2 0 S
+R W 1946 o - May 12 2 1 D
+R W 1946 o - O 13 2 0 S
+R W 1947 1949 - Ap lastSu 2 1 D
+R W 1947 1949 - S lastSu 2 0 S
+R W 1950 o - May 1 2 1 D
+R W 1950 o - S 30 2 0 S
+R W 1951 1960 - Ap lastSu 2 1 D
+R W 1951 1958 - S lastSu 2 0 S
+R W 1959 o - O lastSu 2 0 S
+R W 1960 o - S lastSu 2 0 S
+R W 1963 o - Ap lastSu 2 1 D
+R W 1963 o - S 22 2 0 S
+R W 1966 1986 - Ap lastSu 2s 1 D
+R W 1966 2005 - O lastSu 2s 0 S
+R W 1987 2005 - Ap Su>=1 2s 1 D
+R r 1918 o - Ap 14 2 1 D
+R r 1918 o - O 27 2 0 S
+R r 1930 1934 - May Su>=1 0 1 D
+R r 1930 1934 - O Su>=1 0 0 S
+R r 1937 1941 - Ap Su>=8 0 1 D
+R r 1937 o - O Su>=8 0 0 S
+R r 1938 o - O Su>=1 0 0 S
+R r 1939 1941 - O Su>=8 0 0 S
+R r 1942 o - F 9 2 1 W
+R r 1945 o - Au 14 23u 1 P
+R r 1945 o - S lastSu 2 0 S
+R r 1946 o - Ap Su>=8 2 1 D
+R r 1946 o - O Su>=8 2 0 S
+R r 1947 1957 - Ap lastSu 2 1 D
+R r 1947 1957 - S lastSu 2 0 S
+R r 1959 o - Ap lastSu 2 1 D
+R r 1959 o - O lastSu 2 0 S
+R Sw 1957 o - Ap lastSu 2 1 D
+R Sw 1957 o - O lastSu 2 0 S
+R Sw 1959 1961 - Ap lastSu 2 1 D
+R Sw 1959 o - O lastSu 2 0 S
+R Sw 1960 1961 - S lastSu 2 0 S
+R Ed 1918 1919 - Ap Su>=8 2 1 D
+R Ed 1918 o - O 27 2 0 S
+R Ed 1919 o - May 27 2 0 S
+R Ed 1920 1923 - Ap lastSu 2 1 D
+R Ed 1920 o - O lastSu 2 0 S
+R Ed 1921 1923 - S lastSu 2 0 S
+R Ed 1942 o - F 9 2 1 W
+R Ed 1945 o - Au 14 23u 1 P
+R Ed 1945 o - S lastSu 2 0 S
+R Ed 1947 o - Ap lastSu 2 1 D
+R Ed 1947 o - S lastSu 2 0 S
+R Ed 1972 1986 - Ap lastSu 2 1 D
+R Ed 1972 2006 - O lastSu 2 0 S
+R Va 1918 o - Ap 14 2 1 D
+R Va 1918 o - O 27 2 0 S
+R Va 1942 o - F 9 2 1 W
+R Va 1945 o - Au 14 23u 1 P
+R Va 1945 o - S 30 2 0 S
+R Va 1946 1986 - Ap lastSu 2 1 D
+R Va 1946 o - S 29 2 0 S
+R Va 1947 1961 - S lastSu 2 0 S
+R Va 1962 2006 - O lastSu 2 0 S
+R Y 1918 o - Ap 14 2 1 D
+R Y 1918 o - O 27 2 0 S
+R Y 1919 o - May 25 2 1 D
+R Y 1919 o - N 1 0 0 S
+R Y 1942 o - F 9 2 1 W
+R Y 1945 o - Au 14 23u 1 P
+R Y 1945 o - S 30 2 0 S
+R Y 1972 1986 - Ap lastSu 2 1 D
+R Y 1972 2006 - O lastSu 2 0 S
+R Y 1987 2006 - Ap Su>=1 2 1 D
+R Yu 1965 o - Ap lastSu 0 2 DD
+R Yu 1965 o - O lastSu 2 0 S
+R m 1931 o - Ap 30 0 1 D
+R m 1931 o - O 1 0 0 S
+R m 1939 o - F 5 0 1 D
+R m 1939 o - Jun 25 0 0 S
+R m 1940 o - D 9 0 1 D
+R m 1941 o - Ap 1 0 0 S
+R m 1943 o - D 16 0 1 W
+R m 1944 o - May 1 0 0 S
+R m 1950 o - F 12 0 1 D
+R m 1950 o - Jul 30 0 0 S
+R m 1996 2000 - Ap Su>=1 2 1 D
+R m 1996 2000 - O lastSu 2 0 S
+R m 2001 o - May Su>=1 2 1 D
+R m 2001 o - S lastSu 2 0 S
+R m 2002 2022 - Ap Su>=1 2 1 D
+R m 2002 2022 - O lastSu 2 0 S
+R BB 1942 o - Ap 19 5u 1 D
+R BB 1942 o - Au 31 6u 0 S
+R BB 1943 o - May 2 5u 1 D
+R BB 1943 o - S 5 6u 0 S
+R BB 1944 o - Ap 10 5u 0:30 -
+R BB 1944 o - S 10 6u 0 S
+R BB 1977 o - Jun 12 2 1 D
+R BB 1977 1978 - O Su>=1 2 0 S
+R BB 1978 1980 - Ap Su>=15 2 1 D
+R BB 1979 o - S 30 2 0 S
+R BB 1980 o - S 25 2 0 S
+R BZ 1918 1941 - O Sa>=1 24 0:30 -0530
+R BZ 1919 1942 - F Sa>=8 24 0 CST
+R BZ 1942 o - Jun 27 24 1 CWT
+R BZ 1945 o - Au 14 23u 1 CPT
+R BZ 1945 o - D 15 24 0 CST
+R BZ 1947 1967 - O Sa>=1 24 0:30 -0530
+R BZ 1948 1968 - F Sa>=8 24 0 CST
+R BZ 1973 o - D 5 0 1 CDT
+R BZ 1974 o - F 9 0 0 CST
+R BZ 1982 o - D 18 0 1 CDT
+R BZ 1983 o - F 12 0 0 CST
+R Be 1917 o - Ap 5 24 1 -
+R Be 1917 o - S 30 24 0 -
+R Be 1918 o - Ap 13 24 1 -
+R Be 1918 o - S 15 24 0 S
+R Be 1942 o - Ja 11 2 1 D
+R Be 1942 o - O 18 2 0 S
+R Be 1943 o - Mar 21 2 1 D
+R Be 1943 o - O 31 2 0 S
+R Be 1944 1945 - Mar Su>=8 2 1 D
+R Be 1944 1945 - N Su>=1 2 0 S
+R Be 1947 o - May Su>=15 2 1 D
+R Be 1947 o - S Su>=8 2 0 S
+R Be 1948 1952 - May Su>=22 2 1 D
+R Be 1948 1952 - S Su>=1 2 0 S
+R Be 1956 o - May Su>=22 2 1 D
+R Be 1956 o - O lastSu 2 0 S
+R CR 1979 1980 - F lastSu 0 1 D
+R CR 1979 1980 - Jun Su>=1 0 0 S
+R CR 1991 1992 - Ja Sa>=15 0 1 D
+R CR 1991 o - Jul 1 0 0 S
+R CR 1992 o - Mar 15 0 0 S
+R Q 1928 o - Jun 10 0 1 D
+R Q 1928 o - O 10 0 0 S
+R Q 1940 1942 - Jun Su>=1 0 1 D
+R Q 1940 1942 - S Su>=1 0 0 S
+R Q 1945 1946 - Jun Su>=1 0 1 D
+R Q 1945 1946 - S Su>=1 0 0 S
+R Q 1965 o - Jun 1 0 1 D
+R Q 1965 o - S 30 0 0 S
+R Q 1966 o - May 29 0 1 D
+R Q 1966 o - O 2 0 0 S
+R Q 1967 o - Ap 8 0 1 D
+R Q 1967 1968 - S Su>=8 0 0 S
+R Q 1968 o - Ap 14 0 1 D
+R Q 1969 1977 - Ap lastSu 0 1 D
+R Q 1969 1971 - O lastSu 0 0 S
+R Q 1972 1974 - O 8 0 0 S
+R Q 1975 1977 - O lastSu 0 0 S
+R Q 1978 o - May 7 0 1 D
+R Q 1978 1990 - O Su>=8 0 0 S
+R Q 1979 1980 - Mar Su>=15 0 1 D
+R Q 1981 1985 - May Su>=5 0 1 D
+R Q 1986 1989 - Mar Su>=14 0 1 D
+R Q 1990 1997 - Ap Su>=1 0 1 D
+R Q 1991 1995 - O Su>=8 0s 0 S
+R Q 1996 o - O 6 0s 0 S
+R Q 1997 o - O 12 0s 0 S
+R Q 1998 1999 - Mar lastSu 0s 1 D
+R Q 1998 2003 - O lastSu 0s 0 S
+R Q 2000 2003 - Ap Su>=1 0s 1 D
+R Q 2004 o - Mar lastSu 0s 1 D
+R Q 2006 2010 - O lastSu 0s 0 S
+R Q 2007 o - Mar Su>=8 0s 1 D
+R Q 2008 o - Mar Su>=15 0s 1 D
+R Q 2009 2010 - Mar Su>=8 0s 1 D
+R Q 2011 o - Mar Su>=15 0s 1 D
+R Q 2011 o - N 13 0s 0 S
+R Q 2012 o - Ap 1 0s 1 D
+R Q 2012 ma - N Su>=1 0s 0 S
+R Q 2013 ma - Mar Su>=8 0s 1 D
+R DO 1966 o - O 30 0 1 EDT
+R DO 1967 o - F 28 0 0 EST
+R DO 1969 1973 - O lastSu 0 0:30 -0430
+R DO 1970 o - F 21 0 0 EST
+R DO 1971 o - Ja 20 0 0 EST
+R DO 1972 1974 - Ja 21 0 0 EST
+R SV 1987 1988 - May Su>=1 0 1 D
+R SV 1987 1988 - S lastSu 0 0 S
+R GT 1973 o - N 25 0 1 D
+R GT 1974 o - F 24 0 0 S
+R GT 1983 o - May 21 0 1 D
+R GT 1983 o - S 22 0 0 S
+R GT 1991 o - Mar 23 0 1 D
+R GT 1991 o - S 7 0 0 S
+R GT 2006 o - Ap 30 0 1 D
+R GT 2006 o - O 1 0 0 S
+R HT 1983 o - May 8 0 1 D
+R HT 1984 1987 - Ap lastSu 0 1 D
+R HT 1983 1987 - O lastSu 0 0 S
+R HT 1988 1997 - Ap Su>=1 1s 1 D
+R HT 1988 1997 - O lastSu 1s 0 S
+R HT 2005 2006 - Ap Su>=1 0 1 D
+R HT 2005 2006 - O lastSu 0 0 S
+R HT 2012 2015 - Mar Su>=8 2 1 D
+R HT 2012 2015 - N Su>=1 2 0 S
+R HT 2017 ma - Mar Su>=8 2 1 D
+R HT 2017 ma - N Su>=1 2 0 S
+R HN 1987 1988 - May Su>=1 0 1 D
+R HN 1987 1988 - S lastSu 0 0 S
+R HN 2006 o - May Su>=1 0 1 D
+R HN 2006 o - Au M>=1 0 0 S
+R NI 1979 1980 - Mar Su>=16 0 1 D
+R NI 1979 1980 - Jun M>=23 0 0 S
+R NI 2005 o - Ap 10 0 1 D
+R NI 2005 o - O Su>=1 0 0 S
+R NI 2006 o - Ap 30 2 1 D
+R NI 2006 o - O Su>=1 1 0 S
+R A 1930 o - D 1 0 1 -
+R A 1931 o - Ap 1 0 0 -
+R A 1931 o - O 15 0 1 -
+R A 1932 1940 - Mar 1 0 0 -
+R A 1932 1939 - N 1 0 1 -
+R A 1940 o - Jul 1 0 1 -
+R A 1941 o - Jun 15 0 0 -
+R A 1941 o - O 15 0 1 -
+R A 1943 o - Au 1 0 0 -
+R A 1943 o - O 15 0 1 -
+R A 1946 o - Mar 1 0 0 -
+R A 1946 o - O 1 0 1 -
+R A 1963 o - O 1 0 0 -
+R A 1963 o - D 15 0 1 -
+R A 1964 1966 - Mar 1 0 0 -
+R A 1964 1966 - O 15 0 1 -
+R A 1967 o - Ap 2 0 0 -
+R A 1967 1968 - O Su>=1 0 1 -
+R A 1968 1969 - Ap Su>=1 0 0 -
+R A 1974 o - Ja 23 0 1 -
+R A 1974 o - May 1 0 0 -
+R A 1988 o - D 1 0 1 -
+R A 1989 1993 - Mar Su>=1 0 0 -
+R A 1989 1992 - O Su>=15 0 1 -
+R A 1999 o - O Su>=1 0 1 -
+R A 2000 o - Mar 3 0 0 -
+R A 2007 o - D 30 0 1 -
+R A 2008 2009 - Mar Su>=15 0 0 -
+R A 2008 o - O Su>=15 0 1 -
+R Sa 2008 2009 - Mar Su>=8 0 0 -
+R Sa 2007 2008 - O Su>=8 0 1 -
+R B 1931 o - O 3 11 1 -
+R B 1932 1933 - Ap 1 0 0 -
+R B 1932 o - O 3 0 1 -
+R B 1949 1952 - D 1 0 1 -
+R B 1950 o - Ap 16 1 0 -
+R B 1951 1952 - Ap 1 0 0 -
+R B 1953 o - Mar 1 0 0 -
+R B 1963 o - D 9 0 1 -
+R B 1964 o - Mar 1 0 0 -
+R B 1965 o - Ja 31 0 1 -
+R B 1965 o - Mar 31 0 0 -
+R B 1965 o - D 1 0 1 -
+R B 1966 1968 - Mar 1 0 0 -
+R B 1966 1967 - N 1 0 1 -
+R B 1985 o - N 2 0 1 -
+R B 1986 o - Mar 15 0 0 -
+R B 1986 o - O 25 0 1 -
+R B 1987 o - F 14 0 0 -
+R B 1987 o - O 25 0 1 -
+R B 1988 o - F 7 0 0 -
+R B 1988 o - O 16 0 1 -
+R B 1989 o - Ja 29 0 0 -
+R B 1989 o - O 15 0 1 -
+R B 1990 o - F 11 0 0 -
+R B 1990 o - O 21 0 1 -
+R B 1991 o - F 17 0 0 -
+R B 1991 o - O 20 0 1 -
+R B 1992 o - F 9 0 0 -
+R B 1992 o - O 25 0 1 -
+R B 1993 o - Ja 31 0 0 -
+R B 1993 1995 - O Su>=11 0 1 -
+R B 1994 1995 - F Su>=15 0 0 -
+R B 1996 o - F 11 0 0 -
+R B 1996 o - O 6 0 1 -
+R B 1997 o - F 16 0 0 -
+R B 1997 o - O 6 0 1 -
+R B 1998 o - Mar 1 0 0 -
+R B 1998 o - O 11 0 1 -
+R B 1999 o - F 21 0 0 -
+R B 1999 o - O 3 0 1 -
+R B 2000 o - F 27 0 0 -
+R B 2000 2001 - O Su>=8 0 1 -
+R B 2001 2006 - F Su>=15 0 0 -
+R B 2002 o - N 3 0 1 -
+R B 2003 o - O 19 0 1 -
+R B 2004 o - N 2 0 1 -
+R B 2005 o - O 16 0 1 -
+R B 2006 o - N 5 0 1 -
+R B 2007 o - F 25 0 0 -
+R B 2007 o - O Su>=8 0 1 -
+R B 2008 2017 - O Su>=15 0 1 -
+R B 2008 2011 - F Su>=15 0 0 -
+R B 2012 o - F Su>=22 0 0 -
+R B 2013 2014 - F Su>=15 0 0 -
+R B 2015 o - F Su>=22 0 0 -
+R B 2016 2019 - F Su>=15 0 0 -
+R B 2018 o - N Su>=1 0 1 -
+R x 1927 1931 - S 1 0 1 -
+R x 1928 1932 - Ap 1 0 0 -
+R x 1968 o - N 3 4u 1 -
+R x 1969 o - Mar 30 3u 0 -
+R x 1969 o - N 23 4u 1 -
+R x 1970 o - Mar 29 3u 0 -
+R x 1971 o - Mar 14 3u 0 -
+R x 1970 1972 - O Su>=9 4u 1 -
+R x 1972 1986 - Mar Su>=9 3u 0 -
+R x 1973 o - S 30 4u 1 -
+R x 1974 1987 - O Su>=9 4u 1 -
+R x 1987 o - Ap 12 3u 0 -
+R x 1988 1990 - Mar Su>=9 3u 0 -
+R x 1988 1989 - O Su>=9 4u 1 -
+R x 1990 o - S 16 4u 1 -
+R x 1991 1996 - Mar Su>=9 3u 0 -
+R x 1991 1997 - O Su>=9 4u 1 -
+R x 1997 o - Mar 30 3u 0 -
+R x 1998 o - Mar Su>=9 3u 0 -
+R x 1998 o - S 27 4u 1 -
+R x 1999 o - Ap 4 3u 0 -
+R x 1999 2010 - O Su>=9 4u 1 -
+R x 2000 2007 - Mar Su>=9 3u 0 -
+R x 2008 o - Mar 30 3u 0 -
+R x 2009 o - Mar Su>=9 3u 0 -
+R x 2010 o - Ap Su>=1 3u 0 -
+R x 2011 o - May Su>=2 3u 0 -
+R x 2011 o - Au Su>=16 4u 1 -
+R x 2012 2014 - Ap Su>=23 3u 0 -
+R x 2012 2014 - S Su>=2 4u 1 -
+R x 2016 2018 - May Su>=9 3u 0 -
+R x 2016 2018 - Au Su>=9 4u 1 -
+R x 2019 ma - Ap Su>=2 3u 0 -
+R x 2019 2021 - S Su>=2 4u 1 -
+R x 2022 o - S Su>=9 4u 1 -
+R x 2023 ma - S Su>=2 4u 1 -
+R CO 1992 o - May 3 0 1 -
+R CO 1993 o - F 6 24 0 -
+R EC 1992 o - N 28 0 1 -
+R EC 1993 o - F 5 0 0 -
+R FK 1937 1938 - S lastSu 0 1 -
+R FK 1938 1942 - Mar Su>=19 0 0 -
+R FK 1939 o - O 1 0 1 -
+R FK 1940 1942 - S lastSu 0 1 -
+R FK 1943 o - Ja 1 0 0 -
+R FK 1983 o - S lastSu 0 1 -
+R FK 1984 1985 - Ap lastSu 0 0 -
+R FK 1984 o - S 16 0 1 -
+R FK 1985 2000 - S Su>=9 0 1 -
+R FK 1986 2000 - Ap Su>=16 0 0 -
+R FK 2001 2010 - Ap Su>=15 2 0 -
+R FK 2001 2010 - S Su>=1 2 1 -
+R y 1975 1988 - O 1 0 1 -
+R y 1975 1978 - Mar 1 0 0 -
+R y 1979 1991 - Ap 1 0 0 -
+R y 1989 o - O 22 0 1 -
+R y 1990 o - O 1 0 1 -
+R y 1991 o - O 6 0 1 -
+R y 1992 o - Mar 1 0 0 -
+R y 1992 o - O 5 0 1 -
+R y 1993 o - Mar 31 0 0 -
+R y 1993 1995 - O 1 0 1 -
+R y 1994 1995 - F lastSu 0 0 -
+R y 1996 o - Mar 1 0 0 -
+R y 1996 2001 - O Su>=1 0 1 -
+R y 1997 o - F lastSu 0 0 -
+R y 1998 2001 - Mar Su>=1 0 0 -
+R y 2002 2004 - Ap Su>=1 0 0 -
+R y 2002 2003 - S Su>=1 0 1 -
+R y 2004 2009 - O Su>=15 0 1 -
+R y 2005 2009 - Mar Su>=8 0 0 -
+R y 2010 2024 - O Su>=1 0 1 -
+R y 2010 2012 - Ap Su>=8 0 0 -
+R y 2013 2024 - Mar Su>=22 0 0 -
+R PE 1938 o - Ja 1 0 1 -
+R PE 1938 o - Ap 1 0 0 -
+R PE 1938 1939 - S lastSu 0 1 -
+R PE 1939 1940 - Mar Su>=24 0 0 -
+R PE 1986 1987 - Ja 1 0 1 -
+R PE 1986 1987 - Ap 1 0 0 -
+R PE 1990 o - Ja 1 0 1 -
+R PE 1990 o - Ap 1 0 0 -
+R PE 1994 o - Ja 1 0 1 -
+R PE 1994 o - Ap 1 0 0 -
+R U 1923 1925 - O 1 0 0:30 -
+R U 1924 1926 - Ap 1 0 0 -
+R U 1933 1938 - O lastSu 0 0:30 -
+R U 1934 1941 - Mar lastSa 24 0 -
+R U 1939 o - O 1 0 0:30 -
+R U 1940 o - O 27 0 0:30 -
+R U 1941 o - Au 1 0 0:30 -
+R U 1942 o - D 14 0 0:30 -
+R U 1943 o - Mar 14 0 0 -
+R U 1959 o - May 24 0 0:30 -
+R U 1959 o - N 15 0 0 -
+R U 1960 o - Ja 17 0 1 -
+R U 1960 o - Mar 6 0 0 -
+R U 1965 o - Ap 4 0 1 -
+R U 1965 o - S 26 0 0 -
+R U 1968 o - May 27 0 0:30 -
+R U 1968 o - D 1 0 0 -
+R U 1970 o - Ap 25 0 1 -
+R U 1970 o - Jun 14 0 0 -
+R U 1972 o - Ap 23 0 1 -
+R U 1972 o - Jul 16 0 0 -
+R U 1974 o - Ja 13 0 1:30 -
+R U 1974 o - Mar 10 0 0:30 -
+R U 1974 o - S 1 0 0 -
+R U 1974 o - D 22 0 1 -
+R U 1975 o - Mar 30 0 0 -
+R U 1976 o - D 19 0 1 -
+R U 1977 o - Mar 6 0 0 -
+R U 1977 o - D 4 0 1 -
+R U 1978 1979 - Mar Su>=1 0 0 -
+R U 1978 o - D 17 0 1 -
+R U 1979 o - Ap 29 0 1 -
+R U 1980 o - Mar 16 0 0 -
+R U 1987 o - D 14 0 1 -
+R U 1988 o - F 28 0 0 -
+R U 1988 o - D 11 0 1 -
+R U 1989 o - Mar 5 0 0 -
+R U 1989 o - O 29 0 1 -
+R U 1990 o - F 25 0 0 -
+R U 1990 1991 - O Su>=21 0 1 -
+R U 1991 1992 - Mar Su>=1 0 0 -
+R U 1992 o - O 18 0 1 -
+R U 1993 o - F 28 0 0 -
+R U 2004 o - S 19 0 1 -
+R U 2005 o - Mar 27 2 0 -
+R U 2005 o - O 9 2 1 -
+R U 2006 2015 - Mar Su>=8 2 0 -
+R U 2006 2014 - O Su>=1 2 1 -
+Z Africa/Abidjan -0:16:8 - LMT 1912
+0 - GMT
+Z Africa/Algiers 0:12:12 - LMT 1891 Mar 16
+0:9:21 - PMT 1911 Mar 11
+0 d WE%sT 1940 F 25 2
+1 d CE%sT 1946 O 7
+0 - WET 1956 Ja 29
+1 - CET 1963 Ap 14
+0 d WE%sT 1977 O 21
+1 d CE%sT 1979 O 26
+0 d WE%sT 1981 May
+1 - CET
+Z Africa/Bissau -1:2:20 - LMT 1912 Ja 1 1u
+-1 - %z 1975
+0 - GMT
+Z Africa/Cairo 2:5:9 - LMT 1900 O
+2 K EE%sT
+Z Africa/Casablanca -0:30:20 - LMT 1913 O 26
+0 M %z 1984 Mar 16
+1 - %z 1986
+0 M %z 2018 O 28 3
+1 M %z
+Z Africa/Ceuta -0:21:16 - LMT 1901 Ja 1 0u
+0 - WET 1918 May 6 23
+0 1 WEST 1918 O 7 23
+0 - WET 1924
+0 s WE%sT 1929
+0 - WET 1967
+0 Sp WE%sT 1984 Mar 16
+1 - CET 1986
+1 E CE%sT
+Z Africa/El_Aaiun -0:52:48 - LMT 1934
+-1 - %z 1976 Ap 14
+0 M %z 2018 O 28 3
+1 M %z
+Z Africa/Johannesburg 1:52 - LMT 1892 F 8
+1:30 - SAST 1903 Mar
+2 SA SAST
+Z Africa/Juba 2:6:28 - LMT 1931
+2 SD CA%sT 2000 Ja 15 12
+3 - EAT 2021 F
+2 - CAT
+Z Africa/Khartoum 2:10:8 - LMT 1931
+2 SD CA%sT 2000 Ja 15 12
+3 - EAT 2017 N
+2 - CAT
+Z Africa/Lagos 0:13:35 - LMT 1905 Jul
+0 - GMT 1908 Jul
+0:13:35 - LMT 1914
+0:30 - %z 1919 S
+1 - WAT
+Z Africa/Maputo 2:10:18 - LMT 1909
+2 - CAT
+Z Africa/Monrovia -0:43:8 - LMT 1882
+-0:43:8 - MMT 1919 Mar
+-0:44:30 - MMT 1972 Ja 7
+0 - GMT
+Z Africa/Nairobi 2:27:16 - LMT 1908 May
+2:30 - %z 1928 Jun 30 24
+3 - EAT 1930 Ja 4 24
+2:30 - %z 1936 D 31 24
+2:45 - %z 1942 Jul 31 24
+3 - EAT
+Z Africa/Ndjamena 1:0:12 - LMT 1912
+1 - WAT 1979 O 14
+1 1 WAST 1980 Mar 8
+1 - WAT
+Z Africa/Sao_Tome 0:26:56 - LMT 1884
+-0:36:45 - LMT 1912 Ja 1 0u
+0 - GMT 2018 Ja 1 1
+1 - WAT 2019 Ja 1 2
+0 - GMT
+Z Africa/Tripoli 0:52:44 - LMT 1920
+1 L CE%sT 1959
+2 - EET 1982
+1 L CE%sT 1990 May 4
+2 - EET 1996 S 30
+1 L CE%sT 1997 O 4
+2 - EET 2012 N 10 2
+1 L CE%sT 2013 O 25 2
+2 - EET
+Z Africa/Tunis 0:40:44 - LMT 1881 May 12
+0:9:21 - PMT 1911 Mar 11
+1 n CE%sT
+Z Africa/Windhoek 1:8:24 - LMT 1892 F 8
+1:30 - %z 1903 Mar
+2 - SAST 1942 S 20 2
+2 1 SAST 1943 Mar 21 2
+2 - SAST 1990 Mar 21
+2 NA %s
+Z America/Adak 12:13:22 - LMT 1867 O 19 12:44:35
+-11:46:38 - LMT 1900 Au 20 12
+-11 - NST 1942
+-11 u N%sT 1946
+-11 - NST 1967 Ap
+-11 - BST 1969
+-11 u B%sT 1983 O 30 2
+-10 u AH%sT 1983 N 30
+-10 u H%sT
+Z America/Anchorage 14:0:24 - LMT 1867 O 19 14:31:37
+-9:59:36 - LMT 1900 Au 20 12
+-10 - AST 1942
+-10 u A%sT 1967 Ap
+-10 - AHST 1969
+-10 u AH%sT 1983 O 30 2
+-9 u Y%sT 1983 N 30
+-9 u AK%sT
+Z America/Araguaina -3:12:48 - LMT 1914
+-3 B %z 1990 S 17
+-3 - %z 1995 S 14
+-3 B %z 2003 S 24
+-3 - %z 2012 O 21
+-3 B %z 2013 S
+-3 - %z
+Z America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z
+Z America/Argentina/Catamarca -4:23:8 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
+Z America/Argentina/Cordoba -4:16:48 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z
+Z America/Argentina/Jujuy -4:21:12 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1990 Mar 4
+-4 - %z 1990 O 28
+-4 1 %z 1991 Mar 17
+-4 - %z 1991 O 6
+-3 1 %z 1992
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z 2008 O 18
+-3 - %z
+Z America/Argentina/La_Rioja -4:27:24 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar
+-4 - %z 1991 May 7
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
+Z America/Argentina/Mendoza -4:35:16 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1990 Mar 4
+-4 - %z 1990 O 15
+-4 1 %z 1991 Mar
+-4 - %z 1991 O 15
+-4 1 %z 1992 Mar
+-4 - %z 1992 O 18
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 May 23
+-4 - %z 2004 S 26
+-3 A %z 2008 O 18
+-3 - %z
+Z America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
+Z America/Argentina/Salta -4:21:40 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 A %z 2008 O 18
+-3 - %z
+Z America/Argentina/San_Juan -4:34:4 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar
+-4 - %z 1991 May 7
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 May 31
+-4 - %z 2004 Jul 25
+-3 A %z 2008 O 18
+-3 - %z
+Z America/Argentina/San_Luis -4:25:24 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1990
+-3 1 %z 1990 Mar 14
+-4 - %z 1990 O 15
+-4 1 %z 1991 Mar
+-4 - %z 1991 Jun
+-3 - %z 1999 O 3
+-4 1 %z 2000 Mar 3
+-3 - %z 2004 May 31
+-4 - %z 2004 Jul 25
+-3 A %z 2008 Ja 21
+-4 Sa %z 2009 O 11
+-3 - %z
+Z America/Argentina/Tucuman -4:20:52 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1991 Mar 3
+-4 - %z 1991 O 20
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 Jun
+-4 - %z 2004 Jun 13
+-3 A %z
+Z America/Argentina/Ushuaia -4:33:12 - LMT 1894 O 31
+-4:16:48 - CMT 1920 May
+-4 - %z 1930 D
+-4 A %z 1969 O 5
+-3 A %z 1999 O 3
+-4 A %z 2000 Mar 3
+-3 - %z 2004 May 30
+-4 - %z 2004 Jun 20
+-3 A %z 2008 O 18
+-3 - %z
+Z America/Asuncion -3:50:40 - LMT 1890
+-3:50:40 - AMT 1931 O 10
+-4 - %z 1972 O
+-3 - %z 1974 Ap
+-4 y %z 2024 O 15
+-3 - %z
+Z America/Bahia -2:34:4 - LMT 1914
+-3 B %z 2003 S 24
+-3 - %z 2011 O 16
+-3 B %z 2012 O 21
+-3 - %z
+Z America/Bahia_Banderas -7:1 - LMT 1922 Ja 1 7u
+-7 - MST 1927 Jun 10
+-6 - CST 1930 N 15
+-7 m M%sT 1932 Ap
+-6 - CST 1942 Ap 24
+-7 - MST 1970
+-7 m M%sT 2010 Ap 4 2
+-6 m C%sT
+Z America/Barbados -3:58:29 - LMT 1911 Au 28
+-4 BB A%sT 1944
+-4 BB AST/-0330 1945
+-4 BB A%sT
+Z America/Belem -3:13:56 - LMT 1914
+-3 B %z 1988 S 12
+-3 - %z
+Z America/Belize -5:52:48 - LMT 1912 Ap
+-6 BZ %s
+Z America/Boa_Vista -4:2:40 - LMT 1914
+-4 B %z 1988 S 12
+-4 - %z 1999 S 30
+-4 B %z 2000 O 15
+-4 - %z
+Z America/Bogota -4:56:16 - LMT 1884 Mar 13
+-4:56:16 - BMT 1914 N 23
+-5 CO %z
+Z America/Boise -7:44:49 - LMT 1883 N 18 20u
+-8 u P%sT 1923 May 13 2
+-7 u M%sT 1974
+-7 - MST 1974 F 3 2
+-7 u M%sT
+Z America/Cambridge_Bay 0 - -00 1920
+-7 Y M%sT 1999 O 31 2
+-6 C C%sT 2000 O 29 2
+-5 - EST 2000 N 5
+-6 - CST 2001 Ap 1 3
+-7 C M%sT
+Z America/Campo_Grande -3:38:28 - LMT 1914
+-4 B %z
+Z America/Cancun -5:47:4 - LMT 1922 Ja 1 6u
+-6 - CST 1981 D 26 2
+-5 - EST 1983 Ja 4
+-6 m C%sT 1997 O 26 2
+-5 m E%sT 1998 Au 2 2
+-6 m C%sT 2015 F 1 2
+-5 - EST
+Z America/Caracas -4:27:44 - LMT 1890
+-4:27:40 - CMT 1912 F 12
+-4:30 - %z 1965
+-4 - %z 2007 D 9 3
+-4:30 - %z 2016 May 1 2:30
+-4 - %z
+Z America/Cayenne -3:29:20 - LMT 1911 Jul
+-4 - %z 1967 O
+-3 - %z
+Z America/Chicago -5:50:36 - LMT 1883 N 18 18u
+-6 u C%sT 1920
+-6 Ch C%sT 1936 Mar 1 2
+-5 - EST 1936 N 15 2
+-6 Ch C%sT 1942
+-6 u C%sT 1946
+-6 Ch C%sT 1967
+-6 u C%sT
+Z America/Chihuahua -7:4:20 - LMT 1922 Ja 1 7u
+-7 - MST 1927 Jun 10
+-6 - CST 1930 N 15
+-7 m M%sT 1932 Ap
+-6 - CST 1996
+-6 m C%sT 1998
+-6 - CST 1998 Ap Su>=1 3
+-7 m M%sT 2022 O 30 2
+-6 - CST
+Z America/Ciudad_Juarez -7:5:56 - LMT 1922 Ja 1 7u
+-7 - MST 1927 Jun 10
+-6 - CST 1930 N 15
+-7 m M%sT 1932 Ap
+-6 - CST 1996
+-6 m C%sT 1998
+-6 - CST 1998 Ap Su>=1 3
+-7 m M%sT 2010
+-7 u M%sT 2022 O 30 2
+-6 - CST 2022 N 30
+-7 u M%sT
+Z America/Costa_Rica -5:36:13 - LMT 1890
+-5:36:13 - SJMT 1921 Ja 15
+-6 CR C%sT
+Z America/Coyhaique -4:48:16 - LMT 1890
+-4:42:45 - SMT 1910 Ja 10
+-5 - %z 1916 Jul
+-4:42:45 - SMT 1918 S 10
+-4 - %z 1919 Jul
+-4:42:45 - SMT 1927 S
+-5 x %z 1932 S
+-4 - %z 1942 Jun
+-5 - %z 1942 Au
+-4 - %z 1946 Au 28 24
+-5 1 %z 1947 Mar 31 24
+-5 - %z 1947 May 21 23
+-4 x %z 2025 Mar 20
+-3 - %z
+Z America/Cuiaba -3:44:20 - LMT 1914
+-4 B %z 2003 S 24
+-4 - %z 2004 O
+-4 B %z
+Z America/Danmarkshavn -1:14:40 - LMT 1916 Jul 28
+-3 - %z 1980 Ap 6 2
+-3 E %z 1996
+0 - GMT
+Z America/Dawson -9:17:40 - LMT 1900 Au 20
+-9 Y Y%sT 1965
+-9 Yu Y%sT 1973 O 28
+-8 - PST 1980
+-8 C P%sT 2020 N
+-7 - MST
+Z America/Dawson_Creek -8:0:56 - LMT 1884
+-8 C P%sT 1947
+-8 Va P%sT 1972 Au 30 2
+-7 - MST
+Z America/Denver -6:59:56 - LMT 1883 N 18 19u
+-7 u M%sT 1920
+-7 De M%sT 1942
+-7 u M%sT 1946
+-7 De M%sT 1967
+-7 u M%sT
+Z America/Detroit -5:32:11 - LMT 1905
+-6 - CST 1915 May 15 2
+-5 - EST 1942
+-5 u E%sT 1946
+-5 Dt E%sT 1967 Jun 14 0:1
+-5 u E%sT 1969
+-5 - EST 1973
+-5 u E%sT 1975
+-5 - EST 1975 Ap 27 2
+-5 u E%sT
+Z America/Edmonton -7:33:52 - LMT 1906 S
+-7 Ed M%sT 1987
+-7 C M%sT
+Z America/Eirunepe -4:39:28 - LMT 1914
+-5 B %z 1988 S 12
+-5 - %z 1993 S 28
+-5 B %z 1994 S 22
+-5 - %z 2008 Jun 24
+-4 - %z 2013 N 10
+-5 - %z
+Z America/El_Salvador -5:56:48 - LMT 1921
+-6 SV C%sT
+Z America/Fort_Nelson -8:10:47 - LMT 1884
+-8 Va P%sT 1946
+-8 - PST 1947
+-8 Va P%sT 1987
+-8 C P%sT 2015 Mar 8 2
+-7 - MST
+Z America/Fortaleza -2:34 - LMT 1914
+-3 B %z 1990 S 17
+-3 - %z 1999 S 30
+-3 B %z 2000 O 22
+-3 - %z 2001 S 13
+-3 B %z 2002 O
+-3 - %z
+Z America/Glace_Bay -3:59:48 - LMT 1902 Jun 15
+-4 C A%sT 1953
+-4 H A%sT 1954
+-4 - AST 1972
+-4 H A%sT 1974
+-4 C A%sT
+Z America/Goose_Bay -4:1:40 - LMT 1884
+-3:30:52 - NST 1918
+-3:30:52 C N%sT 1919
+-3:30:52 - NST 1935 Mar 30
+-3:30 - NST 1936
+-3:30 j N%sT 1942 May 11
+-3:30 C N%sT 1946
+-3:30 j N%sT 1966 Mar 15 2
+-4 j A%sT 2011 N
+-4 C A%sT
+Z America/Grand_Turk -4:44:32 - LMT 1890
+-5:7:10 - KMT 1912 F
+-5 - EST 1979
+-5 u E%sT 2015 Mar 8 2
+-4 - AST 2018 Mar 11 3
+-5 u E%sT
+Z America/Guatemala -6:2:4 - LMT 1918 O 5
+-6 GT C%sT
+Z America/Guayaquil -5:19:20 - LMT 1890
+-5:14 - QMT 1931
+-5 EC %z
+Z America/Guyana -3:52:39 - LMT 1911 Au
+-4 - %z 1915 Mar
+-3:45 - %z 1975 Au
+-3 - %z 1992 Mar 29 1
+-4 - %z
+Z America/Halifax -4:14:24 - LMT 1902 Jun 15
+-4 H A%sT 1918
+-4 C A%sT 1919
+-4 H A%sT 1942 F 9 2s
+-4 C A%sT 1946
+-4 H A%sT 1974
+-4 C A%sT
+Z America/Havana -5:29:28 - LMT 1890
+-5:29:36 - HMT 1925 Jul 19 12
+-5 Q C%sT
+Z America/Hermosillo -7:23:52 - LMT 1922 Ja 1 7u
+-7 - MST 1927 Jun 10
+-6 - CST 1930 N 15
+-7 m M%sT 1932 Ap
+-6 - CST 1942 Ap 24
+-7 - MST 1996
+-7 m M%sT 1999
+-7 - MST
+Z America/Indiana/Indianapolis -5:44:38 - LMT 1883 N 18 18u
+-6 u C%sT 1920
+-6 In C%sT 1942
+-6 u C%sT 1946
+-6 In C%sT 1955 Ap 24 2
+-5 - EST 1957 S 29 2
+-6 - CST 1958 Ap 27 2
+-5 - EST 1969
+-5 u E%sT 1971
+-5 - EST 2006
+-5 u E%sT
+Z America/Indiana/Knox -5:46:30 - LMT 1883 N 18 18u
+-6 u C%sT 1947
+-6 St C%sT 1962 Ap 29 2
+-5 - EST 1963 O 27 2
+-6 u C%sT 1991 O 27 2
+-5 - EST 2006 Ap 2 2
+-6 u C%sT
+Z America/Indiana/Marengo -5:45:23 - LMT 1883 N 18 18u
+-6 u C%sT 1951
+-6 Ma C%sT 1961 Ap 30 2
+-5 - EST 1969
+-5 u E%sT 1974 Ja 6 2
+-6 1 CDT 1974 O 27 2
+-5 u E%sT 1976
+-5 - EST 2006
+-5 u E%sT
+Z America/Indiana/Petersburg -5:49:7 - LMT 1883 N 18 18u
+-6 u C%sT 1955
+-6 Pi C%sT 1965 Ap 25 2
+-5 - EST 1966 O 30 2
+-6 u C%sT 1977 O 30 2
+-5 - EST 2006 Ap 2 2
+-6 u C%sT 2007 N 4 2
+-5 u E%sT
+Z America/Indiana/Tell_City -5:47:3 - LMT 1883 N 18 18u
+-6 u C%sT 1946
+-6 Pe C%sT 1964 Ap 26 2
+-5 - EST 1967 O 29 2
+-6 u C%sT 1969 Ap 27 2
+-5 u E%sT 1971
+-5 - EST 2006 Ap 2 2
+-6 u C%sT
+Z America/Indiana/Vevay -5:40:16 - LMT 1883 N 18 18u
+-6 u C%sT 1954 Ap 25 2
+-5 - EST 1969
+-5 u E%sT 1973
+-5 - EST 2006
+-5 u E%sT
+Z America/Indiana/Vincennes -5:50:7 - LMT 1883 N 18 18u
+-6 u C%sT 1946
+-6 V C%sT 1964 Ap 26 2
+-5 - EST 1969
+-5 u E%sT 1971
+-5 - EST 2006 Ap 2 2
+-6 u C%sT 2007 N 4 2
+-5 u E%sT
+Z America/Indiana/Winamac -5:46:25 - LMT 1883 N 18 18u
+-6 u C%sT 1946
+-6 Pu C%sT 1961 Ap 30 2
+-5 - EST 1969
+-5 u E%sT 1971
+-5 - EST 2006 Ap 2 2
+-6 u C%sT 2007 Mar 11 2
+-5 u E%sT
+Z America/Inuvik 0 - -00 1953
+-8 Y P%sT 1979 Ap lastSu 2
+-7 Y M%sT 1980
+-7 C M%sT
+Z America/Iqaluit 0 - -00 1942 Au
+-5 Y E%sT 1999 O 31 2
+-6 C C%sT 2000 O 29 2
+-5 C E%sT
+Z America/Jamaica -5:7:10 - LMT 1890
+-5:7:10 - KMT 1912 F
+-5 - EST 1974
+-5 u E%sT 1984
+-5 - EST
+Z America/Juneau 15:2:19 - LMT 1867 O 19 15:33:32
+-8:57:41 - LMT 1900 Au 20 12
+-8 - PST 1942
+-8 u P%sT 1946
+-8 - PST 1969
+-8 u P%sT 1980 Ap 27 2
+-9 u Y%sT 1980 O 26 2
+-8 u P%sT 1983 O 30 2
+-9 u Y%sT 1983 N 30
+-9 u AK%sT
+Z America/Kentucky/Louisville -5:43:2 - LMT 1883 N 18 18u
+-6 u C%sT 1921
+-6 v C%sT 1942
+-6 u C%sT 1946
+-6 v C%sT 1961 Jul 23 2
+-5 - EST 1968
+-5 u E%sT 1974 Ja 6 2
+-6 1 CDT 1974 O 27 2
+-5 u E%sT
+Z America/Kentucky/Monticello -5:39:24 - LMT 1883 N 18 18u
+-6 u C%sT 1946
+-6 - CST 1968
+-6 u C%sT 2000 O 29 2
+-5 u E%sT
+Z America/La_Paz -4:32:36 - LMT 1890
+-4:32:36 - CMT 1931 O 15
+-4:32:36 1 BST 1932 Mar 21
+-4 - %z
+Z America/Lima -5:8:12 - LMT 1890
+-5:8:36 - LMT 1908 Jul 28
+-5 PE %z
+Z America/Los_Angeles -7:52:58 - LMT 1883 N 18 20u
+-8 u P%sT 1946
+-8 CA P%sT 1967
+-8 u P%sT
+Z America/Maceio -2:22:52 - LMT 1914
+-3 B %z 1990 S 17
+-3 - %z 1995 O 13
+-3 B %z 1996 S 4
+-3 - %z 1999 S 30
+-3 B %z 2000 O 22
+-3 - %z 2001 S 13
+-3 B %z 2002 O
+-3 - %z
+Z America/Managua -5:45:8 - LMT 1890
+-5:45:12 - MMT 1934 Jun 23
+-6 - CST 1973 May
+-5 - EST 1975 F 16
+-6 NI C%sT 1992 Ja 1 4
+-5 - EST 1992 S 24
+-6 - CST 1993
+-5 - EST 1997
+-6 NI C%sT
+Z America/Manaus -4:0:4 - LMT 1914
+-4 B %z 1988 S 12
+-4 - %z 1993 S 28
+-4 B %z 1994 S 22
+-4 - %z
+Z America/Martinique -4:4:20 - LMT 1890
+-4:4:20 - FFMT 1911 May
+-4 - AST 1980 Ap 6
+-4 1 ADT 1980 S 28
+-4 - AST
+Z America/Matamoros -6:30 - LMT 1922 Ja 1 6u
+-6 - CST 1988
+-6 u C%sT 1989
+-6 m C%sT 2010
+-6 u C%sT
+Z America/Mazatlan -7:5:40 - LMT 1922 Ja 1 7u
+-7 - MST 1927 Jun 10
+-6 - CST 1930 N 15
+-7 m M%sT 1932 Ap
+-6 - CST 1942 Ap 24
+-7 - MST 1970
+-7 m M%sT
+Z America/Menominee -5:50:27 - LMT 1885 S 18 12
+-6 u C%sT 1946
+-6 Me C%sT 1969 Ap 27 2
+-5 - EST 1973 Ap 29 2
+-6 u C%sT
+Z America/Merida -5:58:28 - LMT 1922 Ja 1 6u
+-6 - CST 1981 D 26 2
+-5 - EST 1982 N 2 2
+-6 m C%sT
+Z America/Metlakatla 15:13:42 - LMT 1867 O 19 15:44:55
+-8:46:18 - LMT 1900 Au 20 12
+-8 - PST 1942
+-8 u P%sT 1946
+-8 - PST 1969
+-8 u P%sT 1983 O 30 2
+-8 - PST 2015 N 1 2
+-9 u AK%sT 2018 N 4 2
+-8 - PST 2019 Ja 20 2
+-9 u AK%sT
+Z America/Mexico_City -6:36:36 - LMT 1922 Ja 1 7u
+-7 - MST 1927 Jun 10
+-6 - CST 1930 N 15
+-7 m M%sT 1932 Ap
+-6 m C%sT 2001 S 30 2
+-6 - CST 2002 F 20
+-6 m C%sT
+Z America/Miquelon -3:44:40 - LMT 1911 Jun 15
+-4 - AST 1980 May
+-3 - %z 1987
+-3 C %z
+Z America/Moncton -4:19:8 - LMT 1883 D 9
+-5 - EST 1902 Jun 15
+-4 C A%sT 1933
+-4 o A%sT 1942
+-4 C A%sT 1946
+-4 o A%sT 1973
+-4 C A%sT 1993
+-4 o A%sT 2007
+-4 C A%sT
+Z America/Monterrey -6:41:16 - LMT 1922 Ja 1 6u
+-7 - MST 1927 Jun 10
+-6 - CST 1930 N 15
+-7 m M%sT 1932 Ap
+-6 - CST 1988
+-6 u C%sT 1989
+-6 m C%sT
+Z America/Montevideo -3:44:51 - LMT 1908 Jun 10
+-3:44:51 - MMT 1920 May
+-4 - %z 1923 O
+-3:30 U %z 1942 D 14
+-3 U %z 1960
+-3 U %z 1968
+-3 U %z 1970
+-3 U %z 1974
+-3 U %z 1974 Mar 10
+-3 U %z 1974 D 22
+-3 U %z
+Z America/New_York -4:56:2 - LMT 1883 N 18 17u
+-5 u E%sT 1920
+-5 NY E%sT 1942
+-5 u E%sT 1946
+-5 NY E%sT 1967
+-5 u E%sT
+Z America/Nome 12:58:22 - LMT 1867 O 19 13:29:35
+-11:1:38 - LMT 1900 Au 20 12
+-11 - NST 1942
+-11 u N%sT 1946
+-11 - NST 1967 Ap
+-11 - BST 1969
+-11 u B%sT 1983 O 30 2
+-9 u Y%sT 1983 N 30
+-9 u AK%sT
+Z America/Noronha -2:9:40 - LMT 1914
+-2 B %z 1990 S 17
+-2 - %z 1999 S 30
+-2 B %z 2000 O 15
+-2 - %z 2001 S 13
+-2 B %z 2002 O
+-2 - %z
+Z America/North_Dakota/Beulah -6:47:7 - LMT 1883 N 18 19u
+-7 u M%sT 2010 N 7 2
+-6 u C%sT
+Z America/North_Dakota/Center -6:45:12 - LMT 1883 N 18 19u
+-7 u M%sT 1992 O 25 2
+-6 u C%sT
+Z America/North_Dakota/New_Salem -6:45:39 - LMT 1883 N 18 19u
+-7 u M%sT 2003 O 26 2
+-6 u C%sT
+Z America/Nuuk -3:26:56 - LMT 1916 Jul 28
+-3 - %z 1980 Ap 6 2
+-3 E %z 2023 Mar 26 1u
+-2 - %z 2023 O 29 1u
+-2 E %z
+Z America/Ojinaga -6:57:40 - LMT 1922 Ja 1 7u
+-7 - MST 1927 Jun 10
+-6 - CST 1930 N 15
+-7 m M%sT 1932 Ap
+-6 - CST 1996
+-6 m C%sT 1998
+-6 - CST 1998 Ap Su>=1 3
+-7 m M%sT 2010
+-7 u M%sT 2022 O 30 2
+-6 - CST 2022 N 30
+-6 u C%sT
+Z America/Panama -5:18:8 - LMT 1890
+-5:19:36 - CMT 1908 Ap 22
+-5 - EST
+Z America/Paramaribo -3:40:40 - LMT 1911
+-3:40:52 - PMT 1935
+-3:40:36 - PMT 1945 O
+-3:30 - %z 1984 O
+-3 - %z
+Z America/Phoenix -7:28:18 - LMT 1883 N 18 19u
+-7 u M%sT 1944 Ja 1 0:1
+-7 - MST 1944 Ap 1 0:1
+-7 u M%sT 1944 O 1 0:1
+-7 - MST 1967
+-7 u M%sT 1968 Mar 21
+-7 - MST
+Z America/Port-au-Prince -4:49:20 - LMT 1890
+-4:49 - PPMT 1917 Ja 24 12
+-5 HT E%sT
+Z America/Porto_Velho -4:15:36 - LMT 1914
+-4 B %z 1988 S 12
+-4 - %z
+Z America/Puerto_Rico -4:24:25 - LMT 1899 Mar 28 12
+-4 - AST 1942 May 3
+-4 u A%sT 1946
+-4 - AST
+Z America/Punta_Arenas -4:43:40 - LMT 1890
+-4:42:45 - SMT 1910 Ja 10
+-5 - %z 1916 Jul
+-4:42:45 - SMT 1918 S 10
+-4 - %z 1919 Jul
+-4:42:45 - SMT 1927 S
+-5 x %z 1932 S
+-4 - %z 1942 Jun
+-5 - %z 1942 Au
+-4 - %z 1946 Au 28 24
+-5 1 %z 1947 Mar 31 24
+-5 - %z 1947 May 21 23
+-4 x %z 2016 D 4
+-3 - %z
+Z America/Rankin_Inlet 0 - -00 1957
+-6 Y C%sT 2000 O 29 2
+-5 - EST 2001 Ap 1 3
+-6 C C%sT
+Z America/Recife -2:19:36 - LMT 1914
+-3 B %z 1990 S 17
+-3 - %z 1999 S 30
+-3 B %z 2000 O 15
+-3 - %z 2001 S 13
+-3 B %z 2002 O
+-3 - %z
+Z America/Regina -6:58:36 - LMT 1905 S
+-7 r M%sT 1960 Ap lastSu 2
+-6 - CST
+Z America/Resolute 0 - -00 1947 Au 31
+-6 Y C%sT 2000 O 29 2
+-5 - EST 2001 Ap 1 3
+-6 C C%sT 2006 O 29 2
+-5 - EST 2007 Mar 11 3
+-6 C C%sT
+Z America/Rio_Branco -4:31:12 - LMT 1914
+-5 B %z 1988 S 12
+-5 - %z 2008 Jun 24
+-4 - %z 2013 N 10
+-5 - %z
+Z America/Santarem -3:38:48 - LMT 1914
+-4 B %z 1988 S 12
+-4 - %z 2008 Jun 24
+-3 - %z
+Z America/Santiago -4:42:45 - LMT 1890
+-4:42:45 - SMT 1910 Ja 10
+-5 - %z 1916 Jul
+-4:42:45 - SMT 1918 S 10
+-4 - %z 1919 Jul
+-4:42:45 - SMT 1927 S
+-5 x %z 1932 S
+-4 - %z 1942 Jun
+-5 - %z 1942 Au
+-4 - %z 1946 Jul 14 24
+-4 1 %z 1946 Au 28 24
+-5 1 %z 1947 Mar 31 24
+-5 - %z 1947 May 21 23
+-4 x %z
+Z America/Santo_Domingo -4:39:36 - LMT 1890
+-4:40 - SDMT 1933 Ap 1 12
+-5 DO %s 1974 O 27
+-4 - AST 2000 O 29 2
+-5 u E%sT 2000 D 3 1
+-4 - AST
+Z America/Sao_Paulo -3:6:28 - LMT 1914
+-3 B %z 1963 O 23
+-3 1 %z 1964
+-3 B %z
+Z America/Scoresbysund -1:27:52 - LMT 1916 Jul 28
+-2 - %z 1980 Ap 6 2
+-2 c %z 1981 Mar 29
+-1 E %z 2024 Mar 31
+-2 E %z
+Z America/Sitka 14:58:47 - LMT 1867 O 19 15:30
+-9:1:13 - LMT 1900 Au 20 12
+-8 - PST 1942
+-8 u P%sT 1946
+-8 - PST 1969
+-8 u P%sT 1983 O 30 2
+-9 u Y%sT 1983 N 30
+-9 u AK%sT
+Z America/St_Johns -3:30:52 - LMT 1884
+-3:30:52 j N%sT 1918
+-3:30:52 C N%sT 1919
+-3:30:52 j N%sT 1935 Mar 30
+-3:30 j N%sT 1942 May 11
+-3:30 C N%sT 1946
+-3:30 j N%sT 2011 N
+-3:30 C N%sT
+Z America/Swift_Current -7:11:20 - LMT 1905 S
+-7 C M%sT 1946 Ap lastSu 2
+-7 r M%sT 1950
+-7 Sw M%sT 1972 Ap lastSu 2
+-6 - CST
+Z America/Tegucigalpa -5:48:52 - LMT 1921 Ap
+-6 HN C%sT
+Z America/Thule -4:35:8 - LMT 1916 Jul 28
+-4 Th A%sT
+Z America/Tijuana -7:48:4 - LMT 1922 Ja 1 7u
+-7 - MST 1924
+-8 - PST 1927 Jun 10
+-7 - MST 1930 N 15
+-8 - PST 1931 Ap
+-8 1 PDT 1931 S 30
+-8 - PST 1942 Ap 24
+-8 1 PWT 1945 Au 14 23u
+-8 1 PPT 1945 N 15
+-8 - PST 1948 Ap 5
+-8 1 PDT 1949 Ja 14
+-8 - PST 1950 May
+-8 1 PDT 1950 S 24
+-8 - PST 1951 Ap 29 2
+-8 1 PDT 1951 S 30 2
+-8 - PST 1952 Ap 27 2
+-8 1 PDT 1952 S 28 2
+-8 - PST 1954
+-8 CA P%sT 1961
+-8 - PST 1976
+-8 u P%sT 1996
+-8 m P%sT 2001
+-8 u P%sT 2002 F 20
+-8 m P%sT 2010
+-8 u P%sT
+Z America/Toronto -5:17:32 - LMT 1895
+-5 C E%sT 1919
+-5 t E%sT 1942 F 9 2s
+-5 C E%sT 1946
+-5 t E%sT 1974
+-5 C E%sT
+Z America/Vancouver -8:12:28 - LMT 1884
+-8 Va P%sT 1987
+-8 C P%sT
+Z America/Whitehorse -9:0:12 - LMT 1900 Au 20
+-9 Y Y%sT 1965
+-9 Yu Y%sT 1966 F 27
+-8 - PST 1980
+-8 C P%sT 2020 N
+-7 - MST
+Z America/Winnipeg -6:28:36 - LMT 1887 Jul 16
+-6 W C%sT 2006
+-6 C C%sT
+Z America/Yakutat 14:41:5 - LMT 1867 O 19 15:12:18
+-9:18:55 - LMT 1900 Au 20 12
+-9 - YST 1942
+-9 u Y%sT 1946
+-9 - YST 1969
+-9 u Y%sT 1983 N 30
+-9 u AK%sT
+Z Antarctica/Casey 0 - -00 1969
+8 - %z 2009 O 18 2
+11 - %z 2010 Mar 5 2
+8 - %z 2011 O 28 2
+11 - %z 2012 F 21 17u
+8 - %z 2016 O 22
+11 - %z 2018 Mar 11 4
+8 - %z 2018 O 7 4
+11 - %z 2019 Mar 17 3
+8 - %z 2019 O 4 3
+11 - %z 2020 Mar 8 3
+8 - %z 2020 O 4 0:1
+11 - %z 2021 Mar 14
+8 - %z 2021 O 3 0:1
+11 - %z 2022 Mar 13
+8 - %z 2022 O 2 0:1
+11 - %z 2023 Mar 9 3
+8 - %z
+Z Antarctica/Davis 0 - -00 1957 Ja 13
+7 - %z 1964 N
+0 - -00 1969 F
+7 - %z 2009 O 18 2
+5 - %z 2010 Mar 10 20u
+7 - %z 2011 O 28 2
+5 - %z 2012 F 21 20u
+7 - %z
+Z Antarctica/Macquarie 0 - -00 1899 N
+10 - AEST 1916 O 1 2
+10 1 AEDT 1917 F
+10 AU AE%sT 1919 Ap 1 0s
+0 - -00 1948 Mar 25
+10 AU AE%sT 1967
+10 AT AE%sT 2010
+10 1 AEDT 2011
+10 AT AE%sT
+Z Antarctica/Mawson 0 - -00 1954 F 13
+6 - %z 2009 O 18 2
+5 - %z
+Z Antarctica/Palmer 0 - -00 1965
+-4 A %z 1969 O 5
+-3 A %z 1982 May
+-4 x %z 2016 D 4
+-3 - %z
+Z Antarctica/Rothera 0 - -00 1976 D
+-3 - %z
+Z Antarctica/Troll 0 - -00 2005 F 12
+0 Tr %s
+Z Antarctica/Vostok 0 - -00 1957 D 16
+7 - %z 1994 F
+0 - -00 1994 N
+7 - %z 2023 D 18 2
+5 - %z
+Z Asia/Almaty 5:7:48 - LMT 1924 May 2
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 R %z 1992 Ja 19 2s
+6 R %z 2004 O 31 2s
+6 - %z 2024 Mar
+5 - %z
+Z Asia/Amman 2:23:44 - LMT 1931
+2 J EE%sT 2022 O 28 0s
+3 - %z
+Z Asia/Anadyr 11:49:56 - LMT 1924 May 2
+12 - %z 1930 Jun 21
+13 R %z 1982 Ap 1 0s
+12 R %z 1991 Mar 31 2s
+11 R %z 1992 Ja 19 2s
+12 R %z 2010 Mar 28 2s
+11 R %z 2011 Mar 27 2s
+12 - %z
+Z Asia/Aqtau 3:21:4 - LMT 1924 May 2
+4 - %z 1930 Jun 21
+5 - %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 1994 S 25 2s
+4 R %z 2004 O 31 2s
+5 - %z
+Z Asia/Aqtobe 3:48:40 - LMT 1924 May 2
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 2004 O 31 2s
+5 - %z
+Z Asia/Ashgabat 3:53:32 - LMT 1924 May 2
+4 - %z 1930 Jun 21
+5 R %z 1991 Mar 31 2
+4 R %z 1992 Ja 19 2
+5 - %z
+Z Asia/Atyrau 3:27:44 - LMT 1924 May 2
+3 - %z 1930 Jun 21
+5 - %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 1999 Mar 28 2s
+4 R %z 2004 O 31 2s
+5 - %z
+Z Asia/Baghdad 2:57:40 - LMT 1890
+2:57:36 - BMT 1918
+3 - %z 1982 May
+3 IQ %z
+Z Asia/Baku 3:19:24 - LMT 1924 May 2
+3 - %z 1957 Mar
+4 R %z 1991 Mar 31 2s
+3 R %z 1992 S lastSu 2s
+4 - %z 1996
+4 E %z 1997
+4 AZ %z
+Z Asia/Bangkok 6:42:4 - LMT 1880
+6:42:4 - BMT 1920 Ap
+7 - %z
+Z Asia/Barnaul 5:35 - LMT 1919 D 10
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 1995 May 28
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z 2016 Mar 27 2s
+7 - %z
+Z Asia/Beirut 2:22 - LMT 1880
+2 l EE%sT
+Z Asia/Bishkek 4:58:24 - LMT 1924 May 2
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 R %z 1991 Au 31 2
+5 KG %z 2005 Au 12
+6 - %z
+Z Asia/Chita 7:33:52 - LMT 1919 D 15
+8 - %z 1930 Jun 21
+9 R %z 1991 Mar 31 2s
+8 R %z 1992 Ja 19 2s
+9 R %z 2011 Mar 27 2s
+10 - %z 2014 O 26 2s
+8 - %z 2016 Mar 27 2
+9 - %z
+Z Asia/Colombo 5:19:24 - LMT 1880
+5:19:32 - MMT 1906
+5:30 - %z 1942 Ja 5
+5:30 0:30 %z 1942 S
+5:30 1 %z 1945 O 16 2
+5:30 - %z 1996 May 25
+6:30 - %z 1996 O 26 0:30
+6 - %z 2006 Ap 15 0:30
+5:30 - %z
+Z Asia/Damascus 2:25:12 - LMT 1920
+2 S EE%sT 2022 O 28
+3 - %z
+Z Asia/Dhaka 6:1:40 - LMT 1890
+5:53:20 - HMT 1941 O
+6:30 - %z 1942 May 15
+5:30 - %z 1942 S
+6:30 - %z 1951 S 30
+6 - %z 2009
+6 BD %z
+Z Asia/Dili 8:22:20 - LMT 1911 D 31 16u
+8 - %z 1942 F 21 23
+9 - %z 1976 May 3
+8 - %z 2000 S 17
+9 - %z
+Z Asia/Dubai 3:41:12 - LMT 1920
+4 - %z
+Z Asia/Dushanbe 4:35:12 - LMT 1924 May 2
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 1 %z 1991 S 9 2s
+5 - %z
+Z Asia/Famagusta 2:15:48 - LMT 1921 N 14
+2 CY EE%sT 1998 S
+2 E EE%sT 2016 S 8
+3 - %z 2017 O 29 1u
+2 E EE%sT
+Z Asia/Gaza 2:17:52 - LMT 1900 O
+2 Z EET/EEST 1948 May 15
+2 K EE%sT 1967 Jun 5
+2 Z I%sT 1996
+2 J EE%sT 1999
+2 P EE%sT 2008 Au 29
+2 - EET 2008 S
+2 P EE%sT 2010
+2 - EET 2010 Mar 27 0:1
+2 P EE%sT 2011 Au
+2 - EET 2012
+2 P EE%sT
+Z Asia/Hebron 2:20:23 - LMT 1900 O
+2 Z EET/EEST 1948 May 15
+2 K EE%sT 1967 Jun 5
+2 Z I%sT 1996
+2 J EE%sT 1999
+2 P EE%sT
+Z Asia/Ho_Chi_Minh 7:6:30 - LMT 1906 Jul
+7:6:30 - PLMT 1911 May
+7 - %z 1942 D 31 23
+8 - %z 1945 Mar 14 23
+9 - %z 1945 S 1 24
+7 - %z 1947 Ap
+8 - %z 1955 Jul 1 1
+7 - %z 1959 D 31 23
+8 - %z 1975 Jun 13
+7 - %z
+Z Asia/Hong_Kong 7:36:42 - LMT 1904 O 29 17u
+8 - HKT 1941 Jun 15 3
+8 1 HKST 1941 O 1 4
+8 0:30 HKWT 1941 D 25
+9 - JST 1945 N 18 2
+8 HK HK%sT
+Z Asia/Hovd 6:6:36 - LMT 1905 Au
+6 - %z 1978
+7 X %z
+Z Asia/Irkutsk 6:57:5 - LMT 1880
+6:57:5 - IMT 1920 Ja 25
+7 - %z 1930 Jun 21
+8 R %z 1991 Mar 31 2s
+7 R %z 1992 Ja 19 2s
+8 R %z 2011 Mar 27 2s
+9 - %z 2014 O 26 2s
+8 - %z
+Z Asia/Jakarta 7:7:12 - LMT 1867 Au 10
+7:7:12 - BMT 1923 D 31 16:40u
+7:20 - %z 1932 N
+7:30 - %z 1942 Mar 23
+9 - %z 1945 S 23
+7:30 - %z 1948 May
+8 - %z 1950 May
+7:30 - %z 1964
+7 - WIB
+Z Asia/Jayapura 9:22:48 - LMT 1932 N
+9 - %z 1944 S
+9:30 - %z 1964
+9 - WIT
+Z Asia/Jerusalem 2:20:54 - LMT 1880
+2:20:40 - JMT 1918
+2 Z I%sT
+Z Asia/Kabul 4:36:48 - LMT 1890
+4 - %z 1945
+4:30 - %z
+Z Asia/Kamchatka 10:34:36 - LMT 1922 N 10
+11 - %z 1930 Jun 21
+12 R %z 1991 Mar 31 2s
+11 R %z 1992 Ja 19 2s
+12 R %z 2010 Mar 28 2s
+11 R %z 2011 Mar 27 2s
+12 - %z
+Z Asia/Karachi 4:28:12 - LMT 1907
+5:30 - %z 1942 S
+5:30 1 %z 1945 O 15
+5:30 - %z 1951 S 30
+5 - %z 1971 Mar 26
+5 PK PK%sT
+Z Asia/Kathmandu 5:41:16 - LMT 1920
+5:30 - %z 1986
+5:45 - %z
+Z Asia/Khandyga 9:2:13 - LMT 1919 D 15
+8 - %z 1930 Jun 21
+9 R %z 1991 Mar 31 2s
+8 R %z 1992 Ja 19 2s
+9 R %z 2004
+10 R %z 2011 Mar 27 2s
+11 - %z 2011 S 13 0s
+10 - %z 2014 O 26 2s
+9 - %z
+Z Asia/Kolkata 5:53:28 - LMT 1854 Jun 28
+5:53:20 - HMT 1870
+5:21:10 - MMT 1906
+5:30 - IST 1941 O
+5:30 1 %z 1942 May 15
+5:30 - IST 1942 S
+5:30 1 %z 1945 O 15
+5:30 - IST
+Z Asia/Krasnoyarsk 6:11:26 - LMT 1920 Ja 6
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 2011 Mar 27 2s
+8 - %z 2014 O 26 2s
+7 - %z
+Z Asia/Kuching 7:21:20 - LMT 1926 Mar
+7:30 - %z 1933
+8 NB %z 1942 F 16
+9 - %z 1945 S 12
+8 - %z
+Z Asia/Macau 7:34:10 - LMT 1904 O 30
+8 - CST 1941 D 21 23
+9 _ %z 1945 S 30 24
+8 _ C%sT
+Z Asia/Magadan 10:3:12 - LMT 1924 May 2
+10 - %z 1930 Jun 21
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 2011 Mar 27 2s
+12 - %z 2014 O 26 2s
+10 - %z 2016 Ap 24 2s
+11 - %z
+Z Asia/Makassar 7:57:36 - LMT 1920
+7:57:36 - MMT 1932 N
+8 - %z 1942 F 9
+9 - %z 1945 S 23
+8 - WITA
+Z Asia/Manila -15:56:8 - LMT 1844 D 31
+8:3:52 - LMT 1899 S 6 4u
+8 PH P%sT 1942 F 11 24
+9 - JST 1945 Mar 4
+8 PH P%sT
+Z Asia/Nicosia 2:13:28 - LMT 1921 N 14
+2 CY EE%sT 1998 S
+2 E EE%sT
+Z Asia/Novokuznetsk 5:48:48 - LMT 1924 May
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 2010 Mar 28 2s
+6 R %z 2011 Mar 27 2s
+7 - %z
+Z Asia/Novosibirsk 5:31:40 - LMT 1919 D 14 6
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 1993 May 23
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z 2016 Jul 24 2s
+7 - %z
+Z Asia/Omsk 4:53:30 - LMT 1919 N 14
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2s
+5 R %z 1992 Ja 19 2s
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z
+Z Asia/Oral 3:25:24 - LMT 1924 May 2
+3 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1989 Mar 26 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 1992 Mar 29 2s
+4 R %z 2004 O 31 2s
+5 - %z
+Z Asia/Pontianak 7:17:20 - LMT 1908 May
+7:17:20 - PMT 1932 N
+7:30 - %z 1942 Ja 29
+9 - %z 1945 S 23
+7:30 - %z 1948 May
+8 - %z 1950 May
+7:30 - %z 1964
+8 - WITA 1988
+7 - WIB
+Z Asia/Pyongyang 8:23 - LMT 1908 Ap
+8:30 - KST 1912
+9 - JST 1945 Au 24
+9 - KST 2015 Au 15
+8:30 - KST 2018 May 4 23:30
+9 - KST
+Z Asia/Qatar 3:26:8 - LMT 1920
+4 - %z 1972 Jun
+3 - %z
+Z Asia/Qostanay 4:14:28 - LMT 1924 May 2
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 2004 O 31 2s
+6 - %z 2024 Mar
+5 - %z
+Z Asia/Qyzylorda 4:21:52 - LMT 1924 May 2
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1991 Mar 31 2s
+4 R %z 1991 S 29 2s
+5 R %z 1992 Ja 19 2s
+6 R %z 1992 Mar 29 2s
+5 R %z 2004 O 31 2s
+6 - %z 2018 D 21
+5 - %z
+Z Asia/Riyadh 3:6:52 - LMT 1947 Mar 14
+3 - %z
+Z Asia/Sakhalin 9:30:48 - LMT 1905 Au 23
+9 - %z 1945 Au 25
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 1997 Mar lastSu 2s
+10 R %z 2011 Mar 27 2s
+11 - %z 2014 O 26 2s
+10 - %z 2016 Mar 27 2s
+11 - %z
+Z Asia/Samarkand 4:27:53 - LMT 1924 May 2
+4 - %z 1930 Jun 21
+5 - %z 1981 Ap
+5 1 %z 1981 O
+6 - %z 1982 Ap
+5 R %z 1992
+5 - %z
+Z Asia/Seoul 8:27:52 - LMT 1908 Ap
+8:30 - KST 1912
+9 - JST 1945 S 8
+9 KR K%sT 1954 Mar 21
+8:30 KR K%sT 1961 Au 10
+9 KR K%sT
+Z Asia/Shanghai 8:5:43 - LMT 1901
+8 Sh C%sT 1949 May 28
+8 CN C%sT
+Z Asia/Singapore 6:55:25 - LMT 1901
+6:55:25 - SMT 1905 Jun
+7 - %z 1933
+7 0:20 %z 1936
+7:20 - %z 1941 S
+7:30 - %z 1942 F 16
+9 - %z 1945 S 12
+7:30 - %z 1981 D 31 16u
+8 - %z
+Z Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2
+10 - %z 1930 Jun 21
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 2011 Mar 27 2s
+12 - %z 2014 O 26 2s
+11 - %z
+Z Asia/Taipei 8:6 - LMT 1896
+8 - CST 1937 O
+9 - JST 1945 S 21 1
+8 f C%sT
+Z Asia/Tashkent 4:37:11 - LMT 1924 May 2
+5 - %z 1930 Jun 21
+6 R %z 1991 Mar 31 2
+5 R %z 1992
+5 - %z
+Z Asia/Tbilisi 2:59:11 - LMT 1880
+2:59:11 - TBMT 1924 May 2
+3 - %z 1957 Mar
+4 R %z 1991 Mar 31 2s
+3 R %z 1992
+3 e %z 1994 S lastSu
+4 e %z 1996 O lastSu
+4 1 %z 1997 Mar lastSu
+4 e %z 2004 Jun 27
+3 R %z 2005 Mar lastSu 2
+4 - %z
+Z Asia/Tehran 3:25:44 - LMT 1916
+3:25:44 - TMT 1935 Jun 13
+3:30 i %z 1977 O 20 24
+4 i %z 1978 N 10 24
+3:30 i %z
+Z Asia/Thimphu 5:58:36 - LMT 1947 Au 15
+5:30 - %z 1987 O
+6 - %z
+Z Asia/Tokyo 9:18:59 - LMT 1887 D 31 15u
+9 JP J%sT
+Z Asia/Tomsk 5:39:51 - LMT 1919 D 22
+6 - %z 1930 Jun 21
+7 R %z 1991 Mar 31 2s
+6 R %z 1992 Ja 19 2s
+7 R %z 2002 May 1 3
+6 R %z 2011 Mar 27 2s
+7 - %z 2014 O 26 2s
+6 - %z 2016 May 29 2s
+7 - %z
+Z Asia/Ulaanbaatar 7:7:32 - LMT 1905 Au
+7 - %z 1978
+8 X %z
+Z Asia/Urumqi 5:50:20 - LMT 1928
+6 - %z
+Z Asia/Ust-Nera 9:32:54 - LMT 1919 D 15
+8 - %z 1930 Jun 21
+9 R %z 1981 Ap
+11 R %z 1991 Mar 31 2s
+10 R %z 1992 Ja 19 2s
+11 R %z 2011 Mar 27 2s
+12 - %z 2011 S 13 0s
+11 - %z 2014 O 26 2s
+10 - %z
+Z Asia/Vladivostok 8:47:31 - LMT 1922 N 15
+9 - %z 1930 Jun 21
+10 R %z 1991 Mar 31 2s
+9 R %z 1992 Ja 19 2s
+10 R %z 2011 Mar 27 2s
+11 - %z 2014 O 26 2s
+10 - %z
+Z Asia/Yakutsk 8:38:58 - LMT 1919 D 15
+8 - %z 1930 Jun 21
+9 R %z 1991 Mar 31 2s
+8 R %z 1992 Ja 19 2s
+9 R %z 2011 Mar 27 2s
+10 - %z 2014 O 26 2s
+9 - %z
+Z Asia/Yangon 6:24:47 - LMT 1880
+6:24:47 - RMT 1920
+6:30 - %z 1942 May
+9 - %z 1945 May 3
+6:30 - %z
+Z Asia/Yekaterinburg 4:2:33 - LMT 1916 Jul 3
+3:45:5 - PMT 1919 Jul 15 4
+4 - %z 1930 Jun 21
+5 R %z 1991 Mar 31 2s
+4 R %z 1992 Ja 19 2s
+5 R %z 2011 Mar 27 2s
+6 - %z 2014 O 26 2s
+5 - %z
+Z Asia/Yerevan 2:58 - LMT 1924 May 2
+3 - %z 1957 Mar
+4 R %z 1991 Mar 31 2s
+3 R %z 1995 S 24 2s
+4 - %z 1997
+4 R %z 2011
+4 AM %z
+Z Atlantic/Azores -1:42:40 - LMT 1884
+-1:54:32 - HMT 1912 Ja 1 2u
+-2 p %z 1966 O 2 2s
+-1 - %z 1982 Mar 28 0s
+-1 p %z 1986
+-1 E %z 1992 D 27 1s
+0 E WE%sT 1993 Jun 17 1u
+-1 E %z
+Z Atlantic/Bermuda -4:19:18 - LMT 1890
+-4:19:18 Be BMT/BST 1930 Ja 1 2
+-4 Be A%sT 1974 Ap 28 2
+-4 C A%sT 1976
+-4 u A%sT
+Z Atlantic/Canary -1:1:36 - LMT 1922 Mar
+-1 - %z 1946 S 30 1
+0 - WET 1980 Ap 6 0s
+0 1 WEST 1980 S 28 1u
+0 E WE%sT
+Z Atlantic/Cape_Verde -1:34:4 - LMT 1912 Ja 1 2u
+-2 - %z 1942 S
+-2 1 %z 1945 O 15
+-2 - %z 1975 N 25 2
+-1 - %z
+Z Atlantic/Faroe -0:27:4 - LMT 1908 Ja 11
+0 - WET 1981
+0 E WE%sT
+Z Atlantic/Madeira -1:7:36 - LMT 1884
+-1:7:36 - FMT 1912 Ja 1 1u
+-1 p %z 1966 O 2 2s
+0 - WET 1982 Ap 4
+0 p WE%sT 1986 Jul 31
+0 E WE%sT
+Z Atlantic/South_Georgia -2:26:8 - LMT 1890
+-2 - %z
+Z Atlantic/Stanley -3:51:24 - LMT 1890
+-3:51:24 - SMT 1912 Mar 12
+-4 FK %z 1983 May
+-3 FK %z 1985 S 15
+-4 FK %z 2010 S 5 2
+-3 - %z
+Z Australia/Adelaide 9:14:20 - LMT 1895 F
+9 - ACST 1899 May
+9:30 AU AC%sT 1971
+9:30 AS AC%sT
+Z Australia/Brisbane 10:12:8 - LMT 1895
+10 AU AE%sT 1971
+10 AQ AE%sT
+Z Australia/Broken_Hill 9:25:48 - LMT 1895 F
+10 - AEST 1896 Au 23
+9 - ACST 1899 May
+9:30 AU AC%sT 1971
+9:30 AN AC%sT 2000
+9:30 AS AC%sT
+Z Australia/Darwin 8:43:20 - LMT 1895 F
+9 - ACST 1899 May
+9:30 AU AC%sT
+Z Australia/Eucla 8:35:28 - LMT 1895 D
+8:45 AU %z 1943 Jul
+8:45 AW %z
+Z Australia/Hobart 9:49:16 - LMT 1895 S
+10 AT AE%sT 1919 O 24
+10 AU AE%sT 1967
+10 AT AE%sT
+Z Australia/Lindeman 9:55:56 - LMT 1895
+10 AU AE%sT 1971
+10 AQ AE%sT 1992 Jul
+10 Ho AE%sT
+Z Australia/Lord_Howe 10:36:20 - LMT 1895 F
+10 - AEST 1981 Mar
+10:30 LH %z 1985 Jul
+10:30 LH %z
+Z Australia/Melbourne 9:39:52 - LMT 1895 F
+10 AU AE%sT 1971
+10 AV AE%sT
+Z Australia/Perth 7:43:24 - LMT 1895 D
+8 AU AW%sT 1943 Jul
+8 AW AW%sT
+Z Australia/Sydney 10:4:52 - LMT 1895 F
+10 AU AE%sT 1971
+10 AN AE%sT
+Z Etc/GMT 0 - GMT
+Z Etc/GMT+1 -1 - %z
+Z Etc/GMT+10 -10 - %z
+Z Etc/GMT+11 -11 - %z
+Z Etc/GMT+12 -12 - %z
+Z Etc/GMT+2 -2 - %z
+Z Etc/GMT+3 -3 - %z
+Z Etc/GMT+4 -4 - %z
+Z Etc/GMT+5 -5 - %z
+Z Etc/GMT+6 -6 - %z
+Z Etc/GMT+7 -7 - %z
+Z Etc/GMT+8 -8 - %z
+Z Etc/GMT+9 -9 - %z
+Z Etc/GMT-1 1 - %z
+Z Etc/GMT-10 10 - %z
+Z Etc/GMT-11 11 - %z
+Z Etc/GMT-12 12 - %z
+Z Etc/GMT-13 13 - %z
+Z Etc/GMT-14 14 - %z
+Z Etc/GMT-2 2 - %z
+Z Etc/GMT-3 3 - %z
+Z Etc/GMT-4 4 - %z
+Z Etc/GMT-5 5 - %z
+Z Etc/GMT-6 6 - %z
+Z Etc/GMT-7 7 - %z
+Z Etc/GMT-8 8 - %z
+Z Etc/GMT-9 9 - %z
+Z Etc/UTC 0 - UTC
+Z Europe/Andorra 0:6:4 - LMT 1901
+0 - WET 1946 S 30
+1 - CET 1985 Mar 31 2
+1 E CE%sT
+Z Europe/Astrakhan 3:12:12 - LMT 1924 May
+3 - %z 1930 Jun 21
+4 R %z 1989 Mar 26 2s
+3 R %z 1991 Mar 31 2s
+4 - %z 1992 Mar 29 2s
+3 R %z 2011 Mar 27 2s
+4 - %z 2014 O 26 2s
+3 - %z 2016 Mar 27 2s
+4 - %z
+Z Europe/Athens 1:34:52 - LMT 1895 S 14
+1:34:52 - AMT 1916 Jul 28 0:1
+2 g EE%sT 1941 Ap 30
+1 g CE%sT 1944 Ap 4
+2 g EE%sT 1981
+2 E EE%sT
+Z Europe/Belgrade 1:22 - LMT 1884
+1 - CET 1941 Ap 18 23
+1 c CE%sT 1945
+1 - CET 1945 May 8 2s
+1 1 CEST 1945 S 16 2s
+1 - CET 1982 N 27
+1 E CE%sT
+Z Europe/Berlin 0:53:28 - LMT 1893 Ap
+1 c CE%sT 1945 May 24 2
+1 So CE%sT 1946
+1 DE CE%sT 1980
+1 E CE%sT
+Z Europe/Brussels 0:17:30 - LMT 1880
+0:17:30 - BMT 1892 May 1 0:17:30
+0 - WET 1914 N 8
+1 - CET 1916 May
+1 c CE%sT 1918 N 11 11u
+0 b WE%sT 1940 May 20 2s
+1 c CE%sT 1944 S 3
+1 b CE%sT 1977
+1 E CE%sT
+Z Europe/Bucharest 1:44:24 - LMT 1891 O
+1:44:24 - BMT 1931 Jul 24
+2 z EE%sT 1981 Mar 29 2s
+2 c EE%sT 1991
+2 z EE%sT 1994
+2 e EE%sT 1997
+2 E EE%sT
+Z Europe/Budapest 1:16:20 - LMT 1890 N
+1 c CE%sT 1918
+1 h CE%sT 1941 Ap 7 23
+1 c CE%sT 1945
+1 h CE%sT 1984
+1 E CE%sT
+Z Europe/Chisinau 1:55:20 - LMT 1880
+1:55 - CMT 1918 F 15
+1:44:24 - BMT 1931 Jul 24
+2 z EE%sT 1940 Au 15
+2 1 EEST 1941 Jul 17
+1 c CE%sT 1944 Au 24
+3 R MSK/MSD 1990 May 6 2
+2 R EE%sT 1992
+2 e EE%sT 1997
+2 MD EE%sT
+Z Europe/Dublin -0:25:21 - LMT 1880 Au 2
+-0:25:21 - DMT 1916 May 21 2s
+-0:25:21 1 IST 1916 O 1 2s
+0 G %s 1921 D 6
+0 G GMT/IST 1940 F 25 2s
+0 1 IST 1946 O 6 2s
+0 - GMT 1947 Mar 16 2s
+0 1 IST 1947 N 2 2s
+0 - GMT 1948 Ap 18 2s
+0 G GMT/IST 1968 O 27
+1 IE IST/GMT
+Z Europe/Gibraltar -0:21:24 - LMT 1880 Au 2
+0 G %s 1957 Ap 14 2
+1 - CET 1982
+1 E CE%sT
+Z Europe/Helsinki 1:39:49 - LMT 1878 May 31
+1:39:49 - HMT 1921 May
+2 FI EE%sT 1983
+2 E EE%sT
+Z Europe/Istanbul 1:55:52 - LMT 1880
+1:56:56 - IMT 1910 O
+2 T EE%sT 1978 Jun 29
+3 T %z 1984 N 1 2
+2 T EE%sT 2007
+2 E EE%sT 2011 Mar 27 1u
+2 - EET 2011 Mar 28 1u
+2 E EE%sT 2014 Mar 30 1u
+2 - EET 2014 Mar 31 1u
+2 E EE%sT 2015 O 25 1u
+2 1 EEST 2015 N 8 1u
+2 E EE%sT 2016 S 7
+3 - %z
+Z Europe/Kaliningrad 1:22 - LMT 1893 Ap
+1 c CE%sT 1945 Ap 10
+2 O EE%sT 1946 Ap 7
+3 R MSK/MSD 1989 Mar 26 2s
+2 R EE%sT 2011 Mar 27 2s
+3 - %z 2014 O 26 2s
+2 - EET
+Z Europe/Kirov 3:18:48 - LMT 1919 Jul 1 0u
+3 - %z 1930 Jun 21
+4 R %z 1989 Mar 26 2s
+3 R MSK/MSD 1991 Mar 31 2s
+4 - %z 1992 Mar 29 2s
+3 R MSK/MSD 2011 Mar 27 2s
+4 - MSK 2014 O 26 2s
+3 - MSK
+Z Europe/Kyiv 2:2:4 - LMT 1880
+2:2:4 - KMT 1924 May 2
+2 - EET 1930 Jun 21
+3 - MSK 1941 S 20
+1 c CE%sT 1943 N 6
+3 R MSK/MSD 1990 Jul 1 2
+2 1 EEST 1991 S 29 3
+2 c EE%sT 1996 May 13
+2 E EE%sT
+Z Europe/Lisbon -0:36:45 - LMT 1884
+-0:36:45 - LMT 1912 Ja 1 0u
+0 p WE%sT 1966 O 2 2s
+1 - CET 1976 S 26 1
+0 p WE%sT 1986
+0 E WE%sT 1992 S 27 1u
+1 E CE%sT 1996 Mar 31 1u
+0 E WE%sT
+Z Europe/London -0:1:15 - LMT 1847 D
+0 G %s 1968 O 27
+1 - BST 1971 O 31 2u
+0 G %s 1996
+0 E GMT/BST
+Z Europe/Madrid -0:14:44 - LMT 1901 Ja 1 0u
+0 s WE%sT 1940 Mar 16 23
+1 s CE%sT 1979
+1 E CE%sT
+Z Europe/Malta 0:58:4 - LMT 1893 N 2
+1 I CE%sT 1973 Mar 31
+1 MT CE%sT 1981
+1 E CE%sT
+Z Europe/Minsk 1:50:16 - LMT 1880
+1:50 - MMT 1924 May 2
+2 - EET 1930 Jun 21
+3 - MSK 1941 Jun 28
+1 c CE%sT 1944 Jul 3
+3 R MSK/MSD 1990
+3 - MSK 1991 Mar 31 2s
+2 R EE%sT 2011 Mar 27 2s
+3 - %z
+Z Europe/Moscow 2:30:17 - LMT 1880
+2:30:17 - MMT 1916 Jul 3
+2:31:19 R %s 1919 Jul 1 0u
+3 R %s 1921 O
+3 R MSK/MSD 1922 O
+2 - EET 1930 Jun 21
+3 R MSK/MSD 1991 Mar 31 2s
+2 R EE%sT 1992 Ja 19 2s
+3 R MSK/MSD 2011 Mar 27 2s
+4 - MSK 2014 O 26 2s
+3 - MSK
+Z Europe/Paris 0:9:21 - LMT 1891 Mar 16
+0:9:21 - PMT 1911 Mar 11
+0 F WE%sT 1940 Jun 14 23
+1 c CE%sT 1944 Au 25
+0 F WE%sT 1945 S 16 3
+1 F CE%sT 1977
+1 E CE%sT
+Z Europe/Prague 0:57:44 - LMT 1850
+0:57:44 - PMT 1891 O
+1 c CE%sT 1945 May 9
+1 CZ CE%sT 1946 D 1 3
+1 -1 GMT 1947 F 23 2
+1 CZ CE%sT 1979
+1 E CE%sT
+Z Europe/Riga 1:36:34 - LMT 1880
+1:36:34 - RMT 1918 Ap 15 2
+1:36:34 1 LST 1918 S 16 3
+1:36:34 - RMT 1919 Ap 1 2
+1:36:34 1 LST 1919 May 22 3
+1:36:34 - RMT 1926 May 11
+2 - EET 1940 Au 5
+3 - MSK 1941 Jul
+1 c CE%sT 1944 O 13
+3 R MSK/MSD 1989 Mar lastSu 2s
+2 1 EEST 1989 S lastSu 2s
+2 LV EE%sT 1997 Ja 21
+2 E EE%sT 2000 F 29
+2 - EET 2001 Ja 2
+2 E EE%sT
+Z Europe/Rome 0:49:56 - LMT 1866 D 12
+0:49:56 - RMT 1893 O 31 23u
+1 I CE%sT 1943 S 10
+1 c CE%sT 1944 Jun 4
+1 I CE%sT 1980
+1 E CE%sT
+Z Europe/Samara 3:20:20 - LMT 1919 Jul 1 0u
+3 - %z 1930 Jun 21
+4 - %z 1935 Ja 27
+4 R %z 1989 Mar 26 2s
+3 R %z 1991 Mar 31 2s
+2 R %z 1991 S 29 2s
+3 - %z 1991 O 20 3
+4 R %z 2010 Mar 28 2s
+3 R %z 2011 Mar 27 2s
+4 - %z
+Z Europe/Saratov 3:4:18 - LMT 1919 Jul 1 0u
+3 - %z 1930 Jun 21
+4 R %z 1988 Mar 27 2s
+3 R %z 1991 Mar 31 2s
+4 - %z 1992 Mar 29 2s
+3 R %z 2011 Mar 27 2s
+4 - %z 2014 O 26 2s
+3 - %z 2016 D 4 2s
+4 - %z
+Z Europe/Simferopol 2:16:24 - LMT 1880
+2:16 - SMT 1924 May 2
+2 - EET 1930 Jun 21
+3 - MSK 1941 N
+1 c CE%sT 1944 Ap 13
+3 R MSK/MSD 1990
+3 - MSK 1990 Jul 1 2
+2 - EET 1992 Mar 20
+2 c EE%sT 1994 May
+3 c MSK/MSD 1996 Mar 31 0s
+3 1 MSD 1996 O 27 3s
+3 - MSK 1997 Mar lastSu 1u
+2 E EE%sT 2014 Mar 30 2
+4 - MSK 2014 O 26 2s
+3 - MSK
+Z Europe/Sofia 1:33:16 - LMT 1880
+1:56:56 - IMT 1894 N 30
+2 - EET 1942 N 2 3
+1 c CE%sT 1945
+1 - CET 1945 Ap 2 3
+2 - EET 1979 Mar 31 23
+2 BG EE%sT 1982 S 26 3
+2 c EE%sT 1991
+2 e EE%sT 1997
+2 E EE%sT
+Z Europe/Tallinn 1:39 - LMT 1880
+1:39 - TMT 1918 F
+1 c CE%sT 1919 Jul
+1:39 - TMT 1921 May
+2 - EET 1940 Au 6
+3 - MSK 1941 S 15
+1 c CE%sT 1944 S 22
+3 R MSK/MSD 1989 Mar 26 2s
+2 1 EEST 1989 S 24 2s
+2 c EE%sT 1998 S 22
+2 E EE%sT 1999 O 31 4
+2 - EET 2002 F 21
+2 E EE%sT
+Z Europe/Tirane 1:19:20 - LMT 1914
+1 - CET 1940 Jun 16
+1 q CE%sT 1984 Jul
+1 E CE%sT
+Z Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 0u
+3 - %z 1930 Jun 21
+4 R %z 1989 Mar 26 2s
+3 R %z 1991 Mar 31 2s
+2 R %z 1992 Ja 19 2s
+3 R %z 2011 Mar 27 2s
+4 - %z 2014 O 26 2s
+3 - %z 2016 Mar 27 2s
+4 - %z
+Z Europe/Vienna 1:5:21 - LMT 1893 Ap
+1 c CE%sT 1920
+1 a CE%sT 1940 Ap 1 2s
+1 c CE%sT 1945 Ap 2 2s
+1 1 CEST 1945 Ap 12 2s
+1 - CET 1946
+1 a CE%sT 1981
+1 E CE%sT
+Z Europe/Vilnius 1:41:16 - LMT 1880
+1:24 - WMT 1917
+1:35:36 - KMT 1919 O 10
+1 - CET 1920 Jul 12
+2 - EET 1920 O 9
+1 - CET 1940 Au 3
+3 - MSK 1941 Jun 24
+1 c CE%sT 1944 Au
+3 R MSK/MSD 1989 Mar 26 2s
+2 R EE%sT 1991 S 29 2s
+2 c EE%sT 1998
+2 - EET 1998 Mar 29 1u
+1 E CE%sT 1999 O 31 1u
+2 - EET 2003
+2 E EE%sT
+Z Europe/Volgograd 2:57:40 - LMT 1920 Ja 3
+3 - %z 1930 Jun 21
+4 - %z 1961 N 11
+4 R %z 1988 Mar 27 2s
+3 R MSK/MSD 1991 Mar 31 2s
+4 - %z 1992 Mar 29 2s
+3 R MSK/MSD 2011 Mar 27 2s
+4 - MSK 2014 O 26 2s
+3 - MSK 2018 O 28 2s
+4 - %z 2020 D 27 2s
+3 - MSK
+Z Europe/Warsaw 1:24 - LMT 1880
+1:24 - WMT 1915 Au 5
+1 c CE%sT 1918 S 16 3
+2 O EE%sT 1922 Jun
+1 O CE%sT 1940 Jun 23 2
+1 c CE%sT 1944 O
+1 O CE%sT 1977
+1 W- CE%sT 1988
+1 E CE%sT
+Z Europe/Zurich 0:34:8 - LMT 1853 Jul 16
+0:29:46 - BMT 1894 Jun
+1 CH CE%sT 1981
+1 E CE%sT
+Z Factory 0 - -00
+Z Indian/Chagos 4:49:40 - LMT 1907
+5 - %z 1996
+6 - %z
+Z Indian/Maldives 4:54 - LMT 1880
+4:54 - MMT 1960
+5 - %z
+Z Indian/Mauritius 3:50 - LMT 1907
+4 MU %z
+Z Pacific/Apia 12:33:4 - LMT 1892 Jul 5
+-11:26:56 - LMT 1911
+-11:30 - %z 1950
+-11 WS %z 2011 D 29 24
+13 WS %z
+Z Pacific/Auckland 11:39:4 - LMT 1868 N 2
+11:30 NZ NZ%sT 1946
+12 NZ NZ%sT
+Z Pacific/Bougainville 10:22:16 - LMT 1880
+9:48:32 - PMMT 1895
+10 - %z 1942 Jul
+9 - %z 1945 Au 21
+10 - %z 2014 D 28 2
+11 - %z
+Z Pacific/Chatham 12:13:48 - LMT 1868 N 2
+12:15 - %z 1946
+12:45 k %z
+Z Pacific/Easter -7:17:28 - LMT 1890
+-7:17:28 - EMT 1932 S
+-7 x %z 1982 Mar 14 3u
+-6 x %z
+Z Pacific/Efate 11:13:16 - LMT 1912 Ja 13
+11 VU %z
+Z Pacific/Fakaofo -11:24:56 - LMT 1901
+-11 - %z 2011 D 30
+13 - %z
+Z Pacific/Fiji 11:55:44 - LMT 1915 O 26
+12 FJ %z
+Z Pacific/Galapagos -5:58:24 - LMT 1931
+-5 - %z 1986
+-6 EC %z
+Z Pacific/Gambier -8:59:48 - LMT 1912 O
+-9 - %z
+Z Pacific/Guadalcanal 10:39:48 - LMT 1912 O
+11 - %z
+Z Pacific/Guam -14:21 - LMT 1844 D 31
+9:39 - LMT 1901
+10 - GST 1941 D 10
+9 - %z 1944 Jul 31
+10 Gu G%sT 2000 D 23
+10 - ChST
+Z Pacific/Honolulu -10:31:26 - LMT 1896 Ja 13 12
+-10:30 - HST 1933 Ap 30 2
+-10:30 1 HDT 1933 May 21 12
+-10:30 u H%sT 1947 Jun 8 2
+-10 - HST
+Z Pacific/Kanton 0 - -00 1937 Au 31
+-12 - %z 1979 O
+-11 - %z 1994 D 31
+13 - %z
+Z Pacific/Kiritimati -10:29:20 - LMT 1901
+-10:40 - %z 1979 O
+-10 - %z 1994 D 31
+14 - %z
+Z Pacific/Kosrae -13:8:4 - LMT 1844 D 31
+10:51:56 - LMT 1901
+11 - %z 1914 O
+9 - %z 1919 F
+11 - %z 1937
+10 - %z 1941 Ap
+9 - %z 1945 Au
+11 - %z 1969 O
+12 - %z 1999
+11 - %z
+Z Pacific/Kwajalein 11:9:20 - LMT 1901
+11 - %z 1937
+10 - %z 1941 Ap
+9 - %z 1944 F 6
+11 - %z 1969 O
+-12 - %z 1993 Au 20 24
+12 - %z
+Z Pacific/Marquesas -9:18 - LMT 1912 O
+-9:30 - %z
+Z Pacific/Nauru 11:7:40 - LMT 1921 Ja 15
+11:30 - %z 1942 Au 29
+9 - %z 1945 S 8
+11:30 - %z 1979 F 10 2
+12 - %z
+Z Pacific/Niue -11:19:40 - LMT 1952 O 16
+-11:20 - %z 1964 Jul
+-11 - %z
+Z Pacific/Norfolk 11:11:52 - LMT 1901
+11:12 - %z 1951
+11:30 - %z 1974 O 27 2s
+11:30 1 %z 1975 Mar 2 2s
+11:30 - %z 2015 O 4 2s
+11 - %z 2019 Jul
+11 AN %z
+Z Pacific/Noumea 11:5:48 - LMT 1912 Ja 13
+11 NC %z
+Z Pacific/Pago_Pago 12:37:12 - LMT 1892 Jul 5
+-11:22:48 - LMT 1911
+-11 - SST
+Z Pacific/Palau -15:2:4 - LMT 1844 D 31
+8:57:56 - LMT 1901
+9 - %z
+Z Pacific/Pitcairn -8:40:20 - LMT 1901
+-8:30 - %z 1998 Ap 27
+-8 - %z
+Z Pacific/Port_Moresby 9:48:40 - LMT 1880
+9:48:32 - PMMT 1895
+10 - %z
+Z Pacific/Rarotonga 13:20:56 - LMT 1899 D 26
+-10:39:4 - LMT 1952 O 16
+-10:30 - %z 1978 N 12
+-10 CK %z
+Z Pacific/Tahiti -9:58:16 - LMT 1912 O
+-10 - %z
+Z Pacific/Tarawa 11:32:4 - LMT 1901
+12 - %z
+Z Pacific/Tongatapu 12:19:12 - LMT 1945 S 10
+12:20 - %z 1961
+13 - %z 1999
+13 TO %z
+L Etc/GMT GMT
+L Australia/Sydney Australia/ACT
+L Australia/Lord_Howe Australia/LHI
+L Australia/Sydney Australia/NSW
+L Australia/Darwin Australia/North
+L Australia/Brisbane Australia/Queensland
+L Australia/Adelaide Australia/South
+L Australia/Hobart Australia/Tasmania
+L Australia/Melbourne Australia/Victoria
+L Australia/Perth Australia/West
+L Australia/Broken_Hill Australia/Yancowinna
+L America/Rio_Branco Brazil/Acre
+L America/Noronha Brazil/DeNoronha
+L America/Sao_Paulo Brazil/East
+L America/Manaus Brazil/West
+L Europe/Brussels CET
+L America/Chicago CST6CDT
+L America/Halifax Canada/Atlantic
+L America/Winnipeg Canada/Central
+L America/Toronto Canada/Eastern
+L America/Edmonton Canada/Mountain
+L America/St_Johns Canada/Newfoundland
+L America/Vancouver Canada/Pacific
+L America/Regina Canada/Saskatchewan
+L America/Whitehorse Canada/Yukon
+L America/Santiago Chile/Continental
+L Pacific/Easter Chile/EasterIsland
+L America/Havana Cuba
+L Europe/Athens EET
+L America/Panama EST
+L America/New_York EST5EDT
+L Africa/Cairo Egypt
+L Europe/Dublin Eire
+L Etc/GMT Etc/GMT+0
+L Etc/GMT Etc/GMT-0
+L Etc/GMT Etc/GMT0
+L Etc/GMT Etc/Greenwich
+L Etc/UTC Etc/UCT
+L Etc/UTC Etc/Universal
+L Etc/UTC Etc/Zulu
+L Europe/London GB
+L Europe/London GB-Eire
+L Etc/GMT GMT+0
+L Etc/GMT GMT-0
+L Etc/GMT GMT0
+L Etc/GMT Greenwich
+L Asia/Hong_Kong Hongkong
+L Africa/Abidjan Iceland
+L Asia/Tehran Iran
+L Asia/Jerusalem Israel
+L America/Jamaica Jamaica
+L Asia/Tokyo Japan
+L Pacific/Kwajalein Kwajalein
+L Africa/Tripoli Libya
+L Europe/Brussels MET
+L America/Phoenix MST
+L America/Denver MST7MDT
+L America/Tijuana Mexico/BajaNorte
+L America/Mazatlan Mexico/BajaSur
+L America/Mexico_City Mexico/General
+L Pacific/Auckland NZ
+L Pacific/Chatham NZ-CHAT
+L America/Denver Navajo
+L Asia/Shanghai PRC
+L Europe/Warsaw Poland
+L Europe/Lisbon Portugal
+L Asia/Taipei ROC
+L Asia/Seoul ROK
+L Asia/Singapore Singapore
+L Europe/Istanbul Turkey
+L Etc/UTC UCT
+L America/Anchorage US/Alaska
+L America/Adak US/Aleutian
+L America/Phoenix US/Arizona
+L America/Chicago US/Central
+L America/Indiana/Indianapolis US/East-Indiana
+L America/New_York US/Eastern
+L Pacific/Honolulu US/Hawaii
+L America/Indiana/Knox US/Indiana-Starke
+L America/Detroit US/Michigan
+L America/Denver US/Mountain
+L America/Los_Angeles US/Pacific
+L Pacific/Pago_Pago US/Samoa
+L Etc/UTC UTC
+L Etc/UTC Universal
+L Europe/Moscow W-SU
+L Etc/UTC Zulu
+L America/Argentina/Buenos_Aires America/Buenos_Aires
+L America/Argentina/Catamarca America/Catamarca
+L America/Argentina/Cordoba America/Cordoba
+L America/Indiana/Indianapolis America/Indianapolis
+L America/Argentina/Jujuy America/Jujuy
+L America/Indiana/Knox America/Knox_IN
+L America/Kentucky/Louisville America/Louisville
+L America/Argentina/Mendoza America/Mendoza
+L America/Puerto_Rico America/Virgin
+L Pacific/Pago_Pago Pacific/Samoa
+L Africa/Abidjan Africa/Accra
+L Africa/Nairobi Africa/Addis_Ababa
+L Africa/Nairobi Africa/Asmara
+L Africa/Abidjan Africa/Bamako
+L Africa/Lagos Africa/Bangui
+L Africa/Abidjan Africa/Banjul
+L Africa/Maputo Africa/Blantyre
+L Africa/Lagos Africa/Brazzaville
+L Africa/Maputo Africa/Bujumbura
+L Africa/Abidjan Africa/Conakry
+L Africa/Abidjan Africa/Dakar
+L Africa/Nairobi Africa/Dar_es_Salaam
+L Africa/Nairobi Africa/Djibouti
+L Africa/Lagos Africa/Douala
+L Africa/Abidjan Africa/Freetown
+L Africa/Maputo Africa/Gaborone
+L Africa/Maputo Africa/Harare
+L Africa/Nairobi Africa/Kampala
+L Africa/Maputo Africa/Kigali
+L Africa/Lagos Africa/Kinshasa
+L Africa/Lagos Africa/Libreville
+L Africa/Abidjan Africa/Lome
+L Africa/Lagos Africa/Luanda
+L Africa/Maputo Africa/Lubumbashi
+L Africa/Maputo Africa/Lusaka
+L Africa/Lagos Africa/Malabo
+L Africa/Johannesburg Africa/Maseru
+L Africa/Johannesburg Africa/Mbabane
+L Africa/Nairobi Africa/Mogadishu
+L Africa/Lagos Africa/Niamey
+L Africa/Abidjan Africa/Nouakchott
+L Africa/Abidjan Africa/Ouagadougou
+L Africa/Lagos Africa/Porto-Novo
+L America/Puerto_Rico America/Anguilla
+L America/Puerto_Rico America/Antigua
+L America/Puerto_Rico America/Aruba
+L America/Panama America/Atikokan
+L America/Puerto_Rico America/Blanc-Sablon
+L America/Panama America/Cayman
+L America/Phoenix America/Creston
+L America/Puerto_Rico America/Curacao
+L America/Puerto_Rico America/Dominica
+L America/Puerto_Rico America/Grenada
+L America/Puerto_Rico America/Guadeloupe
+L America/Puerto_Rico America/Kralendijk
+L America/Puerto_Rico America/Lower_Princes
+L America/Puerto_Rico America/Marigot
+L America/Puerto_Rico America/Montserrat
+L America/Toronto America/Nassau
+L America/Puerto_Rico America/Port_of_Spain
+L America/Puerto_Rico America/St_Barthelemy
+L America/Puerto_Rico America/St_Kitts
+L America/Puerto_Rico America/St_Lucia
+L America/Puerto_Rico America/St_Thomas
+L America/Puerto_Rico America/St_Vincent
+L America/Puerto_Rico America/Tortola
+L Pacific/Port_Moresby Antarctica/DumontDUrville
+L Pacific/Auckland Antarctica/McMurdo
+L Asia/Riyadh Antarctica/Syowa
+L Europe/Berlin Arctic/Longyearbyen
+L Asia/Riyadh Asia/Aden
+L Asia/Qatar Asia/Bahrain
+L Asia/Kuching Asia/Brunei
+L Asia/Singapore Asia/Kuala_Lumpur
+L Asia/Riyadh Asia/Kuwait
+L Asia/Dubai Asia/Muscat
+L Asia/Bangkok Asia/Phnom_Penh
+L Asia/Bangkok Asia/Vientiane
+L Africa/Abidjan Atlantic/Reykjavik
+L Africa/Abidjan Atlantic/St_Helena
+L Europe/Brussels Europe/Amsterdam
+L Europe/Prague Europe/Bratislava
+L Europe/Zurich Europe/Busingen
+L Europe/Berlin Europe/Copenhagen
+L Europe/London Europe/Guernsey
+L Europe/London Europe/Isle_of_Man
+L Europe/London Europe/Jersey
+L Europe/Belgrade Europe/Ljubljana
+L Europe/Brussels Europe/Luxembourg
+L Europe/Helsinki Europe/Mariehamn
+L Europe/Paris Europe/Monaco
+L Europe/Berlin Europe/Oslo
+L Europe/Belgrade Europe/Podgorica
+L Europe/Rome Europe/San_Marino
+L Europe/Belgrade Europe/Sarajevo
+L Europe/Belgrade Europe/Skopje
+L Europe/Berlin Europe/Stockholm
+L Europe/Zurich Europe/Vaduz
+L Europe/Rome Europe/Vatican
+L Europe/Belgrade Europe/Zagreb
+L Africa/Nairobi Indian/Antananarivo
+L Asia/Bangkok Indian/Christmas
+L Asia/Yangon Indian/Cocos
+L Africa/Nairobi Indian/Comoro
+L Indian/Maldives Indian/Kerguelen
+L Asia/Dubai Indian/Mahe
+L Africa/Nairobi Indian/Mayotte
+L Asia/Dubai Indian/Reunion
+L Pacific/Port_Moresby Pacific/Chuuk
+L Pacific/Tarawa Pacific/Funafuti
+L Pacific/Tarawa Pacific/Majuro
+L Pacific/Pago_Pago Pacific/Midway
+L Pacific/Guadalcanal Pacific/Pohnpei
+L Pacific/Guam Pacific/Saipan
+L Pacific/Tarawa Pacific/Wake
+L Pacific/Tarawa Pacific/Wallis
+L Africa/Abidjan Africa/Timbuktu
+L America/Argentina/Catamarca America/Argentina/ComodRivadavia
+L America/Adak America/Atka
+L America/Panama America/Coral_Harbour
+L America/Tijuana America/Ensenada
+L America/Indiana/Indianapolis America/Fort_Wayne
+L America/Toronto America/Montreal
+L America/Toronto America/Nipigon
+L America/Iqaluit America/Pangnirtung
+L America/Rio_Branco America/Porto_Acre
+L America/Winnipeg America/Rainy_River
+L America/Argentina/Cordoba America/Rosario
+L America/Tijuana America/Santa_Isabel
+L America/Denver America/Shiprock
+L America/Toronto America/Thunder_Bay
+L America/Edmonton America/Yellowknife
+L Pacific/Auckland Antarctica/South_Pole
+L Asia/Ulaanbaatar Asia/Choibalsan
+L Asia/Shanghai Asia/Chongqing
+L Asia/Shanghai Asia/Harbin
+L Asia/Urumqi Asia/Kashgar
+L Asia/Jerusalem Asia/Tel_Aviv
+L Europe/Berlin Atlantic/Jan_Mayen
+L Australia/Sydney Australia/Canberra
+L Australia/Hobart Australia/Currie
+L Europe/London Europe/Belfast
+L Europe/Chisinau Europe/Tiraspol
+L Europe/Kyiv Europe/Uzhgorod
+L Europe/Kyiv Europe/Zaporozhye
+L Pacific/Kanton Pacific/Enderbury
+L Pacific/Honolulu Pacific/Johnston
+L Pacific/Port_Moresby Pacific/Yap
+L Europe/Lisbon WET
+L Africa/Nairobi Africa/Asmera
+L America/Nuuk America/Godthab
+L Asia/Ashgabat Asia/Ashkhabad
+L Asia/Kolkata Asia/Calcutta
+L Asia/Shanghai Asia/Chungking
+L Asia/Dhaka Asia/Dacca
+L Europe/Istanbul Asia/Istanbul
+L Asia/Kathmandu Asia/Katmandu
+L Asia/Macau Asia/Macao
+L Asia/Yangon Asia/Rangoon
+L Asia/Ho_Chi_Minh Asia/Saigon
+L Asia/Thimphu Asia/Thimbu
+L Asia/Makassar Asia/Ujung_Pandang
+L Asia/Ulaanbaatar Asia/Ulan_Bator
+L Atlantic/Faroe Atlantic/Faeroe
+L Europe/Kyiv Europe/Kiev
+L Asia/Nicosia Europe/Nicosia
+L Pacific/Honolulu HST
+L America/Los_Angeles PST8PDT
+L Pacific/Guadalcanal Pacific/Ponape
+L Pacific/Port_Moresby Pacific/Truk
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/zone.tab b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/zone.tab
new file mode 100644
index 0000000..2626b05
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/zone.tab
@@ -0,0 +1,448 @@
+# tzdb timezone descriptions (deprecated version)
+#
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
+#
+# From Paul Eggert (2021-09-20):
+# This file is intended as a backward-compatibility aid for older programs.
+# New programs should use zone1970.tab. This file is like zone1970.tab (see
+# zone1970.tab's comments), but with the following additional restrictions:
+#
+# 1. This file contains only ASCII characters.
+# 2. The first data column contains exactly one country code.
+#
+# Because of (2), each row stands for an area that is the intersection
+# of a region identified by a country code and of a timezone where civil
+# clocks have agreed since 1970; this is a narrower definition than
+# that of zone1970.tab.
+#
+# Unlike zone1970.tab, a row's third column can be a Link from
+# 'backward' instead of a Zone.
+#
+# This table is intended as an aid for users, to help them select timezones
+# appropriate for their practical needs. It is not intended to take or
+# endorse any position on legal or territorial claims.
+#
+#country-
+#code coordinates TZ comments
+AD +4230+00131 Europe/Andorra
+AE +2518+05518 Asia/Dubai
+AF +3431+06912 Asia/Kabul
+AG +1703-06148 America/Antigua
+AI +1812-06304 America/Anguilla
+AL +4120+01950 Europe/Tirane
+AM +4011+04430 Asia/Yerevan
+AO -0848+01314 Africa/Luanda
+AQ -7750+16636 Antarctica/McMurdo New Zealand time - McMurdo, South Pole
+AQ -6617+11031 Antarctica/Casey Casey
+AQ -6835+07758 Antarctica/Davis Davis
+AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville
+AQ -6736+06253 Antarctica/Mawson Mawson
+AQ -6448-06406 Antarctica/Palmer Palmer
+AQ -6734-06808 Antarctica/Rothera Rothera
+AQ -690022+0393524 Antarctica/Syowa Syowa
+AQ -720041+0023206 Antarctica/Troll Troll
+AQ -7824+10654 Antarctica/Vostok Vostok
+AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF)
+AR -3124-06411 America/Argentina/Cordoba Argentina (most areas: CB, CC, CN, ER, FM, MN, SE, SF)
+AR -2447-06525 America/Argentina/Salta Salta (SA, LP, NQ, RN)
+AR -2411-06518 America/Argentina/Jujuy Jujuy (JY)
+AR -2649-06513 America/Argentina/Tucuman Tucuman (TM)
+AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH)
+AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR)
+AR -3132-06831 America/Argentina/San_Juan San Juan (SJ)
+AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ)
+AR -3319-06621 America/Argentina/San_Luis San Luis (SL)
+AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC)
+AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF)
+AS -1416-17042 Pacific/Pago_Pago
+AT +4813+01620 Europe/Vienna
+AU -3133+15905 Australia/Lord_Howe Lord Howe Island
+AU -5430+15857 Antarctica/Macquarie Macquarie Island
+AU -4253+14719 Australia/Hobart Tasmania
+AU -3749+14458 Australia/Melbourne Victoria
+AU -3352+15113 Australia/Sydney New South Wales (most areas)
+AU -3157+14127 Australia/Broken_Hill New South Wales (Yancowinna)
+AU -2728+15302 Australia/Brisbane Queensland (most areas)
+AU -2016+14900 Australia/Lindeman Queensland (Whitsunday Islands)
+AU -3455+13835 Australia/Adelaide South Australia
+AU -1228+13050 Australia/Darwin Northern Territory
+AU -3157+11551 Australia/Perth Western Australia (most areas)
+AU -3143+12852 Australia/Eucla Western Australia (Eucla)
+AW +1230-06958 America/Aruba
+AX +6006+01957 Europe/Mariehamn
+AZ +4023+04951 Asia/Baku
+BA +4352+01825 Europe/Sarajevo
+BB +1306-05937 America/Barbados
+BD +2343+09025 Asia/Dhaka
+BE +5050+00420 Europe/Brussels
+BF +1222-00131 Africa/Ouagadougou
+BG +4241+02319 Europe/Sofia
+BH +2623+05035 Asia/Bahrain
+BI -0323+02922 Africa/Bujumbura
+BJ +0629+00237 Africa/Porto-Novo
+BL +1753-06251 America/St_Barthelemy
+BM +3217-06446 Atlantic/Bermuda
+BN +0456+11455 Asia/Brunei
+BO -1630-06809 America/La_Paz
+BQ +120903-0681636 America/Kralendijk
+BR -0351-03225 America/Noronha Atlantic islands
+BR -0127-04829 America/Belem Para (east), Amapa
+BR -0343-03830 America/Fortaleza Brazil (northeast: MA, PI, CE, RN, PB)
+BR -0803-03454 America/Recife Pernambuco
+BR -0712-04812 America/Araguaina Tocantins
+BR -0940-03543 America/Maceio Alagoas, Sergipe
+BR -1259-03831 America/Bahia Bahia
+BR -2332-04637 America/Sao_Paulo Brazil (southeast: GO, DF, MG, ES, RJ, SP, PR, SC, RS)
+BR -2027-05437 America/Campo_Grande Mato Grosso do Sul
+BR -1535-05605 America/Cuiaba Mato Grosso
+BR -0226-05452 America/Santarem Para (west)
+BR -0846-06354 America/Porto_Velho Rondonia
+BR +0249-06040 America/Boa_Vista Roraima
+BR -0308-06001 America/Manaus Amazonas (east)
+BR -0640-06952 America/Eirunepe Amazonas (west)
+BR -0958-06748 America/Rio_Branco Acre
+BS +2505-07721 America/Nassau
+BT +2728+08939 Asia/Thimphu
+BW -2439+02555 Africa/Gaborone
+BY +5354+02734 Europe/Minsk
+BZ +1730-08812 America/Belize
+CA +4734-05243 America/St_Johns Newfoundland, Labrador (SE)
+CA +4439-06336 America/Halifax Atlantic - NS (most areas), PE
+CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton)
+CA +4606-06447 America/Moncton Atlantic - New Brunswick
+CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas)
+CA +5125-05707 America/Blanc-Sablon AST - QC (Lower North Shore)
+CA +4339-07923 America/Toronto Eastern - ON & QC (most areas)
+CA +6344-06828 America/Iqaluit Eastern - NU (most areas)
+CA +484531-0913718 America/Atikokan EST - ON (Atikokan), NU (Coral H)
+CA +4953-09709 America/Winnipeg Central - ON (west), Manitoba
+CA +744144-0944945 America/Resolute Central - NU (Resolute)
+CA +624900-0920459 America/Rankin_Inlet Central - NU (central)
+CA +5024-10439 America/Regina CST - SK (most areas)
+CA +5017-10750 America/Swift_Current CST - SK (midwest)
+CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W)
+CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west)
+CA +682059-1334300 America/Inuvik Mountain - NT (west)
+CA +4906-11631 America/Creston MST - BC (Creston)
+CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John)
+CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson)
+CA +6043-13503 America/Whitehorse MST - Yukon (east)
+CA +6404-13925 America/Dawson MST - Yukon (west)
+CA +4916-12307 America/Vancouver Pacific - BC (most areas)
+CC -1210+09655 Indian/Cocos
+CD -0418+01518 Africa/Kinshasa Dem. Rep. of Congo (west)
+CD -1140+02728 Africa/Lubumbashi Dem. Rep. of Congo (east)
+CF +0422+01835 Africa/Bangui
+CG -0416+01517 Africa/Brazzaville
+CH +4723+00832 Europe/Zurich
+CI +0519-00402 Africa/Abidjan
+CK -2114-15946 Pacific/Rarotonga
+CL -3327-07040 America/Santiago most of Chile
+CL -4534-07204 America/Coyhaique Aysen Region
+CL -5309-07055 America/Punta_Arenas Magallanes Region
+CL -2709-10926 Pacific/Easter Easter Island
+CM +0403+00942 Africa/Douala
+CN +3114+12128 Asia/Shanghai Beijing Time
+CN +4348+08735 Asia/Urumqi Xinjiang Time
+CO +0436-07405 America/Bogota
+CR +0956-08405 America/Costa_Rica
+CU +2308-08222 America/Havana
+CV +1455-02331 Atlantic/Cape_Verde
+CW +1211-06900 America/Curacao
+CX -1025+10543 Indian/Christmas
+CY +3510+03322 Asia/Nicosia most of Cyprus
+CY +3507+03357 Asia/Famagusta Northern Cyprus
+CZ +5005+01426 Europe/Prague
+DE +5230+01322 Europe/Berlin most of Germany
+DE +4742+00841 Europe/Busingen Busingen
+DJ +1136+04309 Africa/Djibouti
+DK +5540+01235 Europe/Copenhagen
+DM +1518-06124 America/Dominica
+DO +1828-06954 America/Santo_Domingo
+DZ +3647+00303 Africa/Algiers
+EC -0210-07950 America/Guayaquil Ecuador (mainland)
+EC -0054-08936 Pacific/Galapagos Galapagos Islands
+EE +5925+02445 Europe/Tallinn
+EG +3003+03115 Africa/Cairo
+EH +2709-01312 Africa/El_Aaiun
+ER +1520+03853 Africa/Asmara
+ES +4024-00341 Europe/Madrid Spain (mainland)
+ES +3553-00519 Africa/Ceuta Ceuta, Melilla
+ES +2806-01524 Atlantic/Canary Canary Islands
+ET +0902+03842 Africa/Addis_Ababa
+FI +6010+02458 Europe/Helsinki
+FJ -1808+17825 Pacific/Fiji
+FK -5142-05751 Atlantic/Stanley
+FM +0725+15147 Pacific/Chuuk Chuuk/Truk, Yap
+FM +0658+15813 Pacific/Pohnpei Pohnpei/Ponape
+FM +0519+16259 Pacific/Kosrae Kosrae
+FO +6201-00646 Atlantic/Faroe
+FR +4852+00220 Europe/Paris
+GA +0023+00927 Africa/Libreville
+GB +513030-0000731 Europe/London
+GD +1203-06145 America/Grenada
+GE +4143+04449 Asia/Tbilisi
+GF +0456-05220 America/Cayenne
+GG +492717-0023210 Europe/Guernsey
+GH +0533-00013 Africa/Accra
+GI +3608-00521 Europe/Gibraltar
+GL +6411-05144 America/Nuuk most of Greenland
+GL +7646-01840 America/Danmarkshavn National Park (east coast)
+GL +7029-02158 America/Scoresbysund Scoresbysund/Ittoqqortoormiit
+GL +7634-06847 America/Thule Thule/Pituffik
+GM +1328-01639 Africa/Banjul
+GN +0931-01343 Africa/Conakry
+GP +1614-06132 America/Guadeloupe
+GQ +0345+00847 Africa/Malabo
+GR +3758+02343 Europe/Athens
+GS -5416-03632 Atlantic/South_Georgia
+GT +1438-09031 America/Guatemala
+GU +1328+14445 Pacific/Guam
+GW +1151-01535 Africa/Bissau
+GY +0648-05810 America/Guyana
+HK +2217+11409 Asia/Hong_Kong
+HN +1406-08713 America/Tegucigalpa
+HR +4548+01558 Europe/Zagreb
+HT +1832-07220 America/Port-au-Prince
+HU +4730+01905 Europe/Budapest
+ID -0610+10648 Asia/Jakarta Java, Sumatra
+ID -0002+10920 Asia/Pontianak Borneo (west, central)
+ID -0507+11924 Asia/Makassar Borneo (east, south), Sulawesi/Celebes, Bali, Nusa Tengarra, Timor (west)
+ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya), Malukus/Moluccas
+IE +5320-00615 Europe/Dublin
+IL +314650+0351326 Asia/Jerusalem
+IM +5409-00428 Europe/Isle_of_Man
+IN +2232+08822 Asia/Kolkata
+IO -0720+07225 Indian/Chagos
+IQ +3321+04425 Asia/Baghdad
+IR +3540+05126 Asia/Tehran
+IS +6409-02151 Atlantic/Reykjavik
+IT +4154+01229 Europe/Rome
+JE +491101-0020624 Europe/Jersey
+JM +175805-0764736 America/Jamaica
+JO +3157+03556 Asia/Amman
+JP +353916+1394441 Asia/Tokyo
+KE -0117+03649 Africa/Nairobi
+KG +4254+07436 Asia/Bishkek
+KH +1133+10455 Asia/Phnom_Penh
+KI +0125+17300 Pacific/Tarawa Gilbert Islands
+KI -0247-17143 Pacific/Kanton Phoenix Islands
+KI +0152-15720 Pacific/Kiritimati Line Islands
+KM -1141+04316 Indian/Comoro
+KN +1718-06243 America/St_Kitts
+KP +3901+12545 Asia/Pyongyang
+KR +3733+12658 Asia/Seoul
+KW +2920+04759 Asia/Kuwait
+KY +1918-08123 America/Cayman
+KZ +4315+07657 Asia/Almaty most of Kazakhstan
+KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda
+KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay
+KZ +5017+05710 Asia/Aqtobe Aqtobe/Aktobe
+KZ +4431+05016 Asia/Aqtau Mangghystau/Mankistau
+KZ +4707+05156 Asia/Atyrau Atyrau/Atirau/Gur'yev
+KZ +5113+05121 Asia/Oral West Kazakhstan
+LA +1758+10236 Asia/Vientiane
+LB +3353+03530 Asia/Beirut
+LC +1401-06100 America/St_Lucia
+LI +4709+00931 Europe/Vaduz
+LK +0656+07951 Asia/Colombo
+LR +0618-01047 Africa/Monrovia
+LS -2928+02730 Africa/Maseru
+LT +5441+02519 Europe/Vilnius
+LU +4936+00609 Europe/Luxembourg
+LV +5657+02406 Europe/Riga
+LY +3254+01311 Africa/Tripoli
+MA +3339-00735 Africa/Casablanca
+MC +4342+00723 Europe/Monaco
+MD +4700+02850 Europe/Chisinau
+ME +4226+01916 Europe/Podgorica
+MF +1804-06305 America/Marigot
+MG -1855+04731 Indian/Antananarivo
+MH +0709+17112 Pacific/Majuro most of Marshall Islands
+MH +0905+16720 Pacific/Kwajalein Kwajalein
+MK +4159+02126 Europe/Skopje
+ML +1239-00800 Africa/Bamako
+MM +1647+09610 Asia/Yangon
+MN +4755+10653 Asia/Ulaanbaatar most of Mongolia
+MN +4801+09139 Asia/Hovd Bayan-Olgii, Hovd, Uvs
+MO +221150+1133230 Asia/Macau
+MP +1512+14545 Pacific/Saipan
+MQ +1436-06105 America/Martinique
+MR +1806-01557 Africa/Nouakchott
+MS +1643-06213 America/Montserrat
+MT +3554+01431 Europe/Malta
+MU -2010+05730 Indian/Mauritius
+MV +0410+07330 Indian/Maldives
+MW -1547+03500 Africa/Blantyre
+MX +1924-09909 America/Mexico_City Central Mexico
+MX +2105-08646 America/Cancun Quintana Roo
+MX +2058-08937 America/Merida Campeche, Yucatan
+MX +2540-10019 America/Monterrey Durango; Coahuila, Nuevo Leon, Tamaulipas (most areas)
+MX +2550-09730 America/Matamoros Coahuila, Nuevo Leon, Tamaulipas (US border)
+MX +2838-10605 America/Chihuahua Chihuahua (most areas)
+MX +3144-10629 America/Ciudad_Juarez Chihuahua (US border - west)
+MX +2934-10425 America/Ojinaga Chihuahua (US border - east)
+MX +2313-10625 America/Mazatlan Baja California Sur, Nayarit (most areas), Sinaloa
+MX +2048-10515 America/Bahia_Banderas Bahia de Banderas
+MX +2904-11058 America/Hermosillo Sonora
+MX +3232-11701 America/Tijuana Baja California
+MY +0310+10142 Asia/Kuala_Lumpur Malaysia (peninsula)
+MY +0133+11020 Asia/Kuching Sabah, Sarawak
+MZ -2558+03235 Africa/Maputo
+NA -2234+01706 Africa/Windhoek
+NC -2216+16627 Pacific/Noumea
+NE +1331+00207 Africa/Niamey
+NF -2903+16758 Pacific/Norfolk
+NG +0627+00324 Africa/Lagos
+NI +1209-08617 America/Managua
+NL +5222+00454 Europe/Amsterdam
+NO +5955+01045 Europe/Oslo
+NP +2743+08519 Asia/Kathmandu
+NR -0031+16655 Pacific/Nauru
+NU -1901-16955 Pacific/Niue
+NZ -3652+17446 Pacific/Auckland most of New Zealand
+NZ -4357-17633 Pacific/Chatham Chatham Islands
+OM +2336+05835 Asia/Muscat
+PA +0858-07932 America/Panama
+PE -1203-07703 America/Lima
+PF -1732-14934 Pacific/Tahiti Society Islands
+PF -0900-13930 Pacific/Marquesas Marquesas Islands
+PF -2308-13457 Pacific/Gambier Gambier Islands
+PG -0930+14710 Pacific/Port_Moresby most of Papua New Guinea
+PG -0613+15534 Pacific/Bougainville Bougainville
+PH +143512+1205804 Asia/Manila
+PK +2452+06703 Asia/Karachi
+PL +5215+02100 Europe/Warsaw
+PM +4703-05620 America/Miquelon
+PN -2504-13005 Pacific/Pitcairn
+PR +182806-0660622 America/Puerto_Rico
+PS +3130+03428 Asia/Gaza Gaza Strip
+PS +313200+0350542 Asia/Hebron West Bank
+PT +3843-00908 Europe/Lisbon Portugal (mainland)
+PT +3238-01654 Atlantic/Madeira Madeira Islands
+PT +3744-02540 Atlantic/Azores Azores
+PW +0720+13429 Pacific/Palau
+PY -2516-05740 America/Asuncion
+QA +2517+05132 Asia/Qatar
+RE -2052+05528 Indian/Reunion
+RO +4426+02606 Europe/Bucharest
+RS +4450+02030 Europe/Belgrade
+RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad
+RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area
+# The obsolescent zone.tab format cannot represent Europe/Simferopol well.
+# Put it in RU section and list as UA. See "territorial claims" above.
+# Programs should use zone1970.tab instead; see above.
+UA +4457+03406 Europe/Simferopol Crimea
+RU +5836+04939 Europe/Kirov MSK+00 - Kirov
+RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd
+RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan
+RU +5134+04602 Europe/Saratov MSK+01 - Saratov
+RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk
+RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
+RU +5651+06036 Asia/Yekaterinburg MSK+02 - Urals
+RU +5500+07324 Asia/Omsk MSK+03 - Omsk
+RU +5502+08255 Asia/Novosibirsk MSK+04 - Novosibirsk
+RU +5322+08345 Asia/Barnaul MSK+04 - Altai
+RU +5630+08458 Asia/Tomsk MSK+04 - Tomsk
+RU +5345+08707 Asia/Novokuznetsk MSK+04 - Kemerovo
+RU +5601+09250 Asia/Krasnoyarsk MSK+04 - Krasnoyarsk area
+RU +5216+10420 Asia/Irkutsk MSK+05 - Irkutsk, Buryatia
+RU +5203+11328 Asia/Chita MSK+06 - Zabaykalsky
+RU +6200+12940 Asia/Yakutsk MSK+06 - Lena River
+RU +623923+1353314 Asia/Khandyga MSK+06 - Tomponsky, Ust-Maysky
+RU +4310+13156 Asia/Vladivostok MSK+07 - Amur River
+RU +643337+1431336 Asia/Ust-Nera MSK+07 - Oymyakonsky
+RU +5934+15048 Asia/Magadan MSK+08 - Magadan
+RU +4658+14242 Asia/Sakhalin MSK+08 - Sakhalin Island
+RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E), N Kuril Is
+RU +5301+15839 Asia/Kamchatka MSK+09 - Kamchatka
+RU +6445+17729 Asia/Anadyr MSK+09 - Bering Sea
+RW -0157+03004 Africa/Kigali
+SA +2438+04643 Asia/Riyadh
+SB -0932+16012 Pacific/Guadalcanal
+SC -0440+05528 Indian/Mahe
+SD +1536+03232 Africa/Khartoum
+SE +5920+01803 Europe/Stockholm
+SG +0117+10351 Asia/Singapore
+SH -1555-00542 Atlantic/St_Helena
+SI +4603+01431 Europe/Ljubljana
+SJ +7800+01600 Arctic/Longyearbyen
+SK +4809+01707 Europe/Bratislava
+SL +0830-01315 Africa/Freetown
+SM +4355+01228 Europe/San_Marino
+SN +1440-01726 Africa/Dakar
+SO +0204+04522 Africa/Mogadishu
+SR +0550-05510 America/Paramaribo
+SS +0451+03137 Africa/Juba
+ST +0020+00644 Africa/Sao_Tome
+SV +1342-08912 America/El_Salvador
+SX +180305-0630250 America/Lower_Princes
+SY +3330+03618 Asia/Damascus
+SZ -2618+03106 Africa/Mbabane
+TC +2128-07108 America/Grand_Turk
+TD +1207+01503 Africa/Ndjamena
+TF -492110+0701303 Indian/Kerguelen
+TG +0608+00113 Africa/Lome
+TH +1345+10031 Asia/Bangkok
+TJ +3835+06848 Asia/Dushanbe
+TK -0922-17114 Pacific/Fakaofo
+TL -0833+12535 Asia/Dili
+TM +3757+05823 Asia/Ashgabat
+TN +3648+01011 Africa/Tunis
+TO -210800-1751200 Pacific/Tongatapu
+TR +4101+02858 Europe/Istanbul
+TT +1039-06131 America/Port_of_Spain
+TV -0831+17913 Pacific/Funafuti
+TW +2503+12130 Asia/Taipei
+TZ -0648+03917 Africa/Dar_es_Salaam
+UA +5026+03031 Europe/Kyiv most of Ukraine
+UG +0019+03225 Africa/Kampala
+UM +2813-17722 Pacific/Midway Midway Islands
+UM +1917+16637 Pacific/Wake Wake Island
+US +404251-0740023 America/New_York Eastern (most areas)
+US +421953-0830245 America/Detroit Eastern - MI (most areas)
+US +381515-0854534 America/Kentucky/Louisville Eastern - KY (Louisville area)
+US +364947-0845057 America/Kentucky/Monticello Eastern - KY (Wayne)
+US +394606-0860929 America/Indiana/Indianapolis Eastern - IN (most areas)
+US +384038-0873143 America/Indiana/Vincennes Eastern - IN (Da, Du, K, Mn)
+US +410305-0863611 America/Indiana/Winamac Eastern - IN (Pulaski)
+US +382232-0862041 America/Indiana/Marengo Eastern - IN (Crawford)
+US +382931-0871643 America/Indiana/Petersburg Eastern - IN (Pike)
+US +384452-0850402 America/Indiana/Vevay Eastern - IN (Switzerland)
+US +415100-0873900 America/Chicago Central (most areas)
+US +375711-0864541 America/Indiana/Tell_City Central - IN (Perry)
+US +411745-0863730 America/Indiana/Knox Central - IN (Starke)
+US +450628-0873651 America/Menominee Central - MI (Wisconsin border)
+US +470659-1011757 America/North_Dakota/Center Central - ND (Oliver)
+US +465042-1012439 America/North_Dakota/New_Salem Central - ND (Morton rural)
+US +471551-1014640 America/North_Dakota/Beulah Central - ND (Mercer)
+US +394421-1045903 America/Denver Mountain (most areas)
+US +433649-1161209 America/Boise Mountain - ID (south), OR (east)
+US +332654-1120424 America/Phoenix MST - AZ (except Navajo)
+US +340308-1181434 America/Los_Angeles Pacific
+US +611305-1495401 America/Anchorage Alaska (most areas)
+US +581807-1342511 America/Juneau Alaska - Juneau area
+US +571035-1351807 America/Sitka Alaska - Sitka area
+US +550737-1313435 America/Metlakatla Alaska - Annette Island
+US +593249-1394338 America/Yakutat Alaska - Yakutat
+US +643004-1652423 America/Nome Alaska (west)
+US +515248-1763929 America/Adak Alaska - western Aleutians
+US +211825-1575130 Pacific/Honolulu Hawaii
+UY -345433-0561245 America/Montevideo
+UZ +3940+06648 Asia/Samarkand Uzbekistan (west)
+UZ +4120+06918 Asia/Tashkent Uzbekistan (east)
+VA +415408+0122711 Europe/Vatican
+VC +1309-06114 America/St_Vincent
+VE +1030-06656 America/Caracas
+VG +1827-06437 America/Tortola
+VI +1821-06456 America/St_Thomas
+VN +1045+10640 Asia/Ho_Chi_Minh
+VU -1740+16825 Pacific/Efate
+WF -1318-17610 Pacific/Wallis
+WS -1350-17144 Pacific/Apia
+YE +1245+04512 Asia/Aden
+YT -1247+04514 Indian/Mayotte
+ZA -2615+02800 Africa/Johannesburg
+ZM -1525+02817 Africa/Lusaka
+ZW -1750+03103 Africa/Harare
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/zone1970.tab b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/zone1970.tab
new file mode 100644
index 0000000..36535bd
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/zone1970.tab
@@ -0,0 +1,375 @@
+# tzdb timezone descriptions
+#
+# This file is in the public domain.
+#
+# From Paul Eggert (2018-06-27):
+# This file contains a table where each row stands for a timezone where
+# civil timestamps have agreed since 1970. Columns are separated by
+# a single tab. Lines beginning with '#' are comments. All text uses
+# UTF-8 encoding. The columns of the table are as follows:
+#
+# 1. The countries that overlap the timezone, as a comma-separated list
+# of ISO 3166 2-character country codes. See the file 'iso3166.tab'.
+# 2. Latitude and longitude of the timezone's principal location
+# in ISO 6709 sign-degrees-minutes-seconds format,
+# either ±DDMM±DDDMM or ±DDMMSS±DDDMMSS,
+# first latitude (+ is north), then longitude (+ is east).
+# 3. Timezone name used in value of TZ environment variable.
+# Please see the theory.html file for how these names are chosen.
+# If multiple timezones overlap a country, each has a row in the
+# table, with each column 1 containing the country code.
+# 4. Comments; present if and only if countries have multiple timezones,
+# and useful only for those countries. For example, the comments
+# for the row with countries CH,DE,LI and name Europe/Zurich
+# are useful only for DE, since CH and LI have no other timezones.
+#
+# If a timezone covers multiple countries, the most-populous city is used,
+# and that country is listed first in column 1; any other countries
+# are listed alphabetically by country code. The table is sorted
+# first by country code, then (if possible) by an order within the
+# country that (1) makes some geographical sense, and (2) puts the
+# most populous timezones first, where that does not contradict (1).
+#
+# This table is intended as an aid for users, to help them select timezones
+# appropriate for their practical needs. It is not intended to take or
+# endorse any position on legal or territorial claims.
+#
+#country-
+#codes coordinates TZ comments
+AD +4230+00131 Europe/Andorra
+AE,OM,RE,SC,TF +2518+05518 Asia/Dubai Crozet
+AF +3431+06912 Asia/Kabul
+AL +4120+01950 Europe/Tirane
+AM +4011+04430 Asia/Yerevan
+AQ -6617+11031 Antarctica/Casey Casey
+AQ -6835+07758 Antarctica/Davis Davis
+AQ -6736+06253 Antarctica/Mawson Mawson
+AQ -6448-06406 Antarctica/Palmer Palmer
+AQ -6734-06808 Antarctica/Rothera Rothera
+AQ -720041+0023206 Antarctica/Troll Troll
+AQ -7824+10654 Antarctica/Vostok Vostok
+AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF)
+AR -3124-06411 America/Argentina/Cordoba most areas: CB, CC, CN, ER, FM, MN, SE, SF
+AR -2447-06525 America/Argentina/Salta Salta (SA, LP, NQ, RN)
+AR -2411-06518 America/Argentina/Jujuy Jujuy (JY)
+AR -2649-06513 America/Argentina/Tucuman Tucumán (TM)
+AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH)
+AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR)
+AR -3132-06831 America/Argentina/San_Juan San Juan (SJ)
+AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ)
+AR -3319-06621 America/Argentina/San_Luis San Luis (SL)
+AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC)
+AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF)
+AS,UM -1416-17042 Pacific/Pago_Pago Midway
+AT +4813+01620 Europe/Vienna
+AU -3133+15905 Australia/Lord_Howe Lord Howe Island
+AU -5430+15857 Antarctica/Macquarie Macquarie Island
+AU -4253+14719 Australia/Hobart Tasmania
+AU -3749+14458 Australia/Melbourne Victoria
+AU -3352+15113 Australia/Sydney New South Wales (most areas)
+AU -3157+14127 Australia/Broken_Hill New South Wales (Yancowinna)
+AU -2728+15302 Australia/Brisbane Queensland (most areas)
+AU -2016+14900 Australia/Lindeman Queensland (Whitsunday Islands)
+AU -3455+13835 Australia/Adelaide South Australia
+AU -1228+13050 Australia/Darwin Northern Territory
+AU -3157+11551 Australia/Perth Western Australia (most areas)
+AU -3143+12852 Australia/Eucla Western Australia (Eucla)
+AZ +4023+04951 Asia/Baku
+BB +1306-05937 America/Barbados
+BD +2343+09025 Asia/Dhaka
+BE,LU,NL +5050+00420 Europe/Brussels
+BG +4241+02319 Europe/Sofia
+BM +3217-06446 Atlantic/Bermuda
+BO -1630-06809 America/La_Paz
+BR -0351-03225 America/Noronha Atlantic islands
+BR -0127-04829 America/Belem Pará (east), Amapá
+BR -0343-03830 America/Fortaleza Brazil (northeast: MA, PI, CE, RN, PB)
+BR -0803-03454 America/Recife Pernambuco
+BR -0712-04812 America/Araguaina Tocantins
+BR -0940-03543 America/Maceio Alagoas, Sergipe
+BR -1259-03831 America/Bahia Bahia
+BR -2332-04637 America/Sao_Paulo Brazil (southeast: GO, DF, MG, ES, RJ, SP, PR, SC, RS)
+BR -2027-05437 America/Campo_Grande Mato Grosso do Sul
+BR -1535-05605 America/Cuiaba Mato Grosso
+BR -0226-05452 America/Santarem Pará (west)
+BR -0846-06354 America/Porto_Velho Rondônia
+BR +0249-06040 America/Boa_Vista Roraima
+BR -0308-06001 America/Manaus Amazonas (east)
+BR -0640-06952 America/Eirunepe Amazonas (west)
+BR -0958-06748 America/Rio_Branco Acre
+BT +2728+08939 Asia/Thimphu
+BY +5354+02734 Europe/Minsk
+BZ +1730-08812 America/Belize
+CA +4734-05243 America/St_Johns Newfoundland, Labrador (SE)
+CA +4439-06336 America/Halifax Atlantic - NS (most areas), PE
+CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton)
+CA +4606-06447 America/Moncton Atlantic - New Brunswick
+CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas)
+CA,BS +4339-07923 America/Toronto Eastern - ON & QC (most areas)
+CA +6344-06828 America/Iqaluit Eastern - NU (most areas)
+CA +4953-09709 America/Winnipeg Central - ON (west), Manitoba
+CA +744144-0944945 America/Resolute Central - NU (Resolute)
+CA +624900-0920459 America/Rankin_Inlet Central - NU (central)
+CA +5024-10439 America/Regina CST - SK (most areas)
+CA +5017-10750 America/Swift_Current CST - SK (midwest)
+CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W)
+CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west)
+CA +682059-1334300 America/Inuvik Mountain - NT (west)
+CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John)
+CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson)
+CA +6043-13503 America/Whitehorse MST - Yukon (east)
+CA +6404-13925 America/Dawson MST - Yukon (west)
+CA +4916-12307 America/Vancouver Pacific - BC (most areas)
+CH,DE,LI +4723+00832 Europe/Zurich Büsingen
+CI,BF,GH,GM,GN,IS,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan
+CK -2114-15946 Pacific/Rarotonga
+CL -3327-07040 America/Santiago most of Chile
+CL -4534-07204 America/Coyhaique Aysén Region
+CL -5309-07055 America/Punta_Arenas Magallanes Region
+CL -2709-10926 Pacific/Easter Easter Island
+CN +3114+12128 Asia/Shanghai Beijing Time
+CN +4348+08735 Asia/Urumqi Xinjiang Time
+CO +0436-07405 America/Bogota
+CR +0956-08405 America/Costa_Rica
+CU +2308-08222 America/Havana
+CV +1455-02331 Atlantic/Cape_Verde
+CY +3510+03322 Asia/Nicosia most of Cyprus
+CY +3507+03357 Asia/Famagusta Northern Cyprus
+CZ,SK +5005+01426 Europe/Prague
+DE,DK,NO,SE,SJ +5230+01322 Europe/Berlin most of Germany
+DO +1828-06954 America/Santo_Domingo
+DZ +3647+00303 Africa/Algiers
+EC -0210-07950 America/Guayaquil Ecuador (mainland)
+EC -0054-08936 Pacific/Galapagos Galápagos Islands
+EE +5925+02445 Europe/Tallinn
+EG +3003+03115 Africa/Cairo
+EH +2709-01312 Africa/El_Aaiun
+ES +4024-00341 Europe/Madrid Spain (mainland)
+ES +3553-00519 Africa/Ceuta Ceuta, Melilla
+ES +2806-01524 Atlantic/Canary Canary Islands
+FI,AX +6010+02458 Europe/Helsinki
+FJ -1808+17825 Pacific/Fiji
+FK -5142-05751 Atlantic/Stanley
+FM +0519+16259 Pacific/Kosrae Kosrae
+FO +6201-00646 Atlantic/Faroe
+FR,MC +4852+00220 Europe/Paris
+GB,GG,IM,JE +513030-0000731 Europe/London
+GE +4143+04449 Asia/Tbilisi
+GF +0456-05220 America/Cayenne
+GI +3608-00521 Europe/Gibraltar
+GL +6411-05144 America/Nuuk most of Greenland
+GL +7646-01840 America/Danmarkshavn National Park (east coast)
+GL +7029-02158 America/Scoresbysund Scoresbysund/Ittoqqortoormiit
+GL +7634-06847 America/Thule Thule/Pituffik
+GR +3758+02343 Europe/Athens
+GS -5416-03632 Atlantic/South_Georgia
+GT +1438-09031 America/Guatemala
+GU,MP +1328+14445 Pacific/Guam
+GW +1151-01535 Africa/Bissau
+GY +0648-05810 America/Guyana
+HK +2217+11409 Asia/Hong_Kong
+HN +1406-08713 America/Tegucigalpa
+HT +1832-07220 America/Port-au-Prince
+HU +4730+01905 Europe/Budapest
+ID -0610+10648 Asia/Jakarta Java, Sumatra
+ID -0002+10920 Asia/Pontianak Borneo (west, central)
+ID -0507+11924 Asia/Makassar Borneo (east, south), Sulawesi/Celebes, Bali, Nusa Tengarra, Timor (west)
+ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya), Malukus/Moluccas
+IE +5320-00615 Europe/Dublin
+IL +314650+0351326 Asia/Jerusalem
+IN +2232+08822 Asia/Kolkata
+IO -0720+07225 Indian/Chagos
+IQ +3321+04425 Asia/Baghdad
+IR +3540+05126 Asia/Tehran
+IT,SM,VA +4154+01229 Europe/Rome
+JM +175805-0764736 America/Jamaica
+JO +3157+03556 Asia/Amman
+JP,AU +353916+1394441 Asia/Tokyo Eyre Bird Observatory
+KE,DJ,ER,ET,KM,MG,SO,TZ,UG,YT -0117+03649 Africa/Nairobi
+KG +4254+07436 Asia/Bishkek
+KI,MH,TV,UM,WF +0125+17300 Pacific/Tarawa Gilberts, Marshalls, Wake
+KI -0247-17143 Pacific/Kanton Phoenix Islands
+KI +0152-15720 Pacific/Kiritimati Line Islands
+KP +3901+12545 Asia/Pyongyang
+KR +3733+12658 Asia/Seoul
+KZ +4315+07657 Asia/Almaty most of Kazakhstan
+KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda
+KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay
+KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe
+KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau
+KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur'yev
+KZ +5113+05121 Asia/Oral West Kazakhstan
+LB +3353+03530 Asia/Beirut
+LK +0656+07951 Asia/Colombo
+LR +0618-01047 Africa/Monrovia
+LT +5441+02519 Europe/Vilnius
+LV +5657+02406 Europe/Riga
+LY +3254+01311 Africa/Tripoli
+MA +3339-00735 Africa/Casablanca
+MD +4700+02850 Europe/Chisinau
+MH +0905+16720 Pacific/Kwajalein Kwajalein
+MM,CC +1647+09610 Asia/Yangon
+MN +4755+10653 Asia/Ulaanbaatar most of Mongolia
+MN +4801+09139 Asia/Hovd Bayan-Ölgii, Hovd, Uvs
+MO +221150+1133230 Asia/Macau
+MQ +1436-06105 America/Martinique
+MT +3554+01431 Europe/Malta
+MU -2010+05730 Indian/Mauritius
+MV,TF +0410+07330 Indian/Maldives Kerguelen, St Paul I, Amsterdam I
+MX +1924-09909 America/Mexico_City Central Mexico
+MX +2105-08646 America/Cancun Quintana Roo
+MX +2058-08937 America/Merida Campeche, Yucatán
+MX +2540-10019 America/Monterrey Durango; Coahuila, Nuevo León, Tamaulipas (most areas)
+MX +2550-09730 America/Matamoros Coahuila, Nuevo León, Tamaulipas (US border)
+MX +2838-10605 America/Chihuahua Chihuahua (most areas)
+MX +3144-10629 America/Ciudad_Juarez Chihuahua (US border - west)
+MX +2934-10425 America/Ojinaga Chihuahua (US border - east)
+MX +2313-10625 America/Mazatlan Baja California Sur, Nayarit (most areas), Sinaloa
+MX +2048-10515 America/Bahia_Banderas Bahía de Banderas
+MX +2904-11058 America/Hermosillo Sonora
+MX +3232-11701 America/Tijuana Baja California
+MY,BN +0133+11020 Asia/Kuching Sabah, Sarawak
+MZ,BI,BW,CD,MW,RW,ZM,ZW -2558+03235 Africa/Maputo Central Africa Time
+NA -2234+01706 Africa/Windhoek
+NC -2216+16627 Pacific/Noumea
+NF -2903+16758 Pacific/Norfolk
+NG,AO,BJ,CD,CF,CG,CM,GA,GQ,NE +0627+00324 Africa/Lagos West Africa Time
+NI +1209-08617 America/Managua
+NP +2743+08519 Asia/Kathmandu
+NR -0031+16655 Pacific/Nauru
+NU -1901-16955 Pacific/Niue
+NZ,AQ -3652+17446 Pacific/Auckland New Zealand time
+NZ -4357-17633 Pacific/Chatham Chatham Islands
+PA,CA,KY +0858-07932 America/Panama EST - ON (Atikokan), NU (Coral H)
+PE -1203-07703 America/Lima
+PF -1732-14934 Pacific/Tahiti Society Islands
+PF -0900-13930 Pacific/Marquesas Marquesas Islands
+PF -2308-13457 Pacific/Gambier Gambier Islands
+PG,AQ,FM -0930+14710 Pacific/Port_Moresby Papua New Guinea (most areas), Chuuk, Yap, Dumont d'Urville
+PG -0613+15534 Pacific/Bougainville Bougainville
+PH +143512+1205804 Asia/Manila
+PK +2452+06703 Asia/Karachi
+PL +5215+02100 Europe/Warsaw
+PM +4703-05620 America/Miquelon
+PN -2504-13005 Pacific/Pitcairn
+PR,AG,CA,AI,AW,BL,BQ,CW,DM,GD,GP,KN,LC,MF,MS,SX,TT,VC,VG,VI +182806-0660622 America/Puerto_Rico AST - QC (Lower North Shore)
+PS +3130+03428 Asia/Gaza Gaza Strip
+PS +313200+0350542 Asia/Hebron West Bank
+PT +3843-00908 Europe/Lisbon Portugal (mainland)
+PT +3238-01654 Atlantic/Madeira Madeira Islands
+PT +3744-02540 Atlantic/Azores Azores
+PW +0720+13429 Pacific/Palau
+PY -2516-05740 America/Asuncion
+QA,BH +2517+05132 Asia/Qatar
+RO +4426+02606 Europe/Bucharest
+RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade
+RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad
+RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area
+# Mention RU and UA alphabetically. See "territorial claims" above.
+RU,UA +4457+03406 Europe/Simferopol Crimea
+RU +5836+04939 Europe/Kirov MSK+00 - Kirov
+RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd
+RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan
+RU +5134+04602 Europe/Saratov MSK+01 - Saratov
+RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk
+RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
+RU +5651+06036 Asia/Yekaterinburg MSK+02 - Urals
+RU +5500+07324 Asia/Omsk MSK+03 - Omsk
+RU +5502+08255 Asia/Novosibirsk MSK+04 - Novosibirsk
+RU +5322+08345 Asia/Barnaul MSK+04 - Altai
+RU +5630+08458 Asia/Tomsk MSK+04 - Tomsk
+RU +5345+08707 Asia/Novokuznetsk MSK+04 - Kemerovo
+RU +5601+09250 Asia/Krasnoyarsk MSK+04 - Krasnoyarsk area
+RU +5216+10420 Asia/Irkutsk MSK+05 - Irkutsk, Buryatia
+RU +5203+11328 Asia/Chita MSK+06 - Zabaykalsky
+RU +6200+12940 Asia/Yakutsk MSK+06 - Lena River
+RU +623923+1353314 Asia/Khandyga MSK+06 - Tomponsky, Ust-Maysky
+RU +4310+13156 Asia/Vladivostok MSK+07 - Amur River
+RU +643337+1431336 Asia/Ust-Nera MSK+07 - Oymyakonsky
+RU +5934+15048 Asia/Magadan MSK+08 - Magadan
+RU +4658+14242 Asia/Sakhalin MSK+08 - Sakhalin Island
+RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E), N Kuril Is
+RU +5301+15839 Asia/Kamchatka MSK+09 - Kamchatka
+RU +6445+17729 Asia/Anadyr MSK+09 - Bering Sea
+SA,AQ,KW,YE +2438+04643 Asia/Riyadh Syowa
+SB,FM -0932+16012 Pacific/Guadalcanal Pohnpei
+SD +1536+03232 Africa/Khartoum
+SG,AQ,MY +0117+10351 Asia/Singapore peninsular Malaysia, Concordia
+SR +0550-05510 America/Paramaribo
+SS +0451+03137 Africa/Juba
+ST +0020+00644 Africa/Sao_Tome
+SV +1342-08912 America/El_Salvador
+SY +3330+03618 Asia/Damascus
+TC +2128-07108 America/Grand_Turk
+TD +1207+01503 Africa/Ndjamena
+TH,CX,KH,LA,VN +1345+10031 Asia/Bangkok north Vietnam
+TJ +3835+06848 Asia/Dushanbe
+TK -0922-17114 Pacific/Fakaofo
+TL -0833+12535 Asia/Dili
+TM +3757+05823 Asia/Ashgabat
+TN +3648+01011 Africa/Tunis
+TO -210800-1751200 Pacific/Tongatapu
+TR +4101+02858 Europe/Istanbul
+TW +2503+12130 Asia/Taipei
+UA +5026+03031 Europe/Kyiv most of Ukraine
+US +404251-0740023 America/New_York Eastern (most areas)
+US +421953-0830245 America/Detroit Eastern - MI (most areas)
+US +381515-0854534 America/Kentucky/Louisville Eastern - KY (Louisville area)
+US +364947-0845057 America/Kentucky/Monticello Eastern - KY (Wayne)
+US +394606-0860929 America/Indiana/Indianapolis Eastern - IN (most areas)
+US +384038-0873143 America/Indiana/Vincennes Eastern - IN (Da, Du, K, Mn)
+US +410305-0863611 America/Indiana/Winamac Eastern - IN (Pulaski)
+US +382232-0862041 America/Indiana/Marengo Eastern - IN (Crawford)
+US +382931-0871643 America/Indiana/Petersburg Eastern - IN (Pike)
+US +384452-0850402 America/Indiana/Vevay Eastern - IN (Switzerland)
+US +415100-0873900 America/Chicago Central (most areas)
+US +375711-0864541 America/Indiana/Tell_City Central - IN (Perry)
+US +411745-0863730 America/Indiana/Knox Central - IN (Starke)
+US +450628-0873651 America/Menominee Central - MI (Wisconsin border)
+US +470659-1011757 America/North_Dakota/Center Central - ND (Oliver)
+US +465042-1012439 America/North_Dakota/New_Salem Central - ND (Morton rural)
+US +471551-1014640 America/North_Dakota/Beulah Central - ND (Mercer)
+US +394421-1045903 America/Denver Mountain (most areas)
+US +433649-1161209 America/Boise Mountain - ID (south), OR (east)
+US,CA +332654-1120424 America/Phoenix MST - AZ (most areas), Creston BC
+US +340308-1181434 America/Los_Angeles Pacific
+US +611305-1495401 America/Anchorage Alaska (most areas)
+US +581807-1342511 America/Juneau Alaska - Juneau area
+US +571035-1351807 America/Sitka Alaska - Sitka area
+US +550737-1313435 America/Metlakatla Alaska - Annette Island
+US +593249-1394338 America/Yakutat Alaska - Yakutat
+US +643004-1652423 America/Nome Alaska (west)
+US +515248-1763929 America/Adak Alaska - western Aleutians
+US +211825-1575130 Pacific/Honolulu Hawaii
+UY -345433-0561245 America/Montevideo
+UZ +3940+06648 Asia/Samarkand Uzbekistan (west)
+UZ +4120+06918 Asia/Tashkent Uzbekistan (east)
+VE +1030-06656 America/Caracas
+VN +1045+10640 Asia/Ho_Chi_Minh south Vietnam
+VU -1740+16825 Pacific/Efate
+WS -1350-17144 Pacific/Apia
+ZA,LS,SZ -2615+02800 Africa/Johannesburg
+#
+# The next section contains experimental tab-separated comments for
+# use by user agents like tzselect that identify continents and oceans.
+#
+# For example, the comment "#@AQAntarctica/" means the country code
+# AQ is in the continent Antarctica regardless of the Zone name,
+# so Pacific/Auckland should be listed under Antarctica as well as
+# under the Pacific because its line's country codes include AQ.
+#
+# If more than one country code is affected each is listed separated
+# by commas, e.g., #@IS,SHAtlantic/". If a country code is in
+# more than one continent or ocean, each is listed separated by
+# commas, e.g., the second column of "#@CY,TRAsia/,Europe/".
+#
+# These experimental comments are present only for country codes where
+# the continent or ocean is not already obvious from the Zone name.
+# For example, there is no such comment for RU since it already
+# corresponds to Zone names starting with both "Europe/" and "Asia/".
+#
+#@AQ Antarctica/
+#@IS,SH Atlantic/
+#@CY,TR Asia/,Europe/
+#@SJ Arctic/
+#@CC,CX,KM,MG,YT Indian/
diff --git a/testcline/lib/python3.12/site-packages/pytz/zoneinfo/zonenow.tab b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/zonenow.tab
new file mode 100644
index 0000000..093f0a0
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/pytz/zoneinfo/zonenow.tab
@@ -0,0 +1,296 @@
+# tzdb timezone descriptions, for users who do not care about old timestamps
+#
+# This file is in the public domain.
+#
+# From Paul Eggert (2023-12-18):
+# This file contains a table where each row stands for a timezone
+# where civil timestamps are predicted to agree from now on.
+# This file is like zone1970.tab (see zone1970.tab's comments),
+# but with the following changes:
+#
+# 1. Each timezone corresponds to a set of clocks that are planned
+# to agree from now on. This is a larger set of clocks than in
+# zone1970.tab, where each timezone's clocks must agree from 1970 on.
+# 2. The first column is irrelevant and ignored.
+# 3. The table is sorted in a different way:
+# first by standard time UTC offset;
+# then, if DST is used, by daylight saving UTC offset;
+# then by time zone abbreviation.
+# 4. Every timezone has a nonempty comments column, with wording
+# distinguishing the timezone only from other timezones with the
+# same UTC offset at some point during the year.
+#
+# The format of this table is experimental, and may change in future versions.
+#
+# This table is intended as an aid for users, to help them select timezones
+# appropriate for their practical needs. It is not intended to take or
+# endorse any position on legal or territorial claims.
+#
+#XX coordinates TZ comments
+#
+# -11 - SST
+XX -1416-17042 Pacific/Pago_Pago Midway; Samoa ("SST")
+#
+# -11
+XX -1901-16955 Pacific/Niue Niue
+#
+# -10 - HST
+XX +211825-1575130 Pacific/Honolulu Hawaii ("HST")
+#
+# -10
+XX -1732-14934 Pacific/Tahiti Tahiti; Cook Islands
+#
+# -10/-09 - HST / HDT (North America DST)
+XX +515248-1763929 America/Adak western Aleutians in Alaska ("HST/HDT")
+#
+# -09:30
+XX -0900-13930 Pacific/Marquesas Marquesas
+#
+# -09
+XX -2308-13457 Pacific/Gambier Gambier
+#
+# -09/-08 - AKST/AKDT (North America DST)
+XX +611305-1495401 America/Anchorage most of Alaska ("AKST/AKDT")
+#
+# -08
+XX -2504-13005 Pacific/Pitcairn Pitcairn
+#
+# -08/-07 - PST/PDT (North America DST)
+XX +340308-1181434 America/Los_Angeles Pacific ("PST/PDT") - US & Canada; Mexico near US border
+#
+# -07 - MST
+XX +332654-1120424 America/Phoenix Mountain Standard ("MST") - Arizona; western Mexico; Yukon
+#
+# -07/-06 - MST/MDT (North America DST)
+XX +394421-1045903 America/Denver Mountain ("MST/MDT") - US & Canada; Mexico near US border
+#
+# -06
+XX -0054-08936 Pacific/Galapagos Galápagos
+#
+# -06 - CST
+XX +1924-09909 America/Mexico_City Central Standard ("CST") - Saskatchewan; central Mexico; Central America
+#
+# -06/-05 (Chile DST)
+XX -2709-10926 Pacific/Easter Easter Island
+#
+# -06/-05 - CST/CDT (North America DST)
+XX +415100-0873900 America/Chicago Central ("CST/CDT") - US & Canada; Mexico near US border
+#
+# -05
+XX -1203-07703 America/Lima eastern South America
+#
+# -05 - EST
+XX +175805-0764736 America/Jamaica Eastern Standard ("EST") - Caymans; Jamaica; eastern Mexico; Panama
+#
+# -05/-04 - CST/CDT (Cuba DST)
+XX +2308-08222 America/Havana Cuba
+#
+# -05/-04 - EST/EDT (North America DST)
+XX +404251-0740023 America/New_York Eastern ("EST/EDT") - US & Canada
+#
+# -04
+XX +1030-06656 America/Caracas western South America
+#
+# -04 - AST
+XX +1828-06954 America/Santo_Domingo Atlantic Standard ("AST") - eastern Caribbean
+#
+# -04/-03 (Chile DST)
+XX -3327-07040 America/Santiago most of Chile
+#
+# -04/-03 - AST/ADT (North America DST)
+XX +4439-06336 America/Halifax Atlantic ("AST/ADT") - Canada; Bermuda
+#
+# -03:30/-02:30 - NST/NDT (North America DST)
+XX +4734-05243 America/St_Johns Newfoundland ("NST/NDT")
+#
+# -03
+XX -2332-04637 America/Sao_Paulo eastern and southern South America
+#
+# -03/-02 (North America DST)
+XX +4703-05620 America/Miquelon St Pierre & Miquelon
+#
+# -02
+XX -0351-03225 America/Noronha Fernando de Noronha; South Georgia
+#
+# -02/-01 (EU DST)
+XX +6411-05144 America/Nuuk most of Greenland
+#
+# -01
+XX +1455-02331 Atlantic/Cape_Verde Cape Verde
+#
+# -01/+00 (EU DST)
+XX +3744-02540 Atlantic/Azores Azores
+#
+# +00 - GMT
+XX +0519-00402 Africa/Abidjan far western Africa; Iceland ("GMT")
+#
+# +00/+01 - GMT/BST (EU DST)
+XX +513030-0000731 Europe/London United Kingdom ("GMT/BST")
+#
+# +00/+01 - WET/WEST (EU DST)
+XX +3843-00908 Europe/Lisbon western Europe ("WET/WEST")
+#
+# +00/+02 - Troll DST
+XX -720041+0023206 Antarctica/Troll Troll Station in Antarctica
+#
+# +01 - CET
+XX +3647+00303 Africa/Algiers Algeria, Tunisia ("CET")
+#
+# +01 - WAT
+XX +0627+00324 Africa/Lagos western Africa ("WAT")
+#
+# +01/+00 - IST/GMT (EU DST in reverse)
+XX +5320-00615 Europe/Dublin Ireland ("IST/GMT")
+#
+# +01/+00 - (Morocco DST)
+XX +3339-00735 Africa/Casablanca Morocco
+#
+# +01/+02 - CET/CEST (EU DST)
+XX +4852+00220 Europe/Paris central Europe ("CET/CEST")
+#
+# +02 - CAT
+XX -2558+03235 Africa/Maputo central Africa ("CAT")
+#
+# +02 - EET
+XX +3254+01311 Africa/Tripoli Libya; Kaliningrad ("EET")
+#
+# +02 - SAST
+XX -2615+02800 Africa/Johannesburg southern Africa ("SAST")
+#
+# +02/+03 - EET/EEST (EU DST)
+XX +3758+02343 Europe/Athens eastern Europe ("EET/EEST")
+#
+# +02/+03 - EET/EEST (Egypt DST)
+XX +3003+03115 Africa/Cairo Egypt
+#
+# +02/+03 - EET/EEST (Lebanon DST)
+XX +3353+03530 Asia/Beirut Lebanon
+#
+# +02/+03 - EET/EEST (Moldova DST)
+XX +4700+02850 Europe/Chisinau Moldova
+#
+# +02/+03 - EET/EEST (Palestine DST)
+XX +3130+03428 Asia/Gaza Palestine
+#
+# +02/+03 - IST/IDT (Israel DST)
+XX +314650+0351326 Asia/Jerusalem Israel
+#
+# +03
+XX +4101+02858 Europe/Istanbul Near East; Belarus
+#
+# +03 - EAT
+XX -0117+03649 Africa/Nairobi eastern Africa ("EAT")
+#
+# +03 - MSK
+XX +554521+0373704 Europe/Moscow Moscow ("MSK")
+#
+# +03:30
+XX +3540+05126 Asia/Tehran Iran
+#
+# +04
+XX +2518+05518 Asia/Dubai Russia; Caucasus; Persian Gulf; Seychelles; Réunion
+#
+# +04:30
+XX +3431+06912 Asia/Kabul Afghanistan
+#
+# +05
+XX +4120+06918 Asia/Tashkent Russia; Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives
+#
+# +05 - PKT
+XX +2452+06703 Asia/Karachi Pakistan ("PKT")
+#
+# +05:30
+XX +0656+07951 Asia/Colombo Sri Lanka
+#
+# +05:30 - IST
+XX +2232+08822 Asia/Kolkata India ("IST")
+#
+# +05:45
+XX +2743+08519 Asia/Kathmandu Nepal
+#
+# +06
+XX +2343+09025 Asia/Dhaka Russia; Kyrgyzstan; Bhutan; Bangladesh; Chagos
+#
+# +06:30
+XX +1647+09610 Asia/Yangon Myanmar; Cocos
+#
+# +07
+XX +1345+10031 Asia/Bangkok Russia; Indochina; Christmas Island
+#
+# +07 - WIB
+XX -0610+10648 Asia/Jakarta Indonesia ("WIB")
+#
+# +08
+XX +0117+10351 Asia/Singapore Russia; Brunei; Malaysia; Singapore; Concordia
+#
+# +08 - AWST
+XX -3157+11551 Australia/Perth Western Australia ("AWST")
+#
+# +08 - CST
+XX +3114+12128 Asia/Shanghai China ("CST")
+#
+# +08 - HKT
+XX +2217+11409 Asia/Hong_Kong Hong Kong ("HKT")
+#
+# +08 - PHT
+XX +143512+1205804 Asia/Manila Philippines ("PHT")
+#
+# +08 - WITA
+XX -0507+11924 Asia/Makassar Indonesia ("WITA")
+#
+# +08:45
+XX -3143+12852 Australia/Eucla Eucla
+#
+# +09
+XX +5203+11328 Asia/Chita Russia; Palau; East Timor
+#
+# +09 - JST
+XX +353916+1394441 Asia/Tokyo Japan ("JST"); Eyre Bird Observatory
+#
+# +09 - KST
+XX +3733+12658 Asia/Seoul Korea ("KST")
+#
+# +09 - WIT
+XX -0232+14042 Asia/Jayapura Indonesia ("WIT")
+#
+# +09:30 - ACST
+XX -1228+13050 Australia/Darwin Northern Territory ("ACST")
+#
+# +09:30/+10:30 - ACST/ACDT (Australia DST)
+XX -3455+13835 Australia/Adelaide South Australia ("ACST/ACDT")
+#
+# +10
+XX +4310+13156 Asia/Vladivostok Russia; Yap; Chuuk; Papua New Guinea; Dumont d'Urville
+#
+# +10 - AEST
+XX -2728+15302 Australia/Brisbane Queensland ("AEST")
+#
+# +10 - ChST
+XX +1328+14445 Pacific/Guam Mariana Islands ("ChST")
+#
+# +10/+11 - AEST/AEDT (Australia DST)
+XX -3352+15113 Australia/Sydney southeast Australia ("AEST/AEDT")
+#
+# +10:30/+11
+XX -3133+15905 Australia/Lord_Howe Lord Howe Island
+#
+# +11
+XX -0613+15534 Pacific/Bougainville Russia; Kosrae; Bougainville; Solomons
+#
+# +11/+12 (Australia DST)
+XX -2903+16758 Pacific/Norfolk Norfolk Island
+#
+# +12
+XX +5301+15839 Asia/Kamchatka Russia; Tuvalu; Fiji; etc.
+#
+# +12/+13 (New Zealand DST)
+XX -3652+17446 Pacific/Auckland New Zealand ("NZST/NZDT")
+#
+# +12:45/+13:45 (Chatham DST)
+XX -4357-17633 Pacific/Chatham Chatham Islands
+#
+# +13
+XX -210800-1751200 Pacific/Tongatapu Kanton; Tokelau; Samoa (western); Tonga
+#
+# +14
+XX +0152-15720 Pacific/Kiritimati Kiritimati
diff --git a/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE
new file mode 100644
index 0000000..67db858
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE
@@ -0,0 +1,175 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA
new file mode 100644
index 0000000..72d9dc5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA
@@ -0,0 +1,119 @@
+Metadata-Version: 2.1
+Name: requests
+Version: 2.32.3
+Summary: Python HTTP for Humans.
+Home-page: https://requests.readthedocs.io
+Author: Kenneth Reitz
+Author-email: me@kennethreitz.org
+License: Apache-2.0
+Project-URL: Documentation, https://requests.readthedocs.io
+Project-URL: Source, https://github.com/psf/requests
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Internet :: WWW/HTTP
+Classifier: Topic :: Software Development :: Libraries
+Requires-Python: >=3.8
+Description-Content-Type: text/markdown
+License-File: LICENSE
+Requires-Dist: charset-normalizer <4,>=2
+Requires-Dist: idna <4,>=2.5
+Requires-Dist: urllib3 <3,>=1.21.1
+Requires-Dist: certifi >=2017.4.17
+Provides-Extra: security
+Provides-Extra: socks
+Requires-Dist: PySocks !=1.5.7,>=1.5.6 ; extra == 'socks'
+Provides-Extra: use_chardet_on_py3
+Requires-Dist: chardet <6,>=3.0.2 ; extra == 'use_chardet_on_py3'
+
+# Requests
+
+**Requests** is a simple, yet elegant, HTTP library.
+
+```python
+>>> import requests
+>>> r = requests.get('https://httpbin.org/basic-auth/user/pass', auth=('user', 'pass'))
+>>> r.status_code
+200
+>>> r.headers['content-type']
+'application/json; charset=utf8'
+>>> r.encoding
+'utf-8'
+>>> r.text
+'{"authenticated": true, ...'
+>>> r.json()
+{'authenticated': True, ...}
+```
+
+Requests allows you to send HTTP/1.1 requests extremely easily. There’s no need to manually add query strings to your URLs, or to form-encode your `PUT` & `POST` data — but nowadays, just use the `json` method!
+
+Requests is one of the most downloaded Python packages today, pulling in around `30M downloads / week`— according to GitHub, Requests is currently [depended upon](https://github.com/psf/requests/network/dependents?package_id=UGFja2FnZS01NzA4OTExNg%3D%3D) by `1,000,000+` repositories. You may certainly put your trust in this code.
+
+[](https://pepy.tech/project/requests)
+[](https://pypi.org/project/requests)
+[](https://github.com/psf/requests/graphs/contributors)
+
+## Installing Requests and Supported Versions
+
+Requests is available on PyPI:
+
+```console
+$ python -m pip install requests
+```
+
+Requests officially supports Python 3.8+.
+
+## Supported Features & Best–Practices
+
+Requests is ready for the demands of building robust and reliable HTTP–speaking applications, for the needs of today.
+
+- Keep-Alive & Connection Pooling
+- International Domains and URLs
+- Sessions with Cookie Persistence
+- Browser-style TLS/SSL Verification
+- Basic & Digest Authentication
+- Familiar `dict`–like Cookies
+- Automatic Content Decompression and Decoding
+- Multi-part File Uploads
+- SOCKS Proxy Support
+- Connection Timeouts
+- Streaming Downloads
+- Automatic honoring of `.netrc`
+- Chunked HTTP Requests
+
+## API Reference and User Guide available on [Read the Docs](https://requests.readthedocs.io)
+
+[](https://requests.readthedocs.io)
+
+## Cloning the repository
+
+When cloning the Requests repository, you may need to add the `-c
+fetch.fsck.badTimezone=ignore` flag to avoid an error about a bad commit (see
+[this issue](https://github.com/psf/requests/issues/2690) for more background):
+
+```shell
+git clone -c fetch.fsck.badTimezone=ignore https://github.com/psf/requests.git
+```
+
+You can also apply this setting to your global Git config:
+
+```shell
+git config --global fetch.fsck.badTimezone ignore
+```
+
+---
+
+[](https://kennethreitz.org) [](https://www.python.org/psf)
diff --git a/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/RECORD b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/RECORD
new file mode 100644
index 0000000..f34e5a1
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/RECORD
@@ -0,0 +1,43 @@
+requests-2.32.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+requests-2.32.3.dist-info/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
+requests-2.32.3.dist-info/METADATA,sha256=ZY7oRUweLnb7jCEnEW9hFWs7IpQbNVnAA4ncpwA4WBo,4610
+requests-2.32.3.dist-info/RECORD,,
+requests-2.32.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+requests-2.32.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+requests-2.32.3.dist-info/top_level.txt,sha256=fMSVmHfb5rbGOo6xv-O_tUX6j-WyixssE-SnwcDRxNQ,9
+requests/__init__.py,sha256=4xaAERmPDIBPsa2PsjpU9r06yooK-2mZKHTZAhWRWts,5072
+requests/__pycache__/__init__.cpython-312.pyc,,
+requests/__pycache__/__version__.cpython-312.pyc,,
+requests/__pycache__/_internal_utils.cpython-312.pyc,,
+requests/__pycache__/adapters.cpython-312.pyc,,
+requests/__pycache__/api.cpython-312.pyc,,
+requests/__pycache__/auth.cpython-312.pyc,,
+requests/__pycache__/certs.cpython-312.pyc,,
+requests/__pycache__/compat.cpython-312.pyc,,
+requests/__pycache__/cookies.cpython-312.pyc,,
+requests/__pycache__/exceptions.cpython-312.pyc,,
+requests/__pycache__/help.cpython-312.pyc,,
+requests/__pycache__/hooks.cpython-312.pyc,,
+requests/__pycache__/models.cpython-312.pyc,,
+requests/__pycache__/packages.cpython-312.pyc,,
+requests/__pycache__/sessions.cpython-312.pyc,,
+requests/__pycache__/status_codes.cpython-312.pyc,,
+requests/__pycache__/structures.cpython-312.pyc,,
+requests/__pycache__/utils.cpython-312.pyc,,
+requests/__version__.py,sha256=FVfglgZmNQnmYPXpOohDU58F5EUb_-VnSTaAesS187g,435
+requests/_internal_utils.py,sha256=nMQymr4hs32TqVo5AbCrmcJEhvPUh7xXlluyqwslLiQ,1495
+requests/adapters.py,sha256=KIcecscqam6reOCXRl4DwP4jX8Jcl8sd57ft17KR2cQ,27451
+requests/api.py,sha256=_Zb9Oa7tzVIizTKwFrPjDEY9ejtm_OnSRERnADxGsQs,6449
+requests/auth.py,sha256=kF75tqnLctZ9Mf_hm9TZIj4cQWnN5uxRz8oWsx5wmR0,10186
+requests/certs.py,sha256=Z9Sb410Anv6jUFTyss0jFFhU6xst8ctELqfy8Ev23gw,429
+requests/compat.py,sha256=C5w_DPLSurXPgcdWU78fora0APmbYkX2G89QvH5xzPA,1817
+requests/cookies.py,sha256=bNi-iqEj4NPZ00-ob-rHvzkvObzN3lEpgw3g6paS3Xw,18590
+requests/exceptions.py,sha256=jJPS1UWATs86ShVUaLorTiJb1SaGuoNEWgICJep-VkY,4260
+requests/help.py,sha256=gPX5d_H7Xd88aDABejhqGgl9B1VFRTt5BmiYvL3PzIQ,3875
+requests/hooks.py,sha256=CiuysiHA39V5UfcCBXFIx83IrDpuwfN9RcTUgv28ftQ,733
+requests/models.py,sha256=k42roXzC8u_OagAPQi9U4MkfO7i4r2FdaqvMqstPehc,35418
+requests/packages.py,sha256=_g0gZ681UyAlKHRjH6kanbaoxx2eAb6qzcXiODyTIoc,904
+requests/sessions.py,sha256=ykTI8UWGSltOfH07HKollH7kTBGw4WhiBVaQGmckTw4,30495
+requests/status_codes.py,sha256=iJUAeA25baTdw-6PfD0eF4qhpINDJRJI-yaMqxs4LEI,4322
+requests/structures.py,sha256=-IbmhVz06S-5aPSZuUthZ6-6D9XOjRuTXHOabY041XM,2912
+requests/utils.py,sha256=HiQC6Nq_Da3ktaMiFzQkh-dCk3iQHHKEsYS5kDc-8Cw,33619
diff --git a/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/REQUESTED b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/REQUESTED
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/WHEEL
new file mode 100644
index 0000000..bab98d6
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.43.0)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/top_level.txt
new file mode 100644
index 0000000..f229360
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests-2.32.3.dist-info/top_level.txt
@@ -0,0 +1 @@
+requests
diff --git a/testcline/lib/python3.12/site-packages/requests/__init__.py b/testcline/lib/python3.12/site-packages/requests/__init__.py
new file mode 100644
index 0000000..051cda1
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/__init__.py
@@ -0,0 +1,184 @@
+# __
+# /__) _ _ _ _ _/ _
+# / ( (- (/ (/ (- _) / _)
+# /
+
+"""
+Requests HTTP Library
+~~~~~~~~~~~~~~~~~~~~~
+
+Requests is an HTTP library, written in Python, for human beings.
+Basic GET usage:
+
+ >>> import requests
+ >>> r = requests.get('https://www.python.org')
+ >>> r.status_code
+ 200
+ >>> b'Python is a programming language' in r.content
+ True
+
+... or POST:
+
+ >>> payload = dict(key1='value1', key2='value2')
+ >>> r = requests.post('https://httpbin.org/post', data=payload)
+ >>> print(r.text)
+ {
+ ...
+ "form": {
+ "key1": "value1",
+ "key2": "value2"
+ },
+ ...
+ }
+
+The other HTTP methods are supported - see `requests.api`. Full documentation
+is at .
+
+:copyright: (c) 2017 by Kenneth Reitz.
+:license: Apache 2.0, see LICENSE for more details.
+"""
+
+import warnings
+
+import urllib3
+
+from .exceptions import RequestsDependencyWarning
+
+try:
+ from charset_normalizer import __version__ as charset_normalizer_version
+except ImportError:
+ charset_normalizer_version = None
+
+try:
+ from chardet import __version__ as chardet_version
+except ImportError:
+ chardet_version = None
+
+
+def check_compatibility(urllib3_version, chardet_version, charset_normalizer_version):
+ urllib3_version = urllib3_version.split(".")
+ assert urllib3_version != ["dev"] # Verify urllib3 isn't installed from git.
+
+ # Sometimes, urllib3 only reports its version as 16.1.
+ if len(urllib3_version) == 2:
+ urllib3_version.append("0")
+
+ # Check urllib3 for compatibility.
+ major, minor, patch = urllib3_version # noqa: F811
+ major, minor, patch = int(major), int(minor), int(patch)
+ # urllib3 >= 1.21.1
+ assert major >= 1
+ if major == 1:
+ assert minor >= 21
+
+ # Check charset_normalizer for compatibility.
+ if chardet_version:
+ major, minor, patch = chardet_version.split(".")[:3]
+ major, minor, patch = int(major), int(minor), int(patch)
+ # chardet_version >= 3.0.2, < 6.0.0
+ assert (3, 0, 2) <= (major, minor, patch) < (6, 0, 0)
+ elif charset_normalizer_version:
+ major, minor, patch = charset_normalizer_version.split(".")[:3]
+ major, minor, patch = int(major), int(minor), int(patch)
+ # charset_normalizer >= 2.0.0 < 4.0.0
+ assert (2, 0, 0) <= (major, minor, patch) < (4, 0, 0)
+ else:
+ warnings.warn(
+ "Unable to find acceptable character detection dependency "
+ "(chardet or charset_normalizer).",
+ RequestsDependencyWarning,
+ )
+
+
+def _check_cryptography(cryptography_version):
+ # cryptography < 1.3.4
+ try:
+ cryptography_version = list(map(int, cryptography_version.split(".")))
+ except ValueError:
+ return
+
+ if cryptography_version < [1, 3, 4]:
+ warning = "Old version of cryptography ({}) may cause slowdown.".format(
+ cryptography_version
+ )
+ warnings.warn(warning, RequestsDependencyWarning)
+
+
+# Check imported dependencies for compatibility.
+try:
+ check_compatibility(
+ urllib3.__version__, chardet_version, charset_normalizer_version
+ )
+except (AssertionError, ValueError):
+ warnings.warn(
+ "urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
+ "version!".format(
+ urllib3.__version__, chardet_version, charset_normalizer_version
+ ),
+ RequestsDependencyWarning,
+ )
+
+# Attempt to enable urllib3's fallback for SNI support
+# if the standard library doesn't support SNI or the
+# 'ssl' library isn't available.
+try:
+ try:
+ import ssl
+ except ImportError:
+ ssl = None
+
+ if not getattr(ssl, "HAS_SNI", False):
+ from urllib3.contrib import pyopenssl
+
+ pyopenssl.inject_into_urllib3()
+
+ # Check cryptography version
+ from cryptography import __version__ as cryptography_version
+
+ _check_cryptography(cryptography_version)
+except ImportError:
+ pass
+
+# urllib3's DependencyWarnings should be silenced.
+from urllib3.exceptions import DependencyWarning
+
+warnings.simplefilter("ignore", DependencyWarning)
+
+# Set default logging handler to avoid "No handler found" warnings.
+import logging
+from logging import NullHandler
+
+from . import packages, utils
+from .__version__ import (
+ __author__,
+ __author_email__,
+ __build__,
+ __cake__,
+ __copyright__,
+ __description__,
+ __license__,
+ __title__,
+ __url__,
+ __version__,
+)
+from .api import delete, get, head, options, patch, post, put, request
+from .exceptions import (
+ ConnectionError,
+ ConnectTimeout,
+ FileModeWarning,
+ HTTPError,
+ JSONDecodeError,
+ ReadTimeout,
+ RequestException,
+ Timeout,
+ TooManyRedirects,
+ URLRequired,
+)
+from .models import PreparedRequest, Request, Response
+from .sessions import Session, session
+from .status_codes import codes
+
+logging.getLogger(__name__).addHandler(NullHandler())
+
+# FileModeWarnings go off per the default.
+warnings.simplefilter("default", FileModeWarning, append=True)
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..df7653f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/__version__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/__version__.cpython-312.pyc
new file mode 100644
index 0000000..8cfca79
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/__version__.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/_internal_utils.cpython-312.pyc
similarity index 87%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/requests/__pycache__/_internal_utils.cpython-312.pyc
index 38fd54a..fad91be 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/requests/__pycache__/_internal_utils.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/adapters.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/adapters.cpython-312.pyc
new file mode 100644
index 0000000..a2cab65
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/adapters.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/api.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/api.cpython-312.pyc
new file mode 100644
index 0000000..2354325
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/api.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/auth.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/auth.cpython-312.pyc
new file mode 100644
index 0000000..5dad6c3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/auth.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/certs.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/certs.cpython-312.pyc
new file mode 100644
index 0000000..d81e9f2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/certs.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/compat.cpython-312.pyc
new file mode 100644
index 0000000..fdbd1a8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/compat.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/cookies.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/cookies.cpython-312.pyc
new file mode 100644
index 0000000..455614b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/cookies.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/exceptions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/exceptions.cpython-312.pyc
new file mode 100644
index 0000000..8796acb
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/exceptions.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/help.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/help.cpython-312.pyc
new file mode 100644
index 0000000..f6c5748
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/help.cpython-312.pyc differ
diff --git a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/hooks.cpython-312.pyc
similarity index 74%
rename from AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc
rename to testcline/lib/python3.12/site-packages/requests/__pycache__/hooks.cpython-312.pyc
index 7d659d7..e8bc5b2 100644
Binary files a/AIagent/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc and b/testcline/lib/python3.12/site-packages/requests/__pycache__/hooks.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/models.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/models.cpython-312.pyc
new file mode 100644
index 0000000..0aed8c8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/models.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/packages.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/packages.cpython-312.pyc
new file mode 100644
index 0000000..73934cd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/packages.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/sessions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/sessions.cpython-312.pyc
new file mode 100644
index 0000000..bcee937
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/sessions.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/status_codes.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/status_codes.cpython-312.pyc
new file mode 100644
index 0000000..2f540f3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/status_codes.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/structures.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/structures.cpython-312.pyc
new file mode 100644
index 0000000..370cb79
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/structures.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__pycache__/utils.cpython-312.pyc b/testcline/lib/python3.12/site-packages/requests/__pycache__/utils.cpython-312.pyc
new file mode 100644
index 0000000..7369d83
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/requests/__pycache__/utils.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/requests/__version__.py b/testcline/lib/python3.12/site-packages/requests/__version__.py
new file mode 100644
index 0000000..2c105ac
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/__version__.py
@@ -0,0 +1,14 @@
+# .-. .-. .-. . . .-. .-. .-. .-.
+# |( |- |.| | | |- `-. | `-.
+# ' ' `-' `-`.`-' `-' `-' ' `-'
+
+__title__ = "requests"
+__description__ = "Python HTTP for Humans."
+__url__ = "https://requests.readthedocs.io"
+__version__ = "2.32.3"
+__build__ = 0x023203
+__author__ = "Kenneth Reitz"
+__author_email__ = "me@kennethreitz.org"
+__license__ = "Apache-2.0"
+__copyright__ = "Copyright Kenneth Reitz"
+__cake__ = "\u2728 \U0001f370 \u2728"
diff --git a/testcline/lib/python3.12/site-packages/requests/_internal_utils.py b/testcline/lib/python3.12/site-packages/requests/_internal_utils.py
new file mode 100644
index 0000000..f2cf635
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/_internal_utils.py
@@ -0,0 +1,50 @@
+"""
+requests._internal_utils
+~~~~~~~~~~~~~~
+
+Provides utility functions that are consumed internally by Requests
+which depend on extremely few external helpers (such as compat)
+"""
+import re
+
+from .compat import builtin_str
+
+_VALID_HEADER_NAME_RE_BYTE = re.compile(rb"^[^:\s][^:\r\n]*$")
+_VALID_HEADER_NAME_RE_STR = re.compile(r"^[^:\s][^:\r\n]*$")
+_VALID_HEADER_VALUE_RE_BYTE = re.compile(rb"^\S[^\r\n]*$|^$")
+_VALID_HEADER_VALUE_RE_STR = re.compile(r"^\S[^\r\n]*$|^$")
+
+_HEADER_VALIDATORS_STR = (_VALID_HEADER_NAME_RE_STR, _VALID_HEADER_VALUE_RE_STR)
+_HEADER_VALIDATORS_BYTE = (_VALID_HEADER_NAME_RE_BYTE, _VALID_HEADER_VALUE_RE_BYTE)
+HEADER_VALIDATORS = {
+ bytes: _HEADER_VALIDATORS_BYTE,
+ str: _HEADER_VALIDATORS_STR,
+}
+
+
+def to_native_string(string, encoding="ascii"):
+ """Given a string object, regardless of type, returns a representation of
+ that string in the native string type, encoding and decoding where
+ necessary. This assumes ASCII unless told otherwise.
+ """
+ if isinstance(string, builtin_str):
+ out = string
+ else:
+ out = string.decode(encoding)
+
+ return out
+
+
+def unicode_is_ascii(u_string):
+ """Determine if unicode string only contains ASCII characters.
+
+ :param str u_string: unicode string to check. Must be unicode
+ and not Python 2 `str`.
+ :rtype: bool
+ """
+ assert isinstance(u_string, str)
+ try:
+ u_string.encode("ascii")
+ return True
+ except UnicodeEncodeError:
+ return False
diff --git a/testcline/lib/python3.12/site-packages/requests/adapters.py b/testcline/lib/python3.12/site-packages/requests/adapters.py
new file mode 100644
index 0000000..9a58b16
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/adapters.py
@@ -0,0 +1,719 @@
+"""
+requests.adapters
+~~~~~~~~~~~~~~~~~
+
+This module contains the transport adapters that Requests uses to define
+and maintain connections.
+"""
+
+import os.path
+import socket # noqa: F401
+import typing
+import warnings
+
+from urllib3.exceptions import ClosedPoolError, ConnectTimeoutError
+from urllib3.exceptions import HTTPError as _HTTPError
+from urllib3.exceptions import InvalidHeader as _InvalidHeader
+from urllib3.exceptions import (
+ LocationValueError,
+ MaxRetryError,
+ NewConnectionError,
+ ProtocolError,
+)
+from urllib3.exceptions import ProxyError as _ProxyError
+from urllib3.exceptions import ReadTimeoutError, ResponseError
+from urllib3.exceptions import SSLError as _SSLError
+from urllib3.poolmanager import PoolManager, proxy_from_url
+from urllib3.util import Timeout as TimeoutSauce
+from urllib3.util import parse_url
+from urllib3.util.retry import Retry
+from urllib3.util.ssl_ import create_urllib3_context
+
+from .auth import _basic_auth_str
+from .compat import basestring, urlparse
+from .cookies import extract_cookies_to_jar
+from .exceptions import (
+ ConnectionError,
+ ConnectTimeout,
+ InvalidHeader,
+ InvalidProxyURL,
+ InvalidSchema,
+ InvalidURL,
+ ProxyError,
+ ReadTimeout,
+ RetryError,
+ SSLError,
+)
+from .models import Response
+from .structures import CaseInsensitiveDict
+from .utils import (
+ DEFAULT_CA_BUNDLE_PATH,
+ extract_zipped_paths,
+ get_auth_from_url,
+ get_encoding_from_headers,
+ prepend_scheme_if_needed,
+ select_proxy,
+ urldefragauth,
+)
+
+try:
+ from urllib3.contrib.socks import SOCKSProxyManager
+except ImportError:
+
+ def SOCKSProxyManager(*args, **kwargs):
+ raise InvalidSchema("Missing dependencies for SOCKS support.")
+
+
+if typing.TYPE_CHECKING:
+ from .models import PreparedRequest
+
+
+DEFAULT_POOLBLOCK = False
+DEFAULT_POOLSIZE = 10
+DEFAULT_RETRIES = 0
+DEFAULT_POOL_TIMEOUT = None
+
+
+try:
+ import ssl # noqa: F401
+
+ _preloaded_ssl_context = create_urllib3_context()
+ _preloaded_ssl_context.load_verify_locations(
+ extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH)
+ )
+except ImportError:
+ # Bypass default SSLContext creation when Python
+ # interpreter isn't built with the ssl module.
+ _preloaded_ssl_context = None
+
+
+def _urllib3_request_context(
+ request: "PreparedRequest",
+ verify: "bool | str | None",
+ client_cert: "typing.Tuple[str, str] | str | None",
+ poolmanager: "PoolManager",
+) -> "(typing.Dict[str, typing.Any], typing.Dict[str, typing.Any])":
+ host_params = {}
+ pool_kwargs = {}
+ parsed_request_url = urlparse(request.url)
+ scheme = parsed_request_url.scheme.lower()
+ port = parsed_request_url.port
+
+ # Determine if we have and should use our default SSLContext
+ # to optimize performance on standard requests.
+ poolmanager_kwargs = getattr(poolmanager, "connection_pool_kw", {})
+ has_poolmanager_ssl_context = poolmanager_kwargs.get("ssl_context")
+ should_use_default_ssl_context = (
+ _preloaded_ssl_context is not None and not has_poolmanager_ssl_context
+ )
+
+ cert_reqs = "CERT_REQUIRED"
+ if verify is False:
+ cert_reqs = "CERT_NONE"
+ elif verify is True and should_use_default_ssl_context:
+ pool_kwargs["ssl_context"] = _preloaded_ssl_context
+ elif isinstance(verify, str):
+ if not os.path.isdir(verify):
+ pool_kwargs["ca_certs"] = verify
+ else:
+ pool_kwargs["ca_cert_dir"] = verify
+ pool_kwargs["cert_reqs"] = cert_reqs
+ if client_cert is not None:
+ if isinstance(client_cert, tuple) and len(client_cert) == 2:
+ pool_kwargs["cert_file"] = client_cert[0]
+ pool_kwargs["key_file"] = client_cert[1]
+ else:
+ # According to our docs, we allow users to specify just the client
+ # cert path
+ pool_kwargs["cert_file"] = client_cert
+ host_params = {
+ "scheme": scheme,
+ "host": parsed_request_url.hostname,
+ "port": port,
+ }
+ return host_params, pool_kwargs
+
+
+class BaseAdapter:
+ """The Base Transport Adapter"""
+
+ def __init__(self):
+ super().__init__()
+
+ def send(
+ self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
+ ):
+ """Sends PreparedRequest object. Returns Response object.
+
+ :param request: The :class:`PreparedRequest ` being sent.
+ :param stream: (optional) Whether to stream the request content.
+ :param timeout: (optional) How long to wait for the server to send
+ data before giving up, as a float, or a :ref:`(connect timeout,
+ read timeout) ` tuple.
+ :type timeout: float or tuple
+ :param verify: (optional) Either a boolean, in which case it controls whether we verify
+ the server's TLS certificate, or a string, in which case it must be a path
+ to a CA bundle to use
+ :param cert: (optional) Any user-provided SSL certificate to be trusted.
+ :param proxies: (optional) The proxies dictionary to apply to the request.
+ """
+ raise NotImplementedError
+
+ def close(self):
+ """Cleans up adapter specific items."""
+ raise NotImplementedError
+
+
+class HTTPAdapter(BaseAdapter):
+ """The built-in HTTP Adapter for urllib3.
+
+ Provides a general-case interface for Requests sessions to contact HTTP and
+ HTTPS urls by implementing the Transport Adapter interface. This class will
+ usually be created by the :class:`Session ` class under the
+ covers.
+
+ :param pool_connections: The number of urllib3 connection pools to cache.
+ :param pool_maxsize: The maximum number of connections to save in the pool.
+ :param max_retries: The maximum number of retries each connection
+ should attempt. Note, this applies only to failed DNS lookups, socket
+ connections and connection timeouts, never to requests where data has
+ made it to the server. By default, Requests does not retry failed
+ connections. If you need granular control over the conditions under
+ which we retry a request, import urllib3's ``Retry`` class and pass
+ that instead.
+ :param pool_block: Whether the connection pool should block for connections.
+
+ Usage::
+
+ >>> import requests
+ >>> s = requests.Session()
+ >>> a = requests.adapters.HTTPAdapter(max_retries=3)
+ >>> s.mount('http://', a)
+ """
+
+ __attrs__ = [
+ "max_retries",
+ "config",
+ "_pool_connections",
+ "_pool_maxsize",
+ "_pool_block",
+ ]
+
+ def __init__(
+ self,
+ pool_connections=DEFAULT_POOLSIZE,
+ pool_maxsize=DEFAULT_POOLSIZE,
+ max_retries=DEFAULT_RETRIES,
+ pool_block=DEFAULT_POOLBLOCK,
+ ):
+ if max_retries == DEFAULT_RETRIES:
+ self.max_retries = Retry(0, read=False)
+ else:
+ self.max_retries = Retry.from_int(max_retries)
+ self.config = {}
+ self.proxy_manager = {}
+
+ super().__init__()
+
+ self._pool_connections = pool_connections
+ self._pool_maxsize = pool_maxsize
+ self._pool_block = pool_block
+
+ self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block)
+
+ def __getstate__(self):
+ return {attr: getattr(self, attr, None) for attr in self.__attrs__}
+
+ def __setstate__(self, state):
+ # Can't handle by adding 'proxy_manager' to self.__attrs__ because
+ # self.poolmanager uses a lambda function, which isn't pickleable.
+ self.proxy_manager = {}
+ self.config = {}
+
+ for attr, value in state.items():
+ setattr(self, attr, value)
+
+ self.init_poolmanager(
+ self._pool_connections, self._pool_maxsize, block=self._pool_block
+ )
+
+ def init_poolmanager(
+ self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs
+ ):
+ """Initializes a urllib3 PoolManager.
+
+ This method should not be called from user code, and is only
+ exposed for use when subclassing the
+ :class:`HTTPAdapter `.
+
+ :param connections: The number of urllib3 connection pools to cache.
+ :param maxsize: The maximum number of connections to save in the pool.
+ :param block: Block when no free connections are available.
+ :param pool_kwargs: Extra keyword arguments used to initialize the Pool Manager.
+ """
+ # save these values for pickling
+ self._pool_connections = connections
+ self._pool_maxsize = maxsize
+ self._pool_block = block
+
+ self.poolmanager = PoolManager(
+ num_pools=connections,
+ maxsize=maxsize,
+ block=block,
+ **pool_kwargs,
+ )
+
+ def proxy_manager_for(self, proxy, **proxy_kwargs):
+ """Return urllib3 ProxyManager for the given proxy.
+
+ This method should not be called from user code, and is only
+ exposed for use when subclassing the
+ :class:`HTTPAdapter `.
+
+ :param proxy: The proxy to return a urllib3 ProxyManager for.
+ :param proxy_kwargs: Extra keyword arguments used to configure the Proxy Manager.
+ :returns: ProxyManager
+ :rtype: urllib3.ProxyManager
+ """
+ if proxy in self.proxy_manager:
+ manager = self.proxy_manager[proxy]
+ elif proxy.lower().startswith("socks"):
+ username, password = get_auth_from_url(proxy)
+ manager = self.proxy_manager[proxy] = SOCKSProxyManager(
+ proxy,
+ username=username,
+ password=password,
+ num_pools=self._pool_connections,
+ maxsize=self._pool_maxsize,
+ block=self._pool_block,
+ **proxy_kwargs,
+ )
+ else:
+ proxy_headers = self.proxy_headers(proxy)
+ manager = self.proxy_manager[proxy] = proxy_from_url(
+ proxy,
+ proxy_headers=proxy_headers,
+ num_pools=self._pool_connections,
+ maxsize=self._pool_maxsize,
+ block=self._pool_block,
+ **proxy_kwargs,
+ )
+
+ return manager
+
+ def cert_verify(self, conn, url, verify, cert):
+ """Verify a SSL certificate. This method should not be called from user
+ code, and is only exposed for use when subclassing the
+ :class:`HTTPAdapter `.
+
+ :param conn: The urllib3 connection object associated with the cert.
+ :param url: The requested URL.
+ :param verify: Either a boolean, in which case it controls whether we verify
+ the server's TLS certificate, or a string, in which case it must be a path
+ to a CA bundle to use
+ :param cert: The SSL certificate to verify.
+ """
+ if url.lower().startswith("https") and verify:
+ conn.cert_reqs = "CERT_REQUIRED"
+
+ # Only load the CA certificates if 'verify' is a string indicating the CA bundle to use.
+ # Otherwise, if verify is a boolean, we don't load anything since
+ # the connection will be using a context with the default certificates already loaded,
+ # and this avoids a call to the slow load_verify_locations()
+ if verify is not True:
+ # `verify` must be a str with a path then
+ cert_loc = verify
+
+ if not os.path.exists(cert_loc):
+ raise OSError(
+ f"Could not find a suitable TLS CA certificate bundle, "
+ f"invalid path: {cert_loc}"
+ )
+
+ if not os.path.isdir(cert_loc):
+ conn.ca_certs = cert_loc
+ else:
+ conn.ca_cert_dir = cert_loc
+ else:
+ conn.cert_reqs = "CERT_NONE"
+ conn.ca_certs = None
+ conn.ca_cert_dir = None
+
+ if cert:
+ if not isinstance(cert, basestring):
+ conn.cert_file = cert[0]
+ conn.key_file = cert[1]
+ else:
+ conn.cert_file = cert
+ conn.key_file = None
+ if conn.cert_file and not os.path.exists(conn.cert_file):
+ raise OSError(
+ f"Could not find the TLS certificate file, "
+ f"invalid path: {conn.cert_file}"
+ )
+ if conn.key_file and not os.path.exists(conn.key_file):
+ raise OSError(
+ f"Could not find the TLS key file, invalid path: {conn.key_file}"
+ )
+
+ def build_response(self, req, resp):
+ """Builds a :class:`Response ` object from a urllib3
+ response. This should not be called from user code, and is only exposed
+ for use when subclassing the
+ :class:`HTTPAdapter `
+
+ :param req: The :class:`PreparedRequest ` used to generate the response.
+ :param resp: The urllib3 response object.
+ :rtype: requests.Response
+ """
+ response = Response()
+
+ # Fallback to None if there's no status_code, for whatever reason.
+ response.status_code = getattr(resp, "status", None)
+
+ # Make headers case-insensitive.
+ response.headers = CaseInsensitiveDict(getattr(resp, "headers", {}))
+
+ # Set encoding.
+ response.encoding = get_encoding_from_headers(response.headers)
+ response.raw = resp
+ response.reason = response.raw.reason
+
+ if isinstance(req.url, bytes):
+ response.url = req.url.decode("utf-8")
+ else:
+ response.url = req.url
+
+ # Add new cookies from the server.
+ extract_cookies_to_jar(response.cookies, req, resp)
+
+ # Give the Response some context.
+ response.request = req
+ response.connection = self
+
+ return response
+
+ def build_connection_pool_key_attributes(self, request, verify, cert=None):
+ """Build the PoolKey attributes used by urllib3 to return a connection.
+
+ This looks at the PreparedRequest, the user-specified verify value,
+ and the value of the cert parameter to determine what PoolKey values
+ to use to select a connection from a given urllib3 Connection Pool.
+
+ The SSL related pool key arguments are not consistently set. As of
+ this writing, use the following to determine what keys may be in that
+ dictionary:
+
+ * If ``verify`` is ``True``, ``"ssl_context"`` will be set and will be the
+ default Requests SSL Context
+ * If ``verify`` is ``False``, ``"ssl_context"`` will not be set but
+ ``"cert_reqs"`` will be set
+ * If ``verify`` is a string, (i.e., it is a user-specified trust bundle)
+ ``"ca_certs"`` will be set if the string is not a directory recognized
+ by :py:func:`os.path.isdir`, otherwise ``"ca_certs_dir"`` will be
+ set.
+ * If ``"cert"`` is specified, ``"cert_file"`` will always be set. If
+ ``"cert"`` is a tuple with a second item, ``"key_file"`` will also
+ be present
+
+ To override these settings, one may subclass this class, call this
+ method and use the above logic to change parameters as desired. For
+ example, if one wishes to use a custom :py:class:`ssl.SSLContext` one
+ must both set ``"ssl_context"`` and based on what else they require,
+ alter the other keys to ensure the desired behaviour.
+
+ :param request:
+ The PreparedReqest being sent over the connection.
+ :type request:
+ :class:`~requests.models.PreparedRequest`
+ :param verify:
+ Either a boolean, in which case it controls whether
+ we verify the server's TLS certificate, or a string, in which case it
+ must be a path to a CA bundle to use.
+ :param cert:
+ (optional) Any user-provided SSL certificate for client
+ authentication (a.k.a., mTLS). This may be a string (i.e., just
+ the path to a file which holds both certificate and key) or a
+ tuple of length 2 with the certificate file path and key file
+ path.
+ :returns:
+ A tuple of two dictionaries. The first is the "host parameters"
+ portion of the Pool Key including scheme, hostname, and port. The
+ second is a dictionary of SSLContext related parameters.
+ """
+ return _urllib3_request_context(request, verify, cert, self.poolmanager)
+
+ def get_connection_with_tls_context(self, request, verify, proxies=None, cert=None):
+ """Returns a urllib3 connection for the given request and TLS settings.
+ This should not be called from user code, and is only exposed for use
+ when subclassing the :class:`HTTPAdapter `.
+
+ :param request:
+ The :class:`PreparedRequest ` object to be sent
+ over the connection.
+ :param verify:
+ Either a boolean, in which case it controls whether we verify the
+ server's TLS certificate, or a string, in which case it must be a
+ path to a CA bundle to use.
+ :param proxies:
+ (optional) The proxies dictionary to apply to the request.
+ :param cert:
+ (optional) Any user-provided SSL certificate to be used for client
+ authentication (a.k.a., mTLS).
+ :rtype:
+ urllib3.ConnectionPool
+ """
+ proxy = select_proxy(request.url, proxies)
+ try:
+ host_params, pool_kwargs = self.build_connection_pool_key_attributes(
+ request,
+ verify,
+ cert,
+ )
+ except ValueError as e:
+ raise InvalidURL(e, request=request)
+ if proxy:
+ proxy = prepend_scheme_if_needed(proxy, "http")
+ proxy_url = parse_url(proxy)
+ if not proxy_url.host:
+ raise InvalidProxyURL(
+ "Please check proxy URL. It is malformed "
+ "and could be missing the host."
+ )
+ proxy_manager = self.proxy_manager_for(proxy)
+ conn = proxy_manager.connection_from_host(
+ **host_params, pool_kwargs=pool_kwargs
+ )
+ else:
+ # Only scheme should be lower case
+ conn = self.poolmanager.connection_from_host(
+ **host_params, pool_kwargs=pool_kwargs
+ )
+
+ return conn
+
+ def get_connection(self, url, proxies=None):
+ """DEPRECATED: Users should move to `get_connection_with_tls_context`
+ for all subclasses of HTTPAdapter using Requests>=2.32.2.
+
+ Returns a urllib3 connection for the given URL. This should not be
+ called from user code, and is only exposed for use when subclassing the
+ :class:`HTTPAdapter `.
+
+ :param url: The URL to connect to.
+ :param proxies: (optional) A Requests-style dictionary of proxies used on this request.
+ :rtype: urllib3.ConnectionPool
+ """
+ warnings.warn(
+ (
+ "`get_connection` has been deprecated in favor of "
+ "`get_connection_with_tls_context`. Custom HTTPAdapter subclasses "
+ "will need to migrate for Requests>=2.32.2. Please see "
+ "https://github.com/psf/requests/pull/6710 for more details."
+ ),
+ DeprecationWarning,
+ )
+ proxy = select_proxy(url, proxies)
+
+ if proxy:
+ proxy = prepend_scheme_if_needed(proxy, "http")
+ proxy_url = parse_url(proxy)
+ if not proxy_url.host:
+ raise InvalidProxyURL(
+ "Please check proxy URL. It is malformed "
+ "and could be missing the host."
+ )
+ proxy_manager = self.proxy_manager_for(proxy)
+ conn = proxy_manager.connection_from_url(url)
+ else:
+ # Only scheme should be lower case
+ parsed = urlparse(url)
+ url = parsed.geturl()
+ conn = self.poolmanager.connection_from_url(url)
+
+ return conn
+
+ def close(self):
+ """Disposes of any internal state.
+
+ Currently, this closes the PoolManager and any active ProxyManager,
+ which closes any pooled connections.
+ """
+ self.poolmanager.clear()
+ for proxy in self.proxy_manager.values():
+ proxy.clear()
+
+ def request_url(self, request, proxies):
+ """Obtain the url to use when making the final request.
+
+ If the message is being sent through a HTTP proxy, the full URL has to
+ be used. Otherwise, we should only use the path portion of the URL.
+
+ This should not be called from user code, and is only exposed for use
+ when subclassing the
+ :class:`HTTPAdapter `.
+
+ :param request: The :class:`PreparedRequest ` being sent.
+ :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs.
+ :rtype: str
+ """
+ proxy = select_proxy(request.url, proxies)
+ scheme = urlparse(request.url).scheme
+
+ is_proxied_http_request = proxy and scheme != "https"
+ using_socks_proxy = False
+ if proxy:
+ proxy_scheme = urlparse(proxy).scheme.lower()
+ using_socks_proxy = proxy_scheme.startswith("socks")
+
+ url = request.path_url
+ if url.startswith("//"): # Don't confuse urllib3
+ url = f"/{url.lstrip('/')}"
+
+ if is_proxied_http_request and not using_socks_proxy:
+ url = urldefragauth(request.url)
+
+ return url
+
+ def add_headers(self, request, **kwargs):
+ """Add any headers needed by the connection. As of v2.0 this does
+ nothing by default, but is left for overriding by users that subclass
+ the :class:`HTTPAdapter `.
+
+ This should not be called from user code, and is only exposed for use
+ when subclassing the
+ :class:`HTTPAdapter `.
+
+ :param request: The :class:`PreparedRequest ` to add headers to.
+ :param kwargs: The keyword arguments from the call to send().
+ """
+ pass
+
+ def proxy_headers(self, proxy):
+ """Returns a dictionary of the headers to add to any request sent
+ through a proxy. This works with urllib3 magic to ensure that they are
+ correctly sent to the proxy, rather than in a tunnelled request if
+ CONNECT is being used.
+
+ This should not be called from user code, and is only exposed for use
+ when subclassing the
+ :class:`HTTPAdapter `.
+
+ :param proxy: The url of the proxy being used for this request.
+ :rtype: dict
+ """
+ headers = {}
+ username, password = get_auth_from_url(proxy)
+
+ if username:
+ headers["Proxy-Authorization"] = _basic_auth_str(username, password)
+
+ return headers
+
+ def send(
+ self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
+ ):
+ """Sends PreparedRequest object. Returns Response object.
+
+ :param request: The :class:`PreparedRequest ` being sent.
+ :param stream: (optional) Whether to stream the request content.
+ :param timeout: (optional) How long to wait for the server to send
+ data before giving up, as a float, or a :ref:`(connect timeout,
+ read timeout) ` tuple.
+ :type timeout: float or tuple or urllib3 Timeout object
+ :param verify: (optional) Either a boolean, in which case it controls whether
+ we verify the server's TLS certificate, or a string, in which case it
+ must be a path to a CA bundle to use
+ :param cert: (optional) Any user-provided SSL certificate to be trusted.
+ :param proxies: (optional) The proxies dictionary to apply to the request.
+ :rtype: requests.Response
+ """
+
+ try:
+ conn = self.get_connection_with_tls_context(
+ request, verify, proxies=proxies, cert=cert
+ )
+ except LocationValueError as e:
+ raise InvalidURL(e, request=request)
+
+ self.cert_verify(conn, request.url, verify, cert)
+ url = self.request_url(request, proxies)
+ self.add_headers(
+ request,
+ stream=stream,
+ timeout=timeout,
+ verify=verify,
+ cert=cert,
+ proxies=proxies,
+ )
+
+ chunked = not (request.body is None or "Content-Length" in request.headers)
+
+ if isinstance(timeout, tuple):
+ try:
+ connect, read = timeout
+ timeout = TimeoutSauce(connect=connect, read=read)
+ except ValueError:
+ raise ValueError(
+ f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
+ f"or a single float to set both timeouts to the same value."
+ )
+ elif isinstance(timeout, TimeoutSauce):
+ pass
+ else:
+ timeout = TimeoutSauce(connect=timeout, read=timeout)
+
+ try:
+ resp = conn.urlopen(
+ method=request.method,
+ url=url,
+ body=request.body,
+ headers=request.headers,
+ redirect=False,
+ assert_same_host=False,
+ preload_content=False,
+ decode_content=False,
+ retries=self.max_retries,
+ timeout=timeout,
+ chunked=chunked,
+ )
+
+ except (ProtocolError, OSError) as err:
+ raise ConnectionError(err, request=request)
+
+ except MaxRetryError as e:
+ if isinstance(e.reason, ConnectTimeoutError):
+ # TODO: Remove this in 3.0.0: see #2811
+ if not isinstance(e.reason, NewConnectionError):
+ raise ConnectTimeout(e, request=request)
+
+ if isinstance(e.reason, ResponseError):
+ raise RetryError(e, request=request)
+
+ if isinstance(e.reason, _ProxyError):
+ raise ProxyError(e, request=request)
+
+ if isinstance(e.reason, _SSLError):
+ # This branch is for urllib3 v1.22 and later.
+ raise SSLError(e, request=request)
+
+ raise ConnectionError(e, request=request)
+
+ except ClosedPoolError as e:
+ raise ConnectionError(e, request=request)
+
+ except _ProxyError as e:
+ raise ProxyError(e)
+
+ except (_SSLError, _HTTPError) as e:
+ if isinstance(e, _SSLError):
+ # This branch is for urllib3 versions earlier than v1.22
+ raise SSLError(e, request=request)
+ elif isinstance(e, ReadTimeoutError):
+ raise ReadTimeout(e, request=request)
+ elif isinstance(e, _InvalidHeader):
+ raise InvalidHeader(e, request=request)
+ else:
+ raise
+
+ return self.build_response(request, resp)
diff --git a/testcline/lib/python3.12/site-packages/requests/api.py b/testcline/lib/python3.12/site-packages/requests/api.py
new file mode 100644
index 0000000..5960744
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/api.py
@@ -0,0 +1,157 @@
+"""
+requests.api
+~~~~~~~~~~~~
+
+This module implements the Requests API.
+
+:copyright: (c) 2012 by Kenneth Reitz.
+:license: Apache2, see LICENSE for more details.
+"""
+
+from . import sessions
+
+
+def request(method, url, **kwargs):
+ """Constructs and sends a :class:`Request `.
+
+ :param method: method for the new :class:`Request` object: ``GET``, ``OPTIONS``, ``HEAD``, ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
+ :param url: URL for the new :class:`Request` object.
+ :param params: (optional) Dictionary, list of tuples or bytes to send
+ in the query string for the :class:`Request`.
+ :param data: (optional) Dictionary, list of tuples, bytes, or file-like
+ object to send in the body of the :class:`Request`.
+ :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
+ :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
+ :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
+ :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.
+ ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``
+ or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content_type'`` is a string
+ defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers
+ to add for the file.
+ :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
+ :param timeout: (optional) How many seconds to wait for the server to send data
+ before giving up, as a float, or a :ref:`(connect timeout, read
+ timeout) ` tuple.
+ :type timeout: float or tuple
+ :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.
+ :type allow_redirects: bool
+ :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
+ :param verify: (optional) Either a boolean, in which case it controls whether we verify
+ the server's TLS certificate, or a string, in which case it must be a path
+ to a CA bundle to use. Defaults to ``True``.
+ :param stream: (optional) if ``False``, the response content will be immediately downloaded.
+ :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
+ :return: :class:`Response ` object
+ :rtype: requests.Response
+
+ Usage::
+
+ >>> import requests
+ >>> req = requests.request('GET', 'https://httpbin.org/get')
+ >>> req
+
+ """
+
+ # By using the 'with' statement we are sure the session is closed, thus we
+ # avoid leaving sockets open which can trigger a ResourceWarning in some
+ # cases, and look like a memory leak in others.
+ with sessions.Session() as session:
+ return session.request(method=method, url=url, **kwargs)
+
+
+def get(url, params=None, **kwargs):
+ r"""Sends a GET request.
+
+ :param url: URL for the new :class:`Request` object.
+ :param params: (optional) Dictionary, list of tuples or bytes to send
+ in the query string for the :class:`Request`.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :return: :class:`Response ` object
+ :rtype: requests.Response
+ """
+
+ return request("get", url, params=params, **kwargs)
+
+
+def options(url, **kwargs):
+ r"""Sends an OPTIONS request.
+
+ :param url: URL for the new :class:`Request` object.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :return: :class:`Response ` object
+ :rtype: requests.Response
+ """
+
+ return request("options", url, **kwargs)
+
+
+def head(url, **kwargs):
+ r"""Sends a HEAD request.
+
+ :param url: URL for the new :class:`Request` object.
+ :param \*\*kwargs: Optional arguments that ``request`` takes. If
+ `allow_redirects` is not provided, it will be set to `False` (as
+ opposed to the default :meth:`request` behavior).
+ :return: :class:`Response ` object
+ :rtype: requests.Response
+ """
+
+ kwargs.setdefault("allow_redirects", False)
+ return request("head", url, **kwargs)
+
+
+def post(url, data=None, json=None, **kwargs):
+ r"""Sends a POST request.
+
+ :param url: URL for the new :class:`Request` object.
+ :param data: (optional) Dictionary, list of tuples, bytes, or file-like
+ object to send in the body of the :class:`Request`.
+ :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :return: :class:`Response ` object
+ :rtype: requests.Response
+ """
+
+ return request("post", url, data=data, json=json, **kwargs)
+
+
+def put(url, data=None, **kwargs):
+ r"""Sends a PUT request.
+
+ :param url: URL for the new :class:`Request` object.
+ :param data: (optional) Dictionary, list of tuples, bytes, or file-like
+ object to send in the body of the :class:`Request`.
+ :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :return: :class:`Response ` object
+ :rtype: requests.Response
+ """
+
+ return request("put", url, data=data, **kwargs)
+
+
+def patch(url, data=None, **kwargs):
+ r"""Sends a PATCH request.
+
+ :param url: URL for the new :class:`Request` object.
+ :param data: (optional) Dictionary, list of tuples, bytes, or file-like
+ object to send in the body of the :class:`Request`.
+ :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :return: :class:`Response ` object
+ :rtype: requests.Response
+ """
+
+ return request("patch", url, data=data, **kwargs)
+
+
+def delete(url, **kwargs):
+ r"""Sends a DELETE request.
+
+ :param url: URL for the new :class:`Request` object.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :return: :class:`Response ` object
+ :rtype: requests.Response
+ """
+
+ return request("delete", url, **kwargs)
diff --git a/testcline/lib/python3.12/site-packages/requests/auth.py b/testcline/lib/python3.12/site-packages/requests/auth.py
new file mode 100644
index 0000000..4a7ce6d
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/auth.py
@@ -0,0 +1,314 @@
+"""
+requests.auth
+~~~~~~~~~~~~~
+
+This module contains the authentication handlers for Requests.
+"""
+
+import hashlib
+import os
+import re
+import threading
+import time
+import warnings
+from base64 import b64encode
+
+from ._internal_utils import to_native_string
+from .compat import basestring, str, urlparse
+from .cookies import extract_cookies_to_jar
+from .utils import parse_dict_header
+
+CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded"
+CONTENT_TYPE_MULTI_PART = "multipart/form-data"
+
+
+def _basic_auth_str(username, password):
+ """Returns a Basic Auth string."""
+
+ # "I want us to put a big-ol' comment on top of it that
+ # says that this behaviour is dumb but we need to preserve
+ # it because people are relying on it."
+ # - Lukasa
+ #
+ # These are here solely to maintain backwards compatibility
+ # for things like ints. This will be removed in 3.0.0.
+ if not isinstance(username, basestring):
+ warnings.warn(
+ "Non-string usernames will no longer be supported in Requests "
+ "3.0.0. Please convert the object you've passed in ({!r}) to "
+ "a string or bytes object in the near future to avoid "
+ "problems.".format(username),
+ category=DeprecationWarning,
+ )
+ username = str(username)
+
+ if not isinstance(password, basestring):
+ warnings.warn(
+ "Non-string passwords will no longer be supported in Requests "
+ "3.0.0. Please convert the object you've passed in ({!r}) to "
+ "a string or bytes object in the near future to avoid "
+ "problems.".format(type(password)),
+ category=DeprecationWarning,
+ )
+ password = str(password)
+ # -- End Removal --
+
+ if isinstance(username, str):
+ username = username.encode("latin1")
+
+ if isinstance(password, str):
+ password = password.encode("latin1")
+
+ authstr = "Basic " + to_native_string(
+ b64encode(b":".join((username, password))).strip()
+ )
+
+ return authstr
+
+
+class AuthBase:
+ """Base class that all auth implementations derive from"""
+
+ def __call__(self, r):
+ raise NotImplementedError("Auth hooks must be callable.")
+
+
+class HTTPBasicAuth(AuthBase):
+ """Attaches HTTP Basic Authentication to the given Request object."""
+
+ def __init__(self, username, password):
+ self.username = username
+ self.password = password
+
+ def __eq__(self, other):
+ return all(
+ [
+ self.username == getattr(other, "username", None),
+ self.password == getattr(other, "password", None),
+ ]
+ )
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __call__(self, r):
+ r.headers["Authorization"] = _basic_auth_str(self.username, self.password)
+ return r
+
+
+class HTTPProxyAuth(HTTPBasicAuth):
+ """Attaches HTTP Proxy Authentication to a given Request object."""
+
+ def __call__(self, r):
+ r.headers["Proxy-Authorization"] = _basic_auth_str(self.username, self.password)
+ return r
+
+
+class HTTPDigestAuth(AuthBase):
+ """Attaches HTTP Digest Authentication to the given Request object."""
+
+ def __init__(self, username, password):
+ self.username = username
+ self.password = password
+ # Keep state in per-thread local storage
+ self._thread_local = threading.local()
+
+ def init_per_thread_state(self):
+ # Ensure state is initialized just once per-thread
+ if not hasattr(self._thread_local, "init"):
+ self._thread_local.init = True
+ self._thread_local.last_nonce = ""
+ self._thread_local.nonce_count = 0
+ self._thread_local.chal = {}
+ self._thread_local.pos = None
+ self._thread_local.num_401_calls = None
+
+ def build_digest_header(self, method, url):
+ """
+ :rtype: str
+ """
+
+ realm = self._thread_local.chal["realm"]
+ nonce = self._thread_local.chal["nonce"]
+ qop = self._thread_local.chal.get("qop")
+ algorithm = self._thread_local.chal.get("algorithm")
+ opaque = self._thread_local.chal.get("opaque")
+ hash_utf8 = None
+
+ if algorithm is None:
+ _algorithm = "MD5"
+ else:
+ _algorithm = algorithm.upper()
+ # lambdas assume digest modules are imported at the top level
+ if _algorithm == "MD5" or _algorithm == "MD5-SESS":
+
+ def md5_utf8(x):
+ if isinstance(x, str):
+ x = x.encode("utf-8")
+ return hashlib.md5(x).hexdigest()
+
+ hash_utf8 = md5_utf8
+ elif _algorithm == "SHA":
+
+ def sha_utf8(x):
+ if isinstance(x, str):
+ x = x.encode("utf-8")
+ return hashlib.sha1(x).hexdigest()
+
+ hash_utf8 = sha_utf8
+ elif _algorithm == "SHA-256":
+
+ def sha256_utf8(x):
+ if isinstance(x, str):
+ x = x.encode("utf-8")
+ return hashlib.sha256(x).hexdigest()
+
+ hash_utf8 = sha256_utf8
+ elif _algorithm == "SHA-512":
+
+ def sha512_utf8(x):
+ if isinstance(x, str):
+ x = x.encode("utf-8")
+ return hashlib.sha512(x).hexdigest()
+
+ hash_utf8 = sha512_utf8
+
+ KD = lambda s, d: hash_utf8(f"{s}:{d}") # noqa:E731
+
+ if hash_utf8 is None:
+ return None
+
+ # XXX not implemented yet
+ entdig = None
+ p_parsed = urlparse(url)
+ #: path is request-uri defined in RFC 2616 which should not be empty
+ path = p_parsed.path or "/"
+ if p_parsed.query:
+ path += f"?{p_parsed.query}"
+
+ A1 = f"{self.username}:{realm}:{self.password}"
+ A2 = f"{method}:{path}"
+
+ HA1 = hash_utf8(A1)
+ HA2 = hash_utf8(A2)
+
+ if nonce == self._thread_local.last_nonce:
+ self._thread_local.nonce_count += 1
+ else:
+ self._thread_local.nonce_count = 1
+ ncvalue = f"{self._thread_local.nonce_count:08x}"
+ s = str(self._thread_local.nonce_count).encode("utf-8")
+ s += nonce.encode("utf-8")
+ s += time.ctime().encode("utf-8")
+ s += os.urandom(8)
+
+ cnonce = hashlib.sha1(s).hexdigest()[:16]
+ if _algorithm == "MD5-SESS":
+ HA1 = hash_utf8(f"{HA1}:{nonce}:{cnonce}")
+
+ if not qop:
+ respdig = KD(HA1, f"{nonce}:{HA2}")
+ elif qop == "auth" or "auth" in qop.split(","):
+ noncebit = f"{nonce}:{ncvalue}:{cnonce}:auth:{HA2}"
+ respdig = KD(HA1, noncebit)
+ else:
+ # XXX handle auth-int.
+ return None
+
+ self._thread_local.last_nonce = nonce
+
+ # XXX should the partial digests be encoded too?
+ base = (
+ f'username="{self.username}", realm="{realm}", nonce="{nonce}", '
+ f'uri="{path}", response="{respdig}"'
+ )
+ if opaque:
+ base += f', opaque="{opaque}"'
+ if algorithm:
+ base += f', algorithm="{algorithm}"'
+ if entdig:
+ base += f', digest="{entdig}"'
+ if qop:
+ base += f', qop="auth", nc={ncvalue}, cnonce="{cnonce}"'
+
+ return f"Digest {base}"
+
+ def handle_redirect(self, r, **kwargs):
+ """Reset num_401_calls counter on redirects."""
+ if r.is_redirect:
+ self._thread_local.num_401_calls = 1
+
+ def handle_401(self, r, **kwargs):
+ """
+ Takes the given response and tries digest-auth, if needed.
+
+ :rtype: requests.Response
+ """
+
+ # If response is not 4xx, do not auth
+ # See https://github.com/psf/requests/issues/3772
+ if not 400 <= r.status_code < 500:
+ self._thread_local.num_401_calls = 1
+ return r
+
+ if self._thread_local.pos is not None:
+ # Rewind the file position indicator of the body to where
+ # it was to resend the request.
+ r.request.body.seek(self._thread_local.pos)
+ s_auth = r.headers.get("www-authenticate", "")
+
+ if "digest" in s_auth.lower() and self._thread_local.num_401_calls < 2:
+ self._thread_local.num_401_calls += 1
+ pat = re.compile(r"digest ", flags=re.IGNORECASE)
+ self._thread_local.chal = parse_dict_header(pat.sub("", s_auth, count=1))
+
+ # Consume content and release the original connection
+ # to allow our new request to reuse the same one.
+ r.content
+ r.close()
+ prep = r.request.copy()
+ extract_cookies_to_jar(prep._cookies, r.request, r.raw)
+ prep.prepare_cookies(prep._cookies)
+
+ prep.headers["Authorization"] = self.build_digest_header(
+ prep.method, prep.url
+ )
+ _r = r.connection.send(prep, **kwargs)
+ _r.history.append(r)
+ _r.request = prep
+
+ return _r
+
+ self._thread_local.num_401_calls = 1
+ return r
+
+ def __call__(self, r):
+ # Initialize per-thread state, if needed
+ self.init_per_thread_state()
+ # If we have a saved nonce, skip the 401
+ if self._thread_local.last_nonce:
+ r.headers["Authorization"] = self.build_digest_header(r.method, r.url)
+ try:
+ self._thread_local.pos = r.body.tell()
+ except AttributeError:
+ # In the case of HTTPDigestAuth being reused and the body of
+ # the previous request was a file-like object, pos has the
+ # file position of the previous body. Ensure it's set to
+ # None.
+ self._thread_local.pos = None
+ r.register_hook("response", self.handle_401)
+ r.register_hook("response", self.handle_redirect)
+ self._thread_local.num_401_calls = 1
+
+ return r
+
+ def __eq__(self, other):
+ return all(
+ [
+ self.username == getattr(other, "username", None),
+ self.password == getattr(other, "password", None),
+ ]
+ )
+
+ def __ne__(self, other):
+ return not self == other
diff --git a/testcline/lib/python3.12/site-packages/requests/certs.py b/testcline/lib/python3.12/site-packages/requests/certs.py
new file mode 100644
index 0000000..be422c3
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/certs.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+"""
+requests.certs
+~~~~~~~~~~~~~~
+
+This module returns the preferred default CA certificate bundle. There is
+only one — the one from the certifi package.
+
+If you are packaging Requests, e.g., for a Linux distribution or a managed
+environment, you can change the definition of where() to return a separately
+packaged CA bundle.
+"""
+from certifi import where
+
+if __name__ == "__main__":
+ print(where())
diff --git a/testcline/lib/python3.12/site-packages/requests/compat.py b/testcline/lib/python3.12/site-packages/requests/compat.py
new file mode 100644
index 0000000..095de1b
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/compat.py
@@ -0,0 +1,94 @@
+"""
+requests.compat
+~~~~~~~~~~~~~~~
+
+This module previously handled import compatibility issues
+between Python 2 and Python 3. It remains for backwards
+compatibility until the next major version.
+"""
+
+import importlib
+import sys
+
+# -------------------
+# Character Detection
+# -------------------
+
+
+def _resolve_char_detection():
+ """Find supported character detection libraries."""
+ chardet = None
+ for lib in ("chardet", "charset_normalizer"):
+ if chardet is None:
+ try:
+ chardet = importlib.import_module(lib)
+ except ImportError:
+ pass
+ return chardet
+
+
+chardet = _resolve_char_detection()
+
+# -------
+# Pythons
+# -------
+
+# Syntax sugar.
+_ver = sys.version_info
+
+#: Python 2.x?
+is_py2 = _ver[0] == 2
+
+#: Python 3.x?
+is_py3 = _ver[0] == 3
+
+# json/simplejson module import resolution
+has_simplejson = False
+try:
+ import simplejson as json
+
+ has_simplejson = True
+except ImportError:
+ import json
+
+if has_simplejson:
+ from simplejson import JSONDecodeError
+else:
+ from json import JSONDecodeError
+
+# Keep OrderedDict for backwards compatibility.
+from collections import OrderedDict
+from collections.abc import Callable, Mapping, MutableMapping
+from http import cookiejar as cookielib
+from http.cookies import Morsel
+from io import StringIO
+
+# --------------
+# Legacy Imports
+# --------------
+from urllib.parse import (
+ quote,
+ quote_plus,
+ unquote,
+ unquote_plus,
+ urldefrag,
+ urlencode,
+ urljoin,
+ urlparse,
+ urlsplit,
+ urlunparse,
+)
+from urllib.request import (
+ getproxies,
+ getproxies_environment,
+ parse_http_list,
+ proxy_bypass,
+ proxy_bypass_environment,
+)
+
+builtin_str = str
+str = str
+bytes = bytes
+basestring = (str, bytes)
+numeric_types = (int, float)
+integer_types = (int,)
diff --git a/testcline/lib/python3.12/site-packages/requests/cookies.py b/testcline/lib/python3.12/site-packages/requests/cookies.py
new file mode 100644
index 0000000..f69d0cd
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/cookies.py
@@ -0,0 +1,561 @@
+"""
+requests.cookies
+~~~~~~~~~~~~~~~~
+
+Compatibility code to be able to use `http.cookiejar.CookieJar` with requests.
+
+requests.utils imports from here, so be careful with imports.
+"""
+
+import calendar
+import copy
+import time
+
+from ._internal_utils import to_native_string
+from .compat import Morsel, MutableMapping, cookielib, urlparse, urlunparse
+
+try:
+ import threading
+except ImportError:
+ import dummy_threading as threading
+
+
+class MockRequest:
+ """Wraps a `requests.Request` to mimic a `urllib2.Request`.
+
+ The code in `http.cookiejar.CookieJar` expects this interface in order to correctly
+ manage cookie policies, i.e., determine whether a cookie can be set, given the
+ domains of the request and the cookie.
+
+ The original request object is read-only. The client is responsible for collecting
+ the new headers via `get_new_headers()` and interpreting them appropriately. You
+ probably want `get_cookie_header`, defined below.
+ """
+
+ def __init__(self, request):
+ self._r = request
+ self._new_headers = {}
+ self.type = urlparse(self._r.url).scheme
+
+ def get_type(self):
+ return self.type
+
+ def get_host(self):
+ return urlparse(self._r.url).netloc
+
+ def get_origin_req_host(self):
+ return self.get_host()
+
+ def get_full_url(self):
+ # Only return the response's URL if the user hadn't set the Host
+ # header
+ if not self._r.headers.get("Host"):
+ return self._r.url
+ # If they did set it, retrieve it and reconstruct the expected domain
+ host = to_native_string(self._r.headers["Host"], encoding="utf-8")
+ parsed = urlparse(self._r.url)
+ # Reconstruct the URL as we expect it
+ return urlunparse(
+ [
+ parsed.scheme,
+ host,
+ parsed.path,
+ parsed.params,
+ parsed.query,
+ parsed.fragment,
+ ]
+ )
+
+ def is_unverifiable(self):
+ return True
+
+ def has_header(self, name):
+ return name in self._r.headers or name in self._new_headers
+
+ def get_header(self, name, default=None):
+ return self._r.headers.get(name, self._new_headers.get(name, default))
+
+ def add_header(self, key, val):
+ """cookiejar has no legitimate use for this method; add it back if you find one."""
+ raise NotImplementedError(
+ "Cookie headers should be added with add_unredirected_header()"
+ )
+
+ def add_unredirected_header(self, name, value):
+ self._new_headers[name] = value
+
+ def get_new_headers(self):
+ return self._new_headers
+
+ @property
+ def unverifiable(self):
+ return self.is_unverifiable()
+
+ @property
+ def origin_req_host(self):
+ return self.get_origin_req_host()
+
+ @property
+ def host(self):
+ return self.get_host()
+
+
+class MockResponse:
+ """Wraps a `httplib.HTTPMessage` to mimic a `urllib.addinfourl`.
+
+ ...what? Basically, expose the parsed HTTP headers from the server response
+ the way `http.cookiejar` expects to see them.
+ """
+
+ def __init__(self, headers):
+ """Make a MockResponse for `cookiejar` to read.
+
+ :param headers: a httplib.HTTPMessage or analogous carrying the headers
+ """
+ self._headers = headers
+
+ def info(self):
+ return self._headers
+
+ def getheaders(self, name):
+ self._headers.getheaders(name)
+
+
+def extract_cookies_to_jar(jar, request, response):
+ """Extract the cookies from the response into a CookieJar.
+
+ :param jar: http.cookiejar.CookieJar (not necessarily a RequestsCookieJar)
+ :param request: our own requests.Request object
+ :param response: urllib3.HTTPResponse object
+ """
+ if not (hasattr(response, "_original_response") and response._original_response):
+ return
+ # the _original_response field is the wrapped httplib.HTTPResponse object,
+ req = MockRequest(request)
+ # pull out the HTTPMessage with the headers and put it in the mock:
+ res = MockResponse(response._original_response.msg)
+ jar.extract_cookies(res, req)
+
+
+def get_cookie_header(jar, request):
+ """
+ Produce an appropriate Cookie header string to be sent with `request`, or None.
+
+ :rtype: str
+ """
+ r = MockRequest(request)
+ jar.add_cookie_header(r)
+ return r.get_new_headers().get("Cookie")
+
+
+def remove_cookie_by_name(cookiejar, name, domain=None, path=None):
+ """Unsets a cookie by name, by default over all domains and paths.
+
+ Wraps CookieJar.clear(), is O(n).
+ """
+ clearables = []
+ for cookie in cookiejar:
+ if cookie.name != name:
+ continue
+ if domain is not None and domain != cookie.domain:
+ continue
+ if path is not None and path != cookie.path:
+ continue
+ clearables.append((cookie.domain, cookie.path, cookie.name))
+
+ for domain, path, name in clearables:
+ cookiejar.clear(domain, path, name)
+
+
+class CookieConflictError(RuntimeError):
+ """There are two cookies that meet the criteria specified in the cookie jar.
+ Use .get and .set and include domain and path args in order to be more specific.
+ """
+
+
+class RequestsCookieJar(cookielib.CookieJar, MutableMapping):
+ """Compatibility class; is a http.cookiejar.CookieJar, but exposes a dict
+ interface.
+
+ This is the CookieJar we create by default for requests and sessions that
+ don't specify one, since some clients may expect response.cookies and
+ session.cookies to support dict operations.
+
+ Requests does not use the dict interface internally; it's just for
+ compatibility with external client code. All requests code should work
+ out of the box with externally provided instances of ``CookieJar``, e.g.
+ ``LWPCookieJar`` and ``FileCookieJar``.
+
+ Unlike a regular CookieJar, this class is pickleable.
+
+ .. warning:: dictionary operations that are normally O(1) may be O(n).
+ """
+
+ def get(self, name, default=None, domain=None, path=None):
+ """Dict-like get() that also supports optional domain and path args in
+ order to resolve naming collisions from using one cookie jar over
+ multiple domains.
+
+ .. warning:: operation is O(n), not O(1).
+ """
+ try:
+ return self._find_no_duplicates(name, domain, path)
+ except KeyError:
+ return default
+
+ def set(self, name, value, **kwargs):
+ """Dict-like set() that also supports optional domain and path args in
+ order to resolve naming collisions from using one cookie jar over
+ multiple domains.
+ """
+ # support client code that unsets cookies by assignment of a None value:
+ if value is None:
+ remove_cookie_by_name(
+ self, name, domain=kwargs.get("domain"), path=kwargs.get("path")
+ )
+ return
+
+ if isinstance(value, Morsel):
+ c = morsel_to_cookie(value)
+ else:
+ c = create_cookie(name, value, **kwargs)
+ self.set_cookie(c)
+ return c
+
+ def iterkeys(self):
+ """Dict-like iterkeys() that returns an iterator of names of cookies
+ from the jar.
+
+ .. seealso:: itervalues() and iteritems().
+ """
+ for cookie in iter(self):
+ yield cookie.name
+
+ def keys(self):
+ """Dict-like keys() that returns a list of names of cookies from the
+ jar.
+
+ .. seealso:: values() and items().
+ """
+ return list(self.iterkeys())
+
+ def itervalues(self):
+ """Dict-like itervalues() that returns an iterator of values of cookies
+ from the jar.
+
+ .. seealso:: iterkeys() and iteritems().
+ """
+ for cookie in iter(self):
+ yield cookie.value
+
+ def values(self):
+ """Dict-like values() that returns a list of values of cookies from the
+ jar.
+
+ .. seealso:: keys() and items().
+ """
+ return list(self.itervalues())
+
+ def iteritems(self):
+ """Dict-like iteritems() that returns an iterator of name-value tuples
+ from the jar.
+
+ .. seealso:: iterkeys() and itervalues().
+ """
+ for cookie in iter(self):
+ yield cookie.name, cookie.value
+
+ def items(self):
+ """Dict-like items() that returns a list of name-value tuples from the
+ jar. Allows client-code to call ``dict(RequestsCookieJar)`` and get a
+ vanilla python dict of key value pairs.
+
+ .. seealso:: keys() and values().
+ """
+ return list(self.iteritems())
+
+ def list_domains(self):
+ """Utility method to list all the domains in the jar."""
+ domains = []
+ for cookie in iter(self):
+ if cookie.domain not in domains:
+ domains.append(cookie.domain)
+ return domains
+
+ def list_paths(self):
+ """Utility method to list all the paths in the jar."""
+ paths = []
+ for cookie in iter(self):
+ if cookie.path not in paths:
+ paths.append(cookie.path)
+ return paths
+
+ def multiple_domains(self):
+ """Returns True if there are multiple domains in the jar.
+ Returns False otherwise.
+
+ :rtype: bool
+ """
+ domains = []
+ for cookie in iter(self):
+ if cookie.domain is not None and cookie.domain in domains:
+ return True
+ domains.append(cookie.domain)
+ return False # there is only one domain in jar
+
+ def get_dict(self, domain=None, path=None):
+ """Takes as an argument an optional domain and path and returns a plain
+ old Python dict of name-value pairs of cookies that meet the
+ requirements.
+
+ :rtype: dict
+ """
+ dictionary = {}
+ for cookie in iter(self):
+ if (domain is None or cookie.domain == domain) and (
+ path is None or cookie.path == path
+ ):
+ dictionary[cookie.name] = cookie.value
+ return dictionary
+
+ def __contains__(self, name):
+ try:
+ return super().__contains__(name)
+ except CookieConflictError:
+ return True
+
+ def __getitem__(self, name):
+ """Dict-like __getitem__() for compatibility with client code. Throws
+ exception if there are more than one cookie with name. In that case,
+ use the more explicit get() method instead.
+
+ .. warning:: operation is O(n), not O(1).
+ """
+ return self._find_no_duplicates(name)
+
+ def __setitem__(self, name, value):
+ """Dict-like __setitem__ for compatibility with client code. Throws
+ exception if there is already a cookie of that name in the jar. In that
+ case, use the more explicit set() method instead.
+ """
+ self.set(name, value)
+
+ def __delitem__(self, name):
+ """Deletes a cookie given a name. Wraps ``http.cookiejar.CookieJar``'s
+ ``remove_cookie_by_name()``.
+ """
+ remove_cookie_by_name(self, name)
+
+ def set_cookie(self, cookie, *args, **kwargs):
+ if (
+ hasattr(cookie.value, "startswith")
+ and cookie.value.startswith('"')
+ and cookie.value.endswith('"')
+ ):
+ cookie.value = cookie.value.replace('\\"', "")
+ return super().set_cookie(cookie, *args, **kwargs)
+
+ def update(self, other):
+ """Updates this jar with cookies from another CookieJar or dict-like"""
+ if isinstance(other, cookielib.CookieJar):
+ for cookie in other:
+ self.set_cookie(copy.copy(cookie))
+ else:
+ super().update(other)
+
+ def _find(self, name, domain=None, path=None):
+ """Requests uses this method internally to get cookie values.
+
+ If there are conflicting cookies, _find arbitrarily chooses one.
+ See _find_no_duplicates if you want an exception thrown if there are
+ conflicting cookies.
+
+ :param name: a string containing name of cookie
+ :param domain: (optional) string containing domain of cookie
+ :param path: (optional) string containing path of cookie
+ :return: cookie.value
+ """
+ for cookie in iter(self):
+ if cookie.name == name:
+ if domain is None or cookie.domain == domain:
+ if path is None or cookie.path == path:
+ return cookie.value
+
+ raise KeyError(f"name={name!r}, domain={domain!r}, path={path!r}")
+
+ def _find_no_duplicates(self, name, domain=None, path=None):
+ """Both ``__get_item__`` and ``get`` call this function: it's never
+ used elsewhere in Requests.
+
+ :param name: a string containing name of cookie
+ :param domain: (optional) string containing domain of cookie
+ :param path: (optional) string containing path of cookie
+ :raises KeyError: if cookie is not found
+ :raises CookieConflictError: if there are multiple cookies
+ that match name and optionally domain and path
+ :return: cookie.value
+ """
+ toReturn = None
+ for cookie in iter(self):
+ if cookie.name == name:
+ if domain is None or cookie.domain == domain:
+ if path is None or cookie.path == path:
+ if toReturn is not None:
+ # if there are multiple cookies that meet passed in criteria
+ raise CookieConflictError(
+ f"There are multiple cookies with name, {name!r}"
+ )
+ # we will eventually return this as long as no cookie conflict
+ toReturn = cookie.value
+
+ if toReturn:
+ return toReturn
+ raise KeyError(f"name={name!r}, domain={domain!r}, path={path!r}")
+
+ def __getstate__(self):
+ """Unlike a normal CookieJar, this class is pickleable."""
+ state = self.__dict__.copy()
+ # remove the unpickleable RLock object
+ state.pop("_cookies_lock")
+ return state
+
+ def __setstate__(self, state):
+ """Unlike a normal CookieJar, this class is pickleable."""
+ self.__dict__.update(state)
+ if "_cookies_lock" not in self.__dict__:
+ self._cookies_lock = threading.RLock()
+
+ def copy(self):
+ """Return a copy of this RequestsCookieJar."""
+ new_cj = RequestsCookieJar()
+ new_cj.set_policy(self.get_policy())
+ new_cj.update(self)
+ return new_cj
+
+ def get_policy(self):
+ """Return the CookiePolicy instance used."""
+ return self._policy
+
+
+def _copy_cookie_jar(jar):
+ if jar is None:
+ return None
+
+ if hasattr(jar, "copy"):
+ # We're dealing with an instance of RequestsCookieJar
+ return jar.copy()
+ # We're dealing with a generic CookieJar instance
+ new_jar = copy.copy(jar)
+ new_jar.clear()
+ for cookie in jar:
+ new_jar.set_cookie(copy.copy(cookie))
+ return new_jar
+
+
+def create_cookie(name, value, **kwargs):
+ """Make a cookie from underspecified parameters.
+
+ By default, the pair of `name` and `value` will be set for the domain ''
+ and sent on every request (this is sometimes called a "supercookie").
+ """
+ result = {
+ "version": 0,
+ "name": name,
+ "value": value,
+ "port": None,
+ "domain": "",
+ "path": "/",
+ "secure": False,
+ "expires": None,
+ "discard": True,
+ "comment": None,
+ "comment_url": None,
+ "rest": {"HttpOnly": None},
+ "rfc2109": False,
+ }
+
+ badargs = set(kwargs) - set(result)
+ if badargs:
+ raise TypeError(
+ f"create_cookie() got unexpected keyword arguments: {list(badargs)}"
+ )
+
+ result.update(kwargs)
+ result["port_specified"] = bool(result["port"])
+ result["domain_specified"] = bool(result["domain"])
+ result["domain_initial_dot"] = result["domain"].startswith(".")
+ result["path_specified"] = bool(result["path"])
+
+ return cookielib.Cookie(**result)
+
+
+def morsel_to_cookie(morsel):
+ """Convert a Morsel object into a Cookie containing the one k/v pair."""
+
+ expires = None
+ if morsel["max-age"]:
+ try:
+ expires = int(time.time() + int(morsel["max-age"]))
+ except ValueError:
+ raise TypeError(f"max-age: {morsel['max-age']} must be integer")
+ elif morsel["expires"]:
+ time_template = "%a, %d-%b-%Y %H:%M:%S GMT"
+ expires = calendar.timegm(time.strptime(morsel["expires"], time_template))
+ return create_cookie(
+ comment=morsel["comment"],
+ comment_url=bool(morsel["comment"]),
+ discard=False,
+ domain=morsel["domain"],
+ expires=expires,
+ name=morsel.key,
+ path=morsel["path"],
+ port=None,
+ rest={"HttpOnly": morsel["httponly"]},
+ rfc2109=False,
+ secure=bool(morsel["secure"]),
+ value=morsel.value,
+ version=morsel["version"] or 0,
+ )
+
+
+def cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True):
+ """Returns a CookieJar from a key/value dictionary.
+
+ :param cookie_dict: Dict of key/values to insert into CookieJar.
+ :param cookiejar: (optional) A cookiejar to add the cookies to.
+ :param overwrite: (optional) If False, will not replace cookies
+ already in the jar with new ones.
+ :rtype: CookieJar
+ """
+ if cookiejar is None:
+ cookiejar = RequestsCookieJar()
+
+ if cookie_dict is not None:
+ names_from_jar = [cookie.name for cookie in cookiejar]
+ for name in cookie_dict:
+ if overwrite or (name not in names_from_jar):
+ cookiejar.set_cookie(create_cookie(name, cookie_dict[name]))
+
+ return cookiejar
+
+
+def merge_cookies(cookiejar, cookies):
+ """Add cookies to cookiejar and returns a merged CookieJar.
+
+ :param cookiejar: CookieJar object to add the cookies to.
+ :param cookies: Dictionary or CookieJar object to be added.
+ :rtype: CookieJar
+ """
+ if not isinstance(cookiejar, cookielib.CookieJar):
+ raise ValueError("You can only merge into CookieJar")
+
+ if isinstance(cookies, dict):
+ cookiejar = cookiejar_from_dict(cookies, cookiejar=cookiejar, overwrite=False)
+ elif isinstance(cookies, cookielib.CookieJar):
+ try:
+ cookiejar.update(cookies)
+ except AttributeError:
+ for cookie_in_jar in cookies:
+ cookiejar.set_cookie(cookie_in_jar)
+
+ return cookiejar
diff --git a/testcline/lib/python3.12/site-packages/requests/exceptions.py b/testcline/lib/python3.12/site-packages/requests/exceptions.py
new file mode 100644
index 0000000..83986b4
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/exceptions.py
@@ -0,0 +1,151 @@
+"""
+requests.exceptions
+~~~~~~~~~~~~~~~~~~~
+
+This module contains the set of Requests' exceptions.
+"""
+from urllib3.exceptions import HTTPError as BaseHTTPError
+
+from .compat import JSONDecodeError as CompatJSONDecodeError
+
+
+class RequestException(IOError):
+ """There was an ambiguous exception that occurred while handling your
+ request.
+ """
+
+ def __init__(self, *args, **kwargs):
+ """Initialize RequestException with `request` and `response` objects."""
+ response = kwargs.pop("response", None)
+ self.response = response
+ self.request = kwargs.pop("request", None)
+ if response is not None and not self.request and hasattr(response, "request"):
+ self.request = self.response.request
+ super().__init__(*args, **kwargs)
+
+
+class InvalidJSONError(RequestException):
+ """A JSON error occurred."""
+
+
+class JSONDecodeError(InvalidJSONError, CompatJSONDecodeError):
+ """Couldn't decode the text into json"""
+
+ def __init__(self, *args, **kwargs):
+ """
+ Construct the JSONDecodeError instance first with all
+ args. Then use it's args to construct the IOError so that
+ the json specific args aren't used as IOError specific args
+ and the error message from JSONDecodeError is preserved.
+ """
+ CompatJSONDecodeError.__init__(self, *args)
+ InvalidJSONError.__init__(self, *self.args, **kwargs)
+
+ def __reduce__(self):
+ """
+ The __reduce__ method called when pickling the object must
+ be the one from the JSONDecodeError (be it json/simplejson)
+ as it expects all the arguments for instantiation, not just
+ one like the IOError, and the MRO would by default call the
+ __reduce__ method from the IOError due to the inheritance order.
+ """
+ return CompatJSONDecodeError.__reduce__(self)
+
+
+class HTTPError(RequestException):
+ """An HTTP error occurred."""
+
+
+class ConnectionError(RequestException):
+ """A Connection error occurred."""
+
+
+class ProxyError(ConnectionError):
+ """A proxy error occurred."""
+
+
+class SSLError(ConnectionError):
+ """An SSL error occurred."""
+
+
+class Timeout(RequestException):
+ """The request timed out.
+
+ Catching this error will catch both
+ :exc:`~requests.exceptions.ConnectTimeout` and
+ :exc:`~requests.exceptions.ReadTimeout` errors.
+ """
+
+
+class ConnectTimeout(ConnectionError, Timeout):
+ """The request timed out while trying to connect to the remote server.
+
+ Requests that produced this error are safe to retry.
+ """
+
+
+class ReadTimeout(Timeout):
+ """The server did not send any data in the allotted amount of time."""
+
+
+class URLRequired(RequestException):
+ """A valid URL is required to make a request."""
+
+
+class TooManyRedirects(RequestException):
+ """Too many redirects."""
+
+
+class MissingSchema(RequestException, ValueError):
+ """The URL scheme (e.g. http or https) is missing."""
+
+
+class InvalidSchema(RequestException, ValueError):
+ """The URL scheme provided is either invalid or unsupported."""
+
+
+class InvalidURL(RequestException, ValueError):
+ """The URL provided was somehow invalid."""
+
+
+class InvalidHeader(RequestException, ValueError):
+ """The header value provided was somehow invalid."""
+
+
+class InvalidProxyURL(InvalidURL):
+ """The proxy URL provided is invalid."""
+
+
+class ChunkedEncodingError(RequestException):
+ """The server declared chunked encoding but sent an invalid chunk."""
+
+
+class ContentDecodingError(RequestException, BaseHTTPError):
+ """Failed to decode response content."""
+
+
+class StreamConsumedError(RequestException, TypeError):
+ """The content for this response was already consumed."""
+
+
+class RetryError(RequestException):
+ """Custom retries logic failed"""
+
+
+class UnrewindableBodyError(RequestException):
+ """Requests encountered an error when trying to rewind a body."""
+
+
+# Warnings
+
+
+class RequestsWarning(Warning):
+ """Base warning for Requests."""
+
+
+class FileModeWarning(RequestsWarning, DeprecationWarning):
+ """A file was opened in text mode, but Requests determined its binary length."""
+
+
+class RequestsDependencyWarning(RequestsWarning):
+ """An imported dependency doesn't match the expected version range."""
diff --git a/testcline/lib/python3.12/site-packages/requests/help.py b/testcline/lib/python3.12/site-packages/requests/help.py
new file mode 100644
index 0000000..8fbcd65
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/help.py
@@ -0,0 +1,134 @@
+"""Module containing bug report helper(s)."""
+
+import json
+import platform
+import ssl
+import sys
+
+import idna
+import urllib3
+
+from . import __version__ as requests_version
+
+try:
+ import charset_normalizer
+except ImportError:
+ charset_normalizer = None
+
+try:
+ import chardet
+except ImportError:
+ chardet = None
+
+try:
+ from urllib3.contrib import pyopenssl
+except ImportError:
+ pyopenssl = None
+ OpenSSL = None
+ cryptography = None
+else:
+ import cryptography
+ import OpenSSL
+
+
+def _implementation():
+ """Return a dict with the Python implementation and version.
+
+ Provide both the name and the version of the Python implementation
+ currently running. For example, on CPython 3.10.3 it will return
+ {'name': 'CPython', 'version': '3.10.3'}.
+
+ This function works best on CPython and PyPy: in particular, it probably
+ doesn't work for Jython or IronPython. Future investigation should be done
+ to work out the correct shape of the code for those platforms.
+ """
+ implementation = platform.python_implementation()
+
+ if implementation == "CPython":
+ implementation_version = platform.python_version()
+ elif implementation == "PyPy":
+ implementation_version = "{}.{}.{}".format(
+ sys.pypy_version_info.major,
+ sys.pypy_version_info.minor,
+ sys.pypy_version_info.micro,
+ )
+ if sys.pypy_version_info.releaselevel != "final":
+ implementation_version = "".join(
+ [implementation_version, sys.pypy_version_info.releaselevel]
+ )
+ elif implementation == "Jython":
+ implementation_version = platform.python_version() # Complete Guess
+ elif implementation == "IronPython":
+ implementation_version = platform.python_version() # Complete Guess
+ else:
+ implementation_version = "Unknown"
+
+ return {"name": implementation, "version": implementation_version}
+
+
+def info():
+ """Generate information for a bug report."""
+ try:
+ platform_info = {
+ "system": platform.system(),
+ "release": platform.release(),
+ }
+ except OSError:
+ platform_info = {
+ "system": "Unknown",
+ "release": "Unknown",
+ }
+
+ implementation_info = _implementation()
+ urllib3_info = {"version": urllib3.__version__}
+ charset_normalizer_info = {"version": None}
+ chardet_info = {"version": None}
+ if charset_normalizer:
+ charset_normalizer_info = {"version": charset_normalizer.__version__}
+ if chardet:
+ chardet_info = {"version": chardet.__version__}
+
+ pyopenssl_info = {
+ "version": None,
+ "openssl_version": "",
+ }
+ if OpenSSL:
+ pyopenssl_info = {
+ "version": OpenSSL.__version__,
+ "openssl_version": f"{OpenSSL.SSL.OPENSSL_VERSION_NUMBER:x}",
+ }
+ cryptography_info = {
+ "version": getattr(cryptography, "__version__", ""),
+ }
+ idna_info = {
+ "version": getattr(idna, "__version__", ""),
+ }
+
+ system_ssl = ssl.OPENSSL_VERSION_NUMBER
+ system_ssl_info = {"version": f"{system_ssl:x}" if system_ssl is not None else ""}
+
+ return {
+ "platform": platform_info,
+ "implementation": implementation_info,
+ "system_ssl": system_ssl_info,
+ "using_pyopenssl": pyopenssl is not None,
+ "using_charset_normalizer": chardet is None,
+ "pyOpenSSL": pyopenssl_info,
+ "urllib3": urllib3_info,
+ "chardet": chardet_info,
+ "charset_normalizer": charset_normalizer_info,
+ "cryptography": cryptography_info,
+ "idna": idna_info,
+ "requests": {
+ "version": requests_version,
+ },
+ }
+
+
+def main():
+ """Pretty-print the bug information as JSON."""
+ print(json.dumps(info(), sort_keys=True, indent=2))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/testcline/lib/python3.12/site-packages/requests/hooks.py b/testcline/lib/python3.12/site-packages/requests/hooks.py
new file mode 100644
index 0000000..d181ba2
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/hooks.py
@@ -0,0 +1,33 @@
+"""
+requests.hooks
+~~~~~~~~~~~~~~
+
+This module provides the capabilities for the Requests hooks system.
+
+Available hooks:
+
+``response``:
+ The response generated from a Request.
+"""
+HOOKS = ["response"]
+
+
+def default_hooks():
+ return {event: [] for event in HOOKS}
+
+
+# TODO: response is the only one
+
+
+def dispatch_hook(key, hooks, hook_data, **kwargs):
+ """Dispatches a hook dictionary on a given piece of data."""
+ hooks = hooks or {}
+ hooks = hooks.get(key)
+ if hooks:
+ if hasattr(hooks, "__call__"):
+ hooks = [hooks]
+ for hook in hooks:
+ _hook_data = hook(hook_data, **kwargs)
+ if _hook_data is not None:
+ hook_data = _hook_data
+ return hook_data
diff --git a/testcline/lib/python3.12/site-packages/requests/models.py b/testcline/lib/python3.12/site-packages/requests/models.py
new file mode 100644
index 0000000..8f56ca7
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/models.py
@@ -0,0 +1,1037 @@
+"""
+requests.models
+~~~~~~~~~~~~~~~
+
+This module contains the primary objects that power Requests.
+"""
+
+import datetime
+
+# Import encoding now, to avoid implicit import later.
+# Implicit import within threads may cause LookupError when standard library is in a ZIP,
+# such as in Embedded Python. See https://github.com/psf/requests/issues/3578.
+import encodings.idna # noqa: F401
+from io import UnsupportedOperation
+
+from urllib3.exceptions import (
+ DecodeError,
+ LocationParseError,
+ ProtocolError,
+ ReadTimeoutError,
+ SSLError,
+)
+from urllib3.fields import RequestField
+from urllib3.filepost import encode_multipart_formdata
+from urllib3.util import parse_url
+
+from ._internal_utils import to_native_string, unicode_is_ascii
+from .auth import HTTPBasicAuth
+from .compat import (
+ Callable,
+ JSONDecodeError,
+ Mapping,
+ basestring,
+ builtin_str,
+ chardet,
+ cookielib,
+)
+from .compat import json as complexjson
+from .compat import urlencode, urlsplit, urlunparse
+from .cookies import _copy_cookie_jar, cookiejar_from_dict, get_cookie_header
+from .exceptions import (
+ ChunkedEncodingError,
+ ConnectionError,
+ ContentDecodingError,
+ HTTPError,
+ InvalidJSONError,
+ InvalidURL,
+)
+from .exceptions import JSONDecodeError as RequestsJSONDecodeError
+from .exceptions import MissingSchema
+from .exceptions import SSLError as RequestsSSLError
+from .exceptions import StreamConsumedError
+from .hooks import default_hooks
+from .status_codes import codes
+from .structures import CaseInsensitiveDict
+from .utils import (
+ check_header_validity,
+ get_auth_from_url,
+ guess_filename,
+ guess_json_utf,
+ iter_slices,
+ parse_header_links,
+ requote_uri,
+ stream_decode_response_unicode,
+ super_len,
+ to_key_val_list,
+)
+
+#: The set of HTTP status codes that indicate an automatically
+#: processable redirect.
+REDIRECT_STATI = (
+ codes.moved, # 301
+ codes.found, # 302
+ codes.other, # 303
+ codes.temporary_redirect, # 307
+ codes.permanent_redirect, # 308
+)
+
+DEFAULT_REDIRECT_LIMIT = 30
+CONTENT_CHUNK_SIZE = 10 * 1024
+ITER_CHUNK_SIZE = 512
+
+
+class RequestEncodingMixin:
+ @property
+ def path_url(self):
+ """Build the path URL to use."""
+
+ url = []
+
+ p = urlsplit(self.url)
+
+ path = p.path
+ if not path:
+ path = "/"
+
+ url.append(path)
+
+ query = p.query
+ if query:
+ url.append("?")
+ url.append(query)
+
+ return "".join(url)
+
+ @staticmethod
+ def _encode_params(data):
+ """Encode parameters in a piece of data.
+
+ Will successfully encode parameters when passed as a dict or a list of
+ 2-tuples. Order is retained if data is a list of 2-tuples but arbitrary
+ if parameters are supplied as a dict.
+ """
+
+ if isinstance(data, (str, bytes)):
+ return data
+ elif hasattr(data, "read"):
+ return data
+ elif hasattr(data, "__iter__"):
+ result = []
+ for k, vs in to_key_val_list(data):
+ if isinstance(vs, basestring) or not hasattr(vs, "__iter__"):
+ vs = [vs]
+ for v in vs:
+ if v is not None:
+ result.append(
+ (
+ k.encode("utf-8") if isinstance(k, str) else k,
+ v.encode("utf-8") if isinstance(v, str) else v,
+ )
+ )
+ return urlencode(result, doseq=True)
+ else:
+ return data
+
+ @staticmethod
+ def _encode_files(files, data):
+ """Build the body for a multipart/form-data request.
+
+ Will successfully encode files when passed as a dict or a list of
+ tuples. Order is retained if data is a list of tuples but arbitrary
+ if parameters are supplied as a dict.
+ The tuples may be 2-tuples (filename, fileobj), 3-tuples (filename, fileobj, contentype)
+ or 4-tuples (filename, fileobj, contentype, custom_headers).
+ """
+ if not files:
+ raise ValueError("Files must be provided.")
+ elif isinstance(data, basestring):
+ raise ValueError("Data must not be a string.")
+
+ new_fields = []
+ fields = to_key_val_list(data or {})
+ files = to_key_val_list(files or {})
+
+ for field, val in fields:
+ if isinstance(val, basestring) or not hasattr(val, "__iter__"):
+ val = [val]
+ for v in val:
+ if v is not None:
+ # Don't call str() on bytestrings: in Py3 it all goes wrong.
+ if not isinstance(v, bytes):
+ v = str(v)
+
+ new_fields.append(
+ (
+ field.decode("utf-8")
+ if isinstance(field, bytes)
+ else field,
+ v.encode("utf-8") if isinstance(v, str) else v,
+ )
+ )
+
+ for k, v in files:
+ # support for explicit filename
+ ft = None
+ fh = None
+ if isinstance(v, (tuple, list)):
+ if len(v) == 2:
+ fn, fp = v
+ elif len(v) == 3:
+ fn, fp, ft = v
+ else:
+ fn, fp, ft, fh = v
+ else:
+ fn = guess_filename(v) or k
+ fp = v
+
+ if isinstance(fp, (str, bytes, bytearray)):
+ fdata = fp
+ elif hasattr(fp, "read"):
+ fdata = fp.read()
+ elif fp is None:
+ continue
+ else:
+ fdata = fp
+
+ rf = RequestField(name=k, data=fdata, filename=fn, headers=fh)
+ rf.make_multipart(content_type=ft)
+ new_fields.append(rf)
+
+ body, content_type = encode_multipart_formdata(new_fields)
+
+ return body, content_type
+
+
+class RequestHooksMixin:
+ def register_hook(self, event, hook):
+ """Properly register a hook."""
+
+ if event not in self.hooks:
+ raise ValueError(f'Unsupported event specified, with event name "{event}"')
+
+ if isinstance(hook, Callable):
+ self.hooks[event].append(hook)
+ elif hasattr(hook, "__iter__"):
+ self.hooks[event].extend(h for h in hook if isinstance(h, Callable))
+
+ def deregister_hook(self, event, hook):
+ """Deregister a previously registered hook.
+ Returns True if the hook existed, False if not.
+ """
+
+ try:
+ self.hooks[event].remove(hook)
+ return True
+ except ValueError:
+ return False
+
+
+class Request(RequestHooksMixin):
+ """A user-created :class:`Request ` object.
+
+ Used to prepare a :class:`PreparedRequest `, which is sent to the server.
+
+ :param method: HTTP method to use.
+ :param url: URL to send.
+ :param headers: dictionary of headers to send.
+ :param files: dictionary of {filename: fileobject} files to multipart upload.
+ :param data: the body to attach to the request. If a dictionary or
+ list of tuples ``[(key, value)]`` is provided, form-encoding will
+ take place.
+ :param json: json for the body to attach to the request (if files or data is not specified).
+ :param params: URL parameters to append to the URL. If a dictionary or
+ list of tuples ``[(key, value)]`` is provided, form-encoding will
+ take place.
+ :param auth: Auth handler or (user, pass) tuple.
+ :param cookies: dictionary or CookieJar of cookies to attach to this request.
+ :param hooks: dictionary of callback hooks, for internal usage.
+
+ Usage::
+
+ >>> import requests
+ >>> req = requests.Request('GET', 'https://httpbin.org/get')
+ >>> req.prepare()
+
+ """
+
+ def __init__(
+ self,
+ method=None,
+ url=None,
+ headers=None,
+ files=None,
+ data=None,
+ params=None,
+ auth=None,
+ cookies=None,
+ hooks=None,
+ json=None,
+ ):
+ # Default empty dicts for dict params.
+ data = [] if data is None else data
+ files = [] if files is None else files
+ headers = {} if headers is None else headers
+ params = {} if params is None else params
+ hooks = {} if hooks is None else hooks
+
+ self.hooks = default_hooks()
+ for k, v in list(hooks.items()):
+ self.register_hook(event=k, hook=v)
+
+ self.method = method
+ self.url = url
+ self.headers = headers
+ self.files = files
+ self.data = data
+ self.json = json
+ self.params = params
+ self.auth = auth
+ self.cookies = cookies
+
+ def __repr__(self):
+ return f""
+
+ def prepare(self):
+ """Constructs a :class:`PreparedRequest ` for transmission and returns it."""
+ p = PreparedRequest()
+ p.prepare(
+ method=self.method,
+ url=self.url,
+ headers=self.headers,
+ files=self.files,
+ data=self.data,
+ json=self.json,
+ params=self.params,
+ auth=self.auth,
+ cookies=self.cookies,
+ hooks=self.hooks,
+ )
+ return p
+
+
+class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
+ """The fully mutable :class:`PreparedRequest ` object,
+ containing the exact bytes that will be sent to the server.
+
+ Instances are generated from a :class:`Request ` object, and
+ should not be instantiated manually; doing so may produce undesirable
+ effects.
+
+ Usage::
+
+ >>> import requests
+ >>> req = requests.Request('GET', 'https://httpbin.org/get')
+ >>> r = req.prepare()
+ >>> r
+
+
+ >>> s = requests.Session()
+ >>> s.send(r)
+
+ """
+
+ def __init__(self):
+ #: HTTP verb to send to the server.
+ self.method = None
+ #: HTTP URL to send the request to.
+ self.url = None
+ #: dictionary of HTTP headers.
+ self.headers = None
+ # The `CookieJar` used to create the Cookie header will be stored here
+ # after prepare_cookies is called
+ self._cookies = None
+ #: request body to send to the server.
+ self.body = None
+ #: dictionary of callback hooks, for internal usage.
+ self.hooks = default_hooks()
+ #: integer denoting starting position of a readable file-like body.
+ self._body_position = None
+
+ def prepare(
+ self,
+ method=None,
+ url=None,
+ headers=None,
+ files=None,
+ data=None,
+ params=None,
+ auth=None,
+ cookies=None,
+ hooks=None,
+ json=None,
+ ):
+ """Prepares the entire request with the given parameters."""
+
+ self.prepare_method(method)
+ self.prepare_url(url, params)
+ self.prepare_headers(headers)
+ self.prepare_cookies(cookies)
+ self.prepare_body(data, files, json)
+ self.prepare_auth(auth, url)
+
+ # Note that prepare_auth must be last to enable authentication schemes
+ # such as OAuth to work on a fully prepared request.
+
+ # This MUST go after prepare_auth. Authenticators could add a hook
+ self.prepare_hooks(hooks)
+
+ def __repr__(self):
+ return f""
+
+ def copy(self):
+ p = PreparedRequest()
+ p.method = self.method
+ p.url = self.url
+ p.headers = self.headers.copy() if self.headers is not None else None
+ p._cookies = _copy_cookie_jar(self._cookies)
+ p.body = self.body
+ p.hooks = self.hooks
+ p._body_position = self._body_position
+ return p
+
+ def prepare_method(self, method):
+ """Prepares the given HTTP method."""
+ self.method = method
+ if self.method is not None:
+ self.method = to_native_string(self.method.upper())
+
+ @staticmethod
+ def _get_idna_encoded_host(host):
+ import idna
+
+ try:
+ host = idna.encode(host, uts46=True).decode("utf-8")
+ except idna.IDNAError:
+ raise UnicodeError
+ return host
+
+ def prepare_url(self, url, params):
+ """Prepares the given HTTP URL."""
+ #: Accept objects that have string representations.
+ #: We're unable to blindly call unicode/str functions
+ #: as this will include the bytestring indicator (b'')
+ #: on python 3.x.
+ #: https://github.com/psf/requests/pull/2238
+ if isinstance(url, bytes):
+ url = url.decode("utf8")
+ else:
+ url = str(url)
+
+ # Remove leading whitespaces from url
+ url = url.lstrip()
+
+ # Don't do any URL preparation for non-HTTP schemes like `mailto`,
+ # `data` etc to work around exceptions from `url_parse`, which
+ # handles RFC 3986 only.
+ if ":" in url and not url.lower().startswith("http"):
+ self.url = url
+ return
+
+ # Support for unicode domain names and paths.
+ try:
+ scheme, auth, host, port, path, query, fragment = parse_url(url)
+ except LocationParseError as e:
+ raise InvalidURL(*e.args)
+
+ if not scheme:
+ raise MissingSchema(
+ f"Invalid URL {url!r}: No scheme supplied. "
+ f"Perhaps you meant https://{url}?"
+ )
+
+ if not host:
+ raise InvalidURL(f"Invalid URL {url!r}: No host supplied")
+
+ # In general, we want to try IDNA encoding the hostname if the string contains
+ # non-ASCII characters. This allows users to automatically get the correct IDNA
+ # behaviour. For strings containing only ASCII characters, we need to also verify
+ # it doesn't start with a wildcard (*), before allowing the unencoded hostname.
+ if not unicode_is_ascii(host):
+ try:
+ host = self._get_idna_encoded_host(host)
+ except UnicodeError:
+ raise InvalidURL("URL has an invalid label.")
+ elif host.startswith(("*", ".")):
+ raise InvalidURL("URL has an invalid label.")
+
+ # Carefully reconstruct the network location
+ netloc = auth or ""
+ if netloc:
+ netloc += "@"
+ netloc += host
+ if port:
+ netloc += f":{port}"
+
+ # Bare domains aren't valid URLs.
+ if not path:
+ path = "/"
+
+ if isinstance(params, (str, bytes)):
+ params = to_native_string(params)
+
+ enc_params = self._encode_params(params)
+ if enc_params:
+ if query:
+ query = f"{query}&{enc_params}"
+ else:
+ query = enc_params
+
+ url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragment]))
+ self.url = url
+
+ def prepare_headers(self, headers):
+ """Prepares the given HTTP headers."""
+
+ self.headers = CaseInsensitiveDict()
+ if headers:
+ for header in headers.items():
+ # Raise exception on invalid header value.
+ check_header_validity(header)
+ name, value = header
+ self.headers[to_native_string(name)] = value
+
+ def prepare_body(self, data, files, json=None):
+ """Prepares the given HTTP body data."""
+
+ # Check if file, fo, generator, iterator.
+ # If not, run through normal process.
+
+ # Nottin' on you.
+ body = None
+ content_type = None
+
+ if not data and json is not None:
+ # urllib3 requires a bytes-like body. Python 2's json.dumps
+ # provides this natively, but Python 3 gives a Unicode string.
+ content_type = "application/json"
+
+ try:
+ body = complexjson.dumps(json, allow_nan=False)
+ except ValueError as ve:
+ raise InvalidJSONError(ve, request=self)
+
+ if not isinstance(body, bytes):
+ body = body.encode("utf-8")
+
+ is_stream = all(
+ [
+ hasattr(data, "__iter__"),
+ not isinstance(data, (basestring, list, tuple, Mapping)),
+ ]
+ )
+
+ if is_stream:
+ try:
+ length = super_len(data)
+ except (TypeError, AttributeError, UnsupportedOperation):
+ length = None
+
+ body = data
+
+ if getattr(body, "tell", None) is not None:
+ # Record the current file position before reading.
+ # This will allow us to rewind a file in the event
+ # of a redirect.
+ try:
+ self._body_position = body.tell()
+ except OSError:
+ # This differentiates from None, allowing us to catch
+ # a failed `tell()` later when trying to rewind the body
+ self._body_position = object()
+
+ if files:
+ raise NotImplementedError(
+ "Streamed bodies and files are mutually exclusive."
+ )
+
+ if length:
+ self.headers["Content-Length"] = builtin_str(length)
+ else:
+ self.headers["Transfer-Encoding"] = "chunked"
+ else:
+ # Multi-part file uploads.
+ if files:
+ (body, content_type) = self._encode_files(files, data)
+ else:
+ if data:
+ body = self._encode_params(data)
+ if isinstance(data, basestring) or hasattr(data, "read"):
+ content_type = None
+ else:
+ content_type = "application/x-www-form-urlencoded"
+
+ self.prepare_content_length(body)
+
+ # Add content-type if it wasn't explicitly provided.
+ if content_type and ("content-type" not in self.headers):
+ self.headers["Content-Type"] = content_type
+
+ self.body = body
+
+ def prepare_content_length(self, body):
+ """Prepare Content-Length header based on request method and body"""
+ if body is not None:
+ length = super_len(body)
+ if length:
+ # If length exists, set it. Otherwise, we fallback
+ # to Transfer-Encoding: chunked.
+ self.headers["Content-Length"] = builtin_str(length)
+ elif (
+ self.method not in ("GET", "HEAD")
+ and self.headers.get("Content-Length") is None
+ ):
+ # Set Content-Length to 0 for methods that can have a body
+ # but don't provide one. (i.e. not GET or HEAD)
+ self.headers["Content-Length"] = "0"
+
+ def prepare_auth(self, auth, url=""):
+ """Prepares the given HTTP auth data."""
+
+ # If no Auth is explicitly provided, extract it from the URL first.
+ if auth is None:
+ url_auth = get_auth_from_url(self.url)
+ auth = url_auth if any(url_auth) else None
+
+ if auth:
+ if isinstance(auth, tuple) and len(auth) == 2:
+ # special-case basic HTTP auth
+ auth = HTTPBasicAuth(*auth)
+
+ # Allow auth to make its changes.
+ r = auth(self)
+
+ # Update self to reflect the auth changes.
+ self.__dict__.update(r.__dict__)
+
+ # Recompute Content-Length
+ self.prepare_content_length(self.body)
+
+ def prepare_cookies(self, cookies):
+ """Prepares the given HTTP cookie data.
+
+ This function eventually generates a ``Cookie`` header from the
+ given cookies using cookielib. Due to cookielib's design, the header
+ will not be regenerated if it already exists, meaning this function
+ can only be called once for the life of the
+ :class:`PreparedRequest ` object. Any subsequent calls
+ to ``prepare_cookies`` will have no actual effect, unless the "Cookie"
+ header is removed beforehand.
+ """
+ if isinstance(cookies, cookielib.CookieJar):
+ self._cookies = cookies
+ else:
+ self._cookies = cookiejar_from_dict(cookies)
+
+ cookie_header = get_cookie_header(self._cookies, self)
+ if cookie_header is not None:
+ self.headers["Cookie"] = cookie_header
+
+ def prepare_hooks(self, hooks):
+ """Prepares the given hooks."""
+ # hooks can be passed as None to the prepare method and to this
+ # method. To prevent iterating over None, simply use an empty list
+ # if hooks is False-y
+ hooks = hooks or []
+ for event in hooks:
+ self.register_hook(event, hooks[event])
+
+
+class Response:
+ """The :class:`Response ` object, which contains a
+ server's response to an HTTP request.
+ """
+
+ __attrs__ = [
+ "_content",
+ "status_code",
+ "headers",
+ "url",
+ "history",
+ "encoding",
+ "reason",
+ "cookies",
+ "elapsed",
+ "request",
+ ]
+
+ def __init__(self):
+ self._content = False
+ self._content_consumed = False
+ self._next = None
+
+ #: Integer Code of responded HTTP Status, e.g. 404 or 200.
+ self.status_code = None
+
+ #: Case-insensitive Dictionary of Response Headers.
+ #: For example, ``headers['content-encoding']`` will return the
+ #: value of a ``'Content-Encoding'`` response header.
+ self.headers = CaseInsensitiveDict()
+
+ #: File-like object representation of response (for advanced usage).
+ #: Use of ``raw`` requires that ``stream=True`` be set on the request.
+ #: This requirement does not apply for use internally to Requests.
+ self.raw = None
+
+ #: Final URL location of Response.
+ self.url = None
+
+ #: Encoding to decode with when accessing r.text.
+ self.encoding = None
+
+ #: A list of :class:`Response ` objects from
+ #: the history of the Request. Any redirect responses will end
+ #: up here. The list is sorted from the oldest to the most recent request.
+ self.history = []
+
+ #: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK".
+ self.reason = None
+
+ #: A CookieJar of Cookies the server sent back.
+ self.cookies = cookiejar_from_dict({})
+
+ #: The amount of time elapsed between sending the request
+ #: and the arrival of the response (as a timedelta).
+ #: This property specifically measures the time taken between sending
+ #: the first byte of the request and finishing parsing the headers. It
+ #: is therefore unaffected by consuming the response content or the
+ #: value of the ``stream`` keyword argument.
+ self.elapsed = datetime.timedelta(0)
+
+ #: The :class:`PreparedRequest ` object to which this
+ #: is a response.
+ self.request = None
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ self.close()
+
+ def __getstate__(self):
+ # Consume everything; accessing the content attribute makes
+ # sure the content has been fully read.
+ if not self._content_consumed:
+ self.content
+
+ return {attr: getattr(self, attr, None) for attr in self.__attrs__}
+
+ def __setstate__(self, state):
+ for name, value in state.items():
+ setattr(self, name, value)
+
+ # pickled objects do not have .raw
+ setattr(self, "_content_consumed", True)
+ setattr(self, "raw", None)
+
+ def __repr__(self):
+ return f""
+
+ def __bool__(self):
+ """Returns True if :attr:`status_code` is less than 400.
+
+ This attribute checks if the status code of the response is between
+ 400 and 600 to see if there was a client error or a server error. If
+ the status code, is between 200 and 400, this will return True. This
+ is **not** a check to see if the response code is ``200 OK``.
+ """
+ return self.ok
+
+ def __nonzero__(self):
+ """Returns True if :attr:`status_code` is less than 400.
+
+ This attribute checks if the status code of the response is between
+ 400 and 600 to see if there was a client error or a server error. If
+ the status code, is between 200 and 400, this will return True. This
+ is **not** a check to see if the response code is ``200 OK``.
+ """
+ return self.ok
+
+ def __iter__(self):
+ """Allows you to use a response as an iterator."""
+ return self.iter_content(128)
+
+ @property
+ def ok(self):
+ """Returns True if :attr:`status_code` is less than 400, False if not.
+
+ This attribute checks if the status code of the response is between
+ 400 and 600 to see if there was a client error or a server error. If
+ the status code is between 200 and 400, this will return True. This
+ is **not** a check to see if the response code is ``200 OK``.
+ """
+ try:
+ self.raise_for_status()
+ except HTTPError:
+ return False
+ return True
+
+ @property
+ def is_redirect(self):
+ """True if this Response is a well-formed HTTP redirect that could have
+ been processed automatically (by :meth:`Session.resolve_redirects`).
+ """
+ return "location" in self.headers and self.status_code in REDIRECT_STATI
+
+ @property
+ def is_permanent_redirect(self):
+ """True if this Response one of the permanent versions of redirect."""
+ return "location" in self.headers and self.status_code in (
+ codes.moved_permanently,
+ codes.permanent_redirect,
+ )
+
+ @property
+ def next(self):
+ """Returns a PreparedRequest for the next request in a redirect chain, if there is one."""
+ return self._next
+
+ @property
+ def apparent_encoding(self):
+ """The apparent encoding, provided by the charset_normalizer or chardet libraries."""
+ if chardet is not None:
+ return chardet.detect(self.content)["encoding"]
+ else:
+ # If no character detection library is available, we'll fall back
+ # to a standard Python utf-8 str.
+ return "utf-8"
+
+ def iter_content(self, chunk_size=1, decode_unicode=False):
+ """Iterates over the response data. When stream=True is set on the
+ request, this avoids reading the content at once into memory for
+ large responses. The chunk size is the number of bytes it should
+ read into memory. This is not necessarily the length of each item
+ returned as decoding can take place.
+
+ chunk_size must be of type int or None. A value of None will
+ function differently depending on the value of `stream`.
+ stream=True will read data as it arrives in whatever size the
+ chunks are received. If stream=False, data is returned as
+ a single chunk.
+
+ If decode_unicode is True, content will be decoded using the best
+ available encoding based on the response.
+ """
+
+ def generate():
+ # Special case for urllib3.
+ if hasattr(self.raw, "stream"):
+ try:
+ yield from self.raw.stream(chunk_size, decode_content=True)
+ except ProtocolError as e:
+ raise ChunkedEncodingError(e)
+ except DecodeError as e:
+ raise ContentDecodingError(e)
+ except ReadTimeoutError as e:
+ raise ConnectionError(e)
+ except SSLError as e:
+ raise RequestsSSLError(e)
+ else:
+ # Standard file-like object.
+ while True:
+ chunk = self.raw.read(chunk_size)
+ if not chunk:
+ break
+ yield chunk
+
+ self._content_consumed = True
+
+ if self._content_consumed and isinstance(self._content, bool):
+ raise StreamConsumedError()
+ elif chunk_size is not None and not isinstance(chunk_size, int):
+ raise TypeError(
+ f"chunk_size must be an int, it is instead a {type(chunk_size)}."
+ )
+ # simulate reading small chunks of the content
+ reused_chunks = iter_slices(self._content, chunk_size)
+
+ stream_chunks = generate()
+
+ chunks = reused_chunks if self._content_consumed else stream_chunks
+
+ if decode_unicode:
+ chunks = stream_decode_response_unicode(chunks, self)
+
+ return chunks
+
+ def iter_lines(
+ self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=False, delimiter=None
+ ):
+ """Iterates over the response data, one line at a time. When
+ stream=True is set on the request, this avoids reading the
+ content at once into memory for large responses.
+
+ .. note:: This method is not reentrant safe.
+ """
+
+ pending = None
+
+ for chunk in self.iter_content(
+ chunk_size=chunk_size, decode_unicode=decode_unicode
+ ):
+ if pending is not None:
+ chunk = pending + chunk
+
+ if delimiter:
+ lines = chunk.split(delimiter)
+ else:
+ lines = chunk.splitlines()
+
+ if lines and lines[-1] and chunk and lines[-1][-1] == chunk[-1]:
+ pending = lines.pop()
+ else:
+ pending = None
+
+ yield from lines
+
+ if pending is not None:
+ yield pending
+
+ @property
+ def content(self):
+ """Content of the response, in bytes."""
+
+ if self._content is False:
+ # Read the contents.
+ if self._content_consumed:
+ raise RuntimeError("The content for this response was already consumed")
+
+ if self.status_code == 0 or self.raw is None:
+ self._content = None
+ else:
+ self._content = b"".join(self.iter_content(CONTENT_CHUNK_SIZE)) or b""
+
+ self._content_consumed = True
+ # don't need to release the connection; that's been handled by urllib3
+ # since we exhausted the data.
+ return self._content
+
+ @property
+ def text(self):
+ """Content of the response, in unicode.
+
+ If Response.encoding is None, encoding will be guessed using
+ ``charset_normalizer`` or ``chardet``.
+
+ The encoding of the response content is determined based solely on HTTP
+ headers, following RFC 2616 to the letter. If you can take advantage of
+ non-HTTP knowledge to make a better guess at the encoding, you should
+ set ``r.encoding`` appropriately before accessing this property.
+ """
+
+ # Try charset from content-type
+ content = None
+ encoding = self.encoding
+
+ if not self.content:
+ return ""
+
+ # Fallback to auto-detected encoding.
+ if self.encoding is None:
+ encoding = self.apparent_encoding
+
+ # Decode unicode from given encoding.
+ try:
+ content = str(self.content, encoding, errors="replace")
+ except (LookupError, TypeError):
+ # A LookupError is raised if the encoding was not found which could
+ # indicate a misspelling or similar mistake.
+ #
+ # A TypeError can be raised if encoding is None
+ #
+ # So we try blindly encoding.
+ content = str(self.content, errors="replace")
+
+ return content
+
+ def json(self, **kwargs):
+ r"""Returns the json-encoded content of a response, if any.
+
+ :param \*\*kwargs: Optional arguments that ``json.loads`` takes.
+ :raises requests.exceptions.JSONDecodeError: If the response body does not
+ contain valid json.
+ """
+
+ if not self.encoding and self.content and len(self.content) > 3:
+ # No encoding set. JSON RFC 4627 section 3 states we should expect
+ # UTF-8, -16 or -32. Detect which one to use; If the detection or
+ # decoding fails, fall back to `self.text` (using charset_normalizer to make
+ # a best guess).
+ encoding = guess_json_utf(self.content)
+ if encoding is not None:
+ try:
+ return complexjson.loads(self.content.decode(encoding), **kwargs)
+ except UnicodeDecodeError:
+ # Wrong UTF codec detected; usually because it's not UTF-8
+ # but some other 8-bit codec. This is an RFC violation,
+ # and the server didn't bother to tell us what codec *was*
+ # used.
+ pass
+ except JSONDecodeError as e:
+ raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
+
+ try:
+ return complexjson.loads(self.text, **kwargs)
+ except JSONDecodeError as e:
+ # Catch JSON-related errors and raise as requests.JSONDecodeError
+ # This aliases json.JSONDecodeError and simplejson.JSONDecodeError
+ raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
+
+ @property
+ def links(self):
+ """Returns the parsed header links of the response, if any."""
+
+ header = self.headers.get("link")
+
+ resolved_links = {}
+
+ if header:
+ links = parse_header_links(header)
+
+ for link in links:
+ key = link.get("rel") or link.get("url")
+ resolved_links[key] = link
+
+ return resolved_links
+
+ def raise_for_status(self):
+ """Raises :class:`HTTPError`, if one occurred."""
+
+ http_error_msg = ""
+ if isinstance(self.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. (See PR #3538)
+ try:
+ reason = self.reason.decode("utf-8")
+ except UnicodeDecodeError:
+ reason = self.reason.decode("iso-8859-1")
+ else:
+ reason = self.reason
+
+ if 400 <= self.status_code < 500:
+ http_error_msg = (
+ f"{self.status_code} Client Error: {reason} for url: {self.url}"
+ )
+
+ elif 500 <= self.status_code < 600:
+ http_error_msg = (
+ f"{self.status_code} Server Error: {reason} for url: {self.url}"
+ )
+
+ if http_error_msg:
+ raise HTTPError(http_error_msg, response=self)
+
+ def close(self):
+ """Releases the connection back to the pool. Once this method has been
+ called the underlying ``raw`` object must not be accessed again.
+
+ *Note: Should not normally need to be called explicitly.*
+ """
+ if not self._content_consumed:
+ self.raw.close()
+
+ release_conn = getattr(self.raw, "release_conn", None)
+ if release_conn is not None:
+ release_conn()
diff --git a/testcline/lib/python3.12/site-packages/requests/packages.py b/testcline/lib/python3.12/site-packages/requests/packages.py
new file mode 100644
index 0000000..5ab3d8e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/packages.py
@@ -0,0 +1,23 @@
+import sys
+
+from .compat import chardet
+
+# This code exists for backwards compatibility reasons.
+# I don't like it either. Just look the other way. :)
+
+for package in ("urllib3", "idna"):
+ locals()[package] = __import__(package)
+ # This traversal is apparently necessary such that the identities are
+ # preserved (requests.packages.urllib3.* is urllib3.*)
+ for mod in list(sys.modules):
+ if mod == package or mod.startswith(f"{package}."):
+ sys.modules[f"requests.packages.{mod}"] = sys.modules[mod]
+
+if chardet is not None:
+ target = chardet.__name__
+ for mod in list(sys.modules):
+ if mod == target or mod.startswith(f"{target}."):
+ imported_mod = sys.modules[mod]
+ sys.modules[f"requests.packages.{mod}"] = imported_mod
+ mod = mod.replace(target, "chardet")
+ sys.modules[f"requests.packages.{mod}"] = imported_mod
diff --git a/testcline/lib/python3.12/site-packages/requests/sessions.py b/testcline/lib/python3.12/site-packages/requests/sessions.py
new file mode 100644
index 0000000..b387bc3
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/sessions.py
@@ -0,0 +1,831 @@
+"""
+requests.sessions
+~~~~~~~~~~~~~~~~~
+
+This module provides a Session object to manage and persist settings across
+requests (cookies, auth, proxies).
+"""
+import os
+import sys
+import time
+from collections import OrderedDict
+from datetime import timedelta
+
+from ._internal_utils import to_native_string
+from .adapters import HTTPAdapter
+from .auth import _basic_auth_str
+from .compat import Mapping, cookielib, urljoin, urlparse
+from .cookies import (
+ RequestsCookieJar,
+ cookiejar_from_dict,
+ extract_cookies_to_jar,
+ merge_cookies,
+)
+from .exceptions import (
+ ChunkedEncodingError,
+ ContentDecodingError,
+ InvalidSchema,
+ TooManyRedirects,
+)
+from .hooks import default_hooks, dispatch_hook
+
+# formerly defined here, reexposed here for backward compatibility
+from .models import ( # noqa: F401
+ DEFAULT_REDIRECT_LIMIT,
+ REDIRECT_STATI,
+ PreparedRequest,
+ Request,
+)
+from .status_codes import codes
+from .structures import CaseInsensitiveDict
+from .utils import ( # noqa: F401
+ DEFAULT_PORTS,
+ default_headers,
+ get_auth_from_url,
+ get_environ_proxies,
+ get_netrc_auth,
+ requote_uri,
+ resolve_proxies,
+ rewind_body,
+ should_bypass_proxies,
+ to_key_val_list,
+)
+
+# Preferred clock, based on which one is more accurate on a given system.
+if sys.platform == "win32":
+ preferred_clock = time.perf_counter
+else:
+ preferred_clock = time.time
+
+
+def merge_setting(request_setting, session_setting, dict_class=OrderedDict):
+ """Determines appropriate setting for a given request, taking into account
+ the explicit setting on that request, and the setting in the session. If a
+ setting is a dictionary, they will be merged together using `dict_class`
+ """
+
+ if session_setting is None:
+ return request_setting
+
+ if request_setting is None:
+ return session_setting
+
+ # Bypass if not a dictionary (e.g. verify)
+ if not (
+ isinstance(session_setting, Mapping) and isinstance(request_setting, Mapping)
+ ):
+ return request_setting
+
+ merged_setting = dict_class(to_key_val_list(session_setting))
+ merged_setting.update(to_key_val_list(request_setting))
+
+ # Remove keys that are set to None. Extract keys first to avoid altering
+ # the dictionary during iteration.
+ none_keys = [k for (k, v) in merged_setting.items() if v is None]
+ for key in none_keys:
+ del merged_setting[key]
+
+ return merged_setting
+
+
+def merge_hooks(request_hooks, session_hooks, dict_class=OrderedDict):
+ """Properly merges both requests and session hooks.
+
+ This is necessary because when request_hooks == {'response': []}, the
+ merge breaks Session hooks entirely.
+ """
+ if session_hooks is None or session_hooks.get("response") == []:
+ return request_hooks
+
+ if request_hooks is None or request_hooks.get("response") == []:
+ return session_hooks
+
+ return merge_setting(request_hooks, session_hooks, dict_class)
+
+
+class SessionRedirectMixin:
+ def get_redirect_target(self, resp):
+ """Receives a Response. Returns a redirect URI or ``None``"""
+ # Due to the nature of how requests processes redirects this method will
+ # be called at least once upon the original response and at least twice
+ # on each subsequent redirect response (if any).
+ # If a custom mixin is used to handle this logic, it may be advantageous
+ # to cache the redirect location onto the response object as a private
+ # attribute.
+ if resp.is_redirect:
+ location = resp.headers["location"]
+ # Currently the underlying http module on py3 decode headers
+ # in latin1, but empirical evidence suggests that latin1 is very
+ # rarely used with non-ASCII characters in HTTP headers.
+ # It is more likely to get UTF8 header rather than latin1.
+ # This causes incorrect handling of UTF8 encoded location headers.
+ # To solve this, we re-encode the location in latin1.
+ location = location.encode("latin1")
+ return to_native_string(location, "utf8")
+ return None
+
+ def should_strip_auth(self, old_url, new_url):
+ """Decide whether Authorization header should be removed when redirecting"""
+ old_parsed = urlparse(old_url)
+ new_parsed = urlparse(new_url)
+ if old_parsed.hostname != new_parsed.hostname:
+ return True
+ # Special case: allow http -> https redirect when using the standard
+ # ports. This isn't specified by RFC 7235, but is kept to avoid
+ # breaking backwards compatibility with older versions of requests
+ # that allowed any redirects on the same host.
+ if (
+ old_parsed.scheme == "http"
+ and old_parsed.port in (80, None)
+ and new_parsed.scheme == "https"
+ and new_parsed.port in (443, None)
+ ):
+ return False
+
+ # Handle default port usage corresponding to scheme.
+ changed_port = old_parsed.port != new_parsed.port
+ changed_scheme = old_parsed.scheme != new_parsed.scheme
+ default_port = (DEFAULT_PORTS.get(old_parsed.scheme, None), None)
+ if (
+ not changed_scheme
+ and old_parsed.port in default_port
+ and new_parsed.port in default_port
+ ):
+ return False
+
+ # Standard case: root URI must match
+ return changed_port or changed_scheme
+
+ def resolve_redirects(
+ self,
+ resp,
+ req,
+ stream=False,
+ timeout=None,
+ verify=True,
+ cert=None,
+ proxies=None,
+ yield_requests=False,
+ **adapter_kwargs,
+ ):
+ """Receives a Response. Returns a generator of Responses or Requests."""
+
+ hist = [] # keep track of history
+
+ url = self.get_redirect_target(resp)
+ previous_fragment = urlparse(req.url).fragment
+ while url:
+ prepared_request = req.copy()
+
+ # Update history and keep track of redirects.
+ # resp.history must ignore the original request in this loop
+ hist.append(resp)
+ resp.history = hist[1:]
+
+ try:
+ resp.content # Consume socket so it can be released
+ except (ChunkedEncodingError, ContentDecodingError, RuntimeError):
+ resp.raw.read(decode_content=False)
+
+ if len(resp.history) >= self.max_redirects:
+ raise TooManyRedirects(
+ f"Exceeded {self.max_redirects} redirects.", response=resp
+ )
+
+ # Release the connection back into the pool.
+ resp.close()
+
+ # Handle redirection without scheme (see: RFC 1808 Section 4)
+ if url.startswith("//"):
+ parsed_rurl = urlparse(resp.url)
+ url = ":".join([to_native_string(parsed_rurl.scheme), url])
+
+ # Normalize url case and attach previous fragment if needed (RFC 7231 7.1.2)
+ parsed = urlparse(url)
+ if parsed.fragment == "" and previous_fragment:
+ parsed = parsed._replace(fragment=previous_fragment)
+ elif parsed.fragment:
+ previous_fragment = parsed.fragment
+ url = parsed.geturl()
+
+ # Facilitate relative 'location' headers, as allowed by RFC 7231.
+ # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource')
+ # Compliant with RFC3986, we percent encode the url.
+ if not parsed.netloc:
+ url = urljoin(resp.url, requote_uri(url))
+ else:
+ url = requote_uri(url)
+
+ prepared_request.url = to_native_string(url)
+
+ self.rebuild_method(prepared_request, resp)
+
+ # https://github.com/psf/requests/issues/1084
+ if resp.status_code not in (
+ codes.temporary_redirect,
+ codes.permanent_redirect,
+ ):
+ # https://github.com/psf/requests/issues/3490
+ purged_headers = ("Content-Length", "Content-Type", "Transfer-Encoding")
+ for header in purged_headers:
+ prepared_request.headers.pop(header, None)
+ prepared_request.body = None
+
+ headers = prepared_request.headers
+ headers.pop("Cookie", None)
+
+ # Extract any cookies sent on the response to the cookiejar
+ # in the new request. Because we've mutated our copied prepared
+ # request, use the old one that we haven't yet touched.
+ extract_cookies_to_jar(prepared_request._cookies, req, resp.raw)
+ merge_cookies(prepared_request._cookies, self.cookies)
+ prepared_request.prepare_cookies(prepared_request._cookies)
+
+ # Rebuild auth and proxy information.
+ proxies = self.rebuild_proxies(prepared_request, proxies)
+ self.rebuild_auth(prepared_request, resp)
+
+ # A failed tell() sets `_body_position` to `object()`. This non-None
+ # value ensures `rewindable` will be True, allowing us to raise an
+ # UnrewindableBodyError, instead of hanging the connection.
+ rewindable = prepared_request._body_position is not None and (
+ "Content-Length" in headers or "Transfer-Encoding" in headers
+ )
+
+ # Attempt to rewind consumed file-like object.
+ if rewindable:
+ rewind_body(prepared_request)
+
+ # Override the original request.
+ req = prepared_request
+
+ if yield_requests:
+ yield req
+ else:
+ resp = self.send(
+ req,
+ stream=stream,
+ timeout=timeout,
+ verify=verify,
+ cert=cert,
+ proxies=proxies,
+ allow_redirects=False,
+ **adapter_kwargs,
+ )
+
+ extract_cookies_to_jar(self.cookies, prepared_request, resp.raw)
+
+ # extract redirect url, if any, for the next loop
+ url = self.get_redirect_target(resp)
+ yield resp
+
+ def rebuild_auth(self, prepared_request, response):
+ """When being redirected we may want to strip authentication from the
+ request to avoid leaking credentials. This method intelligently removes
+ and reapplies authentication where possible to avoid credential loss.
+ """
+ headers = prepared_request.headers
+ url = prepared_request.url
+
+ if "Authorization" in headers and self.should_strip_auth(
+ response.request.url, url
+ ):
+ # If we get redirected to a new host, we should strip out any
+ # authentication headers.
+ del headers["Authorization"]
+
+ # .netrc might have more auth for us on our new host.
+ new_auth = get_netrc_auth(url) if self.trust_env else None
+ if new_auth is not None:
+ prepared_request.prepare_auth(new_auth)
+
+ def rebuild_proxies(self, prepared_request, proxies):
+ """This method re-evaluates the proxy configuration by considering the
+ environment variables. If we are redirected to a URL covered by
+ NO_PROXY, we strip the proxy configuration. Otherwise, we set missing
+ proxy keys for this URL (in case they were stripped by a previous
+ redirect).
+
+ This method also replaces the Proxy-Authorization header where
+ necessary.
+
+ :rtype: dict
+ """
+ headers = prepared_request.headers
+ scheme = urlparse(prepared_request.url).scheme
+ new_proxies = resolve_proxies(prepared_request, proxies, self.trust_env)
+
+ if "Proxy-Authorization" in headers:
+ del headers["Proxy-Authorization"]
+
+ try:
+ username, password = get_auth_from_url(new_proxies[scheme])
+ except KeyError:
+ username, password = None, None
+
+ # urllib3 handles proxy authorization for us in the standard adapter.
+ # Avoid appending this to TLS tunneled requests where it may be leaked.
+ if not scheme.startswith("https") and username and password:
+ headers["Proxy-Authorization"] = _basic_auth_str(username, password)
+
+ return new_proxies
+
+ def rebuild_method(self, prepared_request, response):
+ """When being redirected we may want to change the method of the request
+ based on certain specs or browser behavior.
+ """
+ method = prepared_request.method
+
+ # https://tools.ietf.org/html/rfc7231#section-6.4.4
+ if response.status_code == codes.see_other and method != "HEAD":
+ method = "GET"
+
+ # Do what the browsers do, despite standards...
+ # First, turn 302s into GETs.
+ if response.status_code == codes.found and method != "HEAD":
+ method = "GET"
+
+ # Second, if a POST is responded to with a 301, turn it into a GET.
+ # This bizarre behaviour is explained in Issue 1704.
+ if response.status_code == codes.moved and method == "POST":
+ method = "GET"
+
+ prepared_request.method = method
+
+
+class Session(SessionRedirectMixin):
+ """A Requests session.
+
+ Provides cookie persistence, connection-pooling, and configuration.
+
+ Basic Usage::
+
+ >>> import requests
+ >>> s = requests.Session()
+ >>> s.get('https://httpbin.org/get')
+
+
+ Or as a context manager::
+
+ >>> with requests.Session() as s:
+ ... s.get('https://httpbin.org/get')
+
+ """
+
+ __attrs__ = [
+ "headers",
+ "cookies",
+ "auth",
+ "proxies",
+ "hooks",
+ "params",
+ "verify",
+ "cert",
+ "adapters",
+ "stream",
+ "trust_env",
+ "max_redirects",
+ ]
+
+ def __init__(self):
+ #: A case-insensitive dictionary of headers to be sent on each
+ #: :class:`Request ` sent from this
+ #: :class:`Session `.
+ self.headers = default_headers()
+
+ #: Default Authentication tuple or object to attach to
+ #: :class:`Request `.
+ self.auth = None
+
+ #: Dictionary mapping protocol or protocol and host to the URL of the proxy
+ #: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to
+ #: be used on each :class:`Request `.
+ self.proxies = {}
+
+ #: Event-handling hooks.
+ self.hooks = default_hooks()
+
+ #: Dictionary of querystring data to attach to each
+ #: :class:`Request `. The dictionary values may be lists for
+ #: representing multivalued query parameters.
+ self.params = {}
+
+ #: Stream response content default.
+ self.stream = False
+
+ #: SSL Verification default.
+ #: Defaults to `True`, requiring requests to verify the TLS certificate at the
+ #: remote end.
+ #: If verify is set to `False`, requests will accept any TLS certificate
+ #: presented by the server, and will ignore hostname mismatches and/or
+ #: expired certificates, which will make your application vulnerable to
+ #: man-in-the-middle (MitM) attacks.
+ #: Only set this to `False` for testing.
+ self.verify = True
+
+ #: SSL client certificate default, if String, path to ssl client
+ #: cert file (.pem). If Tuple, ('cert', 'key') pair.
+ self.cert = None
+
+ #: Maximum number of redirects allowed. If the request exceeds this
+ #: limit, a :class:`TooManyRedirects` exception is raised.
+ #: This defaults to requests.models.DEFAULT_REDIRECT_LIMIT, which is
+ #: 30.
+ self.max_redirects = DEFAULT_REDIRECT_LIMIT
+
+ #: Trust environment settings for proxy configuration, default
+ #: authentication and similar.
+ self.trust_env = True
+
+ #: A CookieJar containing all currently outstanding cookies set on this
+ #: session. By default it is a
+ #: :class:`RequestsCookieJar `, but
+ #: may be any other ``cookielib.CookieJar`` compatible object.
+ self.cookies = cookiejar_from_dict({})
+
+ # Default connection adapters.
+ self.adapters = OrderedDict()
+ self.mount("https://", HTTPAdapter())
+ self.mount("http://", HTTPAdapter())
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ self.close()
+
+ def prepare_request(self, request):
+ """Constructs a :class:`PreparedRequest ` for
+ transmission and returns it. The :class:`PreparedRequest` has settings
+ merged from the :class:`Request ` instance and those of the
+ :class:`Session`.
+
+ :param request: :class:`Request` instance to prepare with this
+ session's settings.
+ :rtype: requests.PreparedRequest
+ """
+ cookies = request.cookies or {}
+
+ # Bootstrap CookieJar.
+ if not isinstance(cookies, cookielib.CookieJar):
+ cookies = cookiejar_from_dict(cookies)
+
+ # Merge with session cookies
+ merged_cookies = merge_cookies(
+ merge_cookies(RequestsCookieJar(), self.cookies), cookies
+ )
+
+ # Set environment's basic authentication if not explicitly set.
+ auth = request.auth
+ if self.trust_env and not auth and not self.auth:
+ auth = get_netrc_auth(request.url)
+
+ p = PreparedRequest()
+ p.prepare(
+ method=request.method.upper(),
+ url=request.url,
+ files=request.files,
+ data=request.data,
+ json=request.json,
+ headers=merge_setting(
+ request.headers, self.headers, dict_class=CaseInsensitiveDict
+ ),
+ params=merge_setting(request.params, self.params),
+ auth=merge_setting(auth, self.auth),
+ cookies=merged_cookies,
+ hooks=merge_hooks(request.hooks, self.hooks),
+ )
+ return p
+
+ def request(
+ self,
+ method,
+ url,
+ params=None,
+ data=None,
+ headers=None,
+ cookies=None,
+ files=None,
+ auth=None,
+ timeout=None,
+ allow_redirects=True,
+ proxies=None,
+ hooks=None,
+ stream=None,
+ verify=None,
+ cert=None,
+ json=None,
+ ):
+ """Constructs a :class:`Request `, prepares it and sends it.
+ Returns :class:`Response ` object.
+
+ :param method: method for the new :class:`Request` object.
+ :param url: URL for the new :class:`Request` object.
+ :param params: (optional) Dictionary or bytes to be sent in the query
+ string for the :class:`Request`.
+ :param data: (optional) Dictionary, list of tuples, bytes, or file-like
+ object to send in the body of the :class:`Request`.
+ :param json: (optional) json to send in the body of the
+ :class:`Request`.
+ :param headers: (optional) Dictionary of HTTP Headers to send with the
+ :class:`Request`.
+ :param cookies: (optional) Dict or CookieJar object to send with the
+ :class:`Request`.
+ :param files: (optional) Dictionary of ``'filename': file-like-objects``
+ for multipart encoding upload.
+ :param auth: (optional) Auth tuple or callable to enable
+ Basic/Digest/Custom HTTP Auth.
+ :param timeout: (optional) How long to wait for the server to send
+ data before giving up, as a float, or a :ref:`(connect timeout,
+ read timeout) ` tuple.
+ :type timeout: float or tuple
+ :param allow_redirects: (optional) Set to True by default.
+ :type allow_redirects: bool
+ :param proxies: (optional) Dictionary mapping protocol or protocol and
+ hostname to the URL of the proxy.
+ :param hooks: (optional) Dictionary mapping hook name to one event or
+ list of events, event must be callable.
+ :param stream: (optional) whether to immediately download the response
+ content. Defaults to ``False``.
+ :param verify: (optional) Either a boolean, in which case it controls whether we verify
+ the server's TLS certificate, or a string, in which case it must be a path
+ to a CA bundle to use. Defaults to ``True``. When set to
+ ``False``, requests will accept any TLS certificate presented by
+ the server, and will ignore hostname mismatches and/or expired
+ certificates, which will make your application vulnerable to
+ man-in-the-middle (MitM) attacks. Setting verify to ``False``
+ may be useful during local development or testing.
+ :param cert: (optional) if String, path to ssl client cert file (.pem).
+ If Tuple, ('cert', 'key') pair.
+ :rtype: requests.Response
+ """
+ # Create the Request.
+ req = Request(
+ method=method.upper(),
+ url=url,
+ headers=headers,
+ files=files,
+ data=data or {},
+ json=json,
+ params=params or {},
+ auth=auth,
+ cookies=cookies,
+ hooks=hooks,
+ )
+ prep = self.prepare_request(req)
+
+ proxies = proxies or {}
+
+ settings = self.merge_environment_settings(
+ prep.url, proxies, stream, verify, cert
+ )
+
+ # Send the request.
+ send_kwargs = {
+ "timeout": timeout,
+ "allow_redirects": allow_redirects,
+ }
+ send_kwargs.update(settings)
+ resp = self.send(prep, **send_kwargs)
+
+ return resp
+
+ def get(self, url, **kwargs):
+ r"""Sends a GET request. Returns :class:`Response` object.
+
+ :param url: URL for the new :class:`Request` object.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :rtype: requests.Response
+ """
+
+ kwargs.setdefault("allow_redirects", True)
+ return self.request("GET", url, **kwargs)
+
+ def options(self, url, **kwargs):
+ r"""Sends a OPTIONS request. Returns :class:`Response` object.
+
+ :param url: URL for the new :class:`Request` object.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :rtype: requests.Response
+ """
+
+ kwargs.setdefault("allow_redirects", True)
+ return self.request("OPTIONS", url, **kwargs)
+
+ def head(self, url, **kwargs):
+ r"""Sends a HEAD request. Returns :class:`Response` object.
+
+ :param url: URL for the new :class:`Request` object.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :rtype: requests.Response
+ """
+
+ kwargs.setdefault("allow_redirects", False)
+ return self.request("HEAD", url, **kwargs)
+
+ def post(self, url, data=None, json=None, **kwargs):
+ r"""Sends a POST request. Returns :class:`Response` object.
+
+ :param url: URL for the new :class:`Request` object.
+ :param data: (optional) Dictionary, list of tuples, bytes, or file-like
+ object to send in the body of the :class:`Request`.
+ :param json: (optional) json to send in the body of the :class:`Request`.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :rtype: requests.Response
+ """
+
+ return self.request("POST", url, data=data, json=json, **kwargs)
+
+ def put(self, url, data=None, **kwargs):
+ r"""Sends a PUT request. Returns :class:`Response` object.
+
+ :param url: URL for the new :class:`Request` object.
+ :param data: (optional) Dictionary, list of tuples, bytes, or file-like
+ object to send in the body of the :class:`Request`.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :rtype: requests.Response
+ """
+
+ return self.request("PUT", url, data=data, **kwargs)
+
+ def patch(self, url, data=None, **kwargs):
+ r"""Sends a PATCH request. Returns :class:`Response` object.
+
+ :param url: URL for the new :class:`Request` object.
+ :param data: (optional) Dictionary, list of tuples, bytes, or file-like
+ object to send in the body of the :class:`Request`.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :rtype: requests.Response
+ """
+
+ return self.request("PATCH", url, data=data, **kwargs)
+
+ def delete(self, url, **kwargs):
+ r"""Sends a DELETE request. Returns :class:`Response` object.
+
+ :param url: URL for the new :class:`Request` object.
+ :param \*\*kwargs: Optional arguments that ``request`` takes.
+ :rtype: requests.Response
+ """
+
+ return self.request("DELETE", url, **kwargs)
+
+ def send(self, request, **kwargs):
+ """Send a given PreparedRequest.
+
+ :rtype: requests.Response
+ """
+ # Set defaults that the hooks can utilize to ensure they always have
+ # the correct parameters to reproduce the previous request.
+ kwargs.setdefault("stream", self.stream)
+ kwargs.setdefault("verify", self.verify)
+ kwargs.setdefault("cert", self.cert)
+ if "proxies" not in kwargs:
+ kwargs["proxies"] = resolve_proxies(request, self.proxies, self.trust_env)
+
+ # It's possible that users might accidentally send a Request object.
+ # Guard against that specific failure case.
+ if isinstance(request, Request):
+ raise ValueError("You can only send PreparedRequests.")
+
+ # Set up variables needed for resolve_redirects and dispatching of hooks
+ allow_redirects = kwargs.pop("allow_redirects", True)
+ stream = kwargs.get("stream")
+ hooks = request.hooks
+
+ # Get the appropriate adapter to use
+ adapter = self.get_adapter(url=request.url)
+
+ # Start time (approximately) of the request
+ start = preferred_clock()
+
+ # Send the request
+ r = adapter.send(request, **kwargs)
+
+ # Total elapsed time of the request (approximately)
+ elapsed = preferred_clock() - start
+ r.elapsed = timedelta(seconds=elapsed)
+
+ # Response manipulation hooks
+ r = dispatch_hook("response", hooks, r, **kwargs)
+
+ # Persist cookies
+ if r.history:
+ # If the hooks create history then we want those cookies too
+ for resp in r.history:
+ extract_cookies_to_jar(self.cookies, resp.request, resp.raw)
+
+ extract_cookies_to_jar(self.cookies, request, r.raw)
+
+ # Resolve redirects if allowed.
+ if allow_redirects:
+ # Redirect resolving generator.
+ gen = self.resolve_redirects(r, request, **kwargs)
+ history = [resp for resp in gen]
+ else:
+ history = []
+
+ # Shuffle things around if there's history.
+ if history:
+ # Insert the first (original) request at the start
+ history.insert(0, r)
+ # Get the last request made
+ r = history.pop()
+ r.history = history
+
+ # If redirects aren't being followed, store the response on the Request for Response.next().
+ if not allow_redirects:
+ try:
+ r._next = next(
+ self.resolve_redirects(r, request, yield_requests=True, **kwargs)
+ )
+ except StopIteration:
+ pass
+
+ if not stream:
+ r.content
+
+ return r
+
+ def merge_environment_settings(self, url, proxies, stream, verify, cert):
+ """
+ Check the environment and merge it with some settings.
+
+ :rtype: dict
+ """
+ # Gather clues from the surrounding environment.
+ if self.trust_env:
+ # Set environment's proxies.
+ no_proxy = proxies.get("no_proxy") if proxies is not None else None
+ env_proxies = get_environ_proxies(url, no_proxy=no_proxy)
+ for k, v in env_proxies.items():
+ proxies.setdefault(k, v)
+
+ # Look for requests environment configuration
+ # and be compatible with cURL.
+ if verify is True or verify is None:
+ verify = (
+ os.environ.get("REQUESTS_CA_BUNDLE")
+ or os.environ.get("CURL_CA_BUNDLE")
+ or verify
+ )
+
+ # Merge all the kwargs.
+ proxies = merge_setting(proxies, self.proxies)
+ stream = merge_setting(stream, self.stream)
+ verify = merge_setting(verify, self.verify)
+ cert = merge_setting(cert, self.cert)
+
+ return {"proxies": proxies, "stream": stream, "verify": verify, "cert": cert}
+
+ def get_adapter(self, url):
+ """
+ Returns the appropriate connection adapter for the given URL.
+
+ :rtype: requests.adapters.BaseAdapter
+ """
+ for prefix, adapter in self.adapters.items():
+ if url.lower().startswith(prefix.lower()):
+ return adapter
+
+ # Nothing matches :-/
+ raise InvalidSchema(f"No connection adapters were found for {url!r}")
+
+ def close(self):
+ """Closes all adapters and as such the session"""
+ for v in self.adapters.values():
+ v.close()
+
+ def mount(self, prefix, adapter):
+ """Registers a connection adapter to a prefix.
+
+ Adapters are sorted in descending order by prefix length.
+ """
+ self.adapters[prefix] = adapter
+ keys_to_move = [k for k in self.adapters if len(k) < len(prefix)]
+
+ for key in keys_to_move:
+ self.adapters[key] = self.adapters.pop(key)
+
+ def __getstate__(self):
+ state = {attr: getattr(self, attr, None) for attr in self.__attrs__}
+ return state
+
+ def __setstate__(self, state):
+ for attr, value in state.items():
+ setattr(self, attr, value)
+
+
+def session():
+ """
+ Returns a :class:`Session` for context-management.
+
+ .. deprecated:: 1.0.0
+
+ This method has been deprecated since version 1.0.0 and is only kept for
+ backwards compatibility. New code should use :class:`~requests.sessions.Session`
+ to create a session. This may be removed at a future date.
+
+ :rtype: Session
+ """
+ return Session()
diff --git a/testcline/lib/python3.12/site-packages/requests/status_codes.py b/testcline/lib/python3.12/site-packages/requests/status_codes.py
new file mode 100644
index 0000000..c7945a2
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/status_codes.py
@@ -0,0 +1,128 @@
+r"""
+The ``codes`` object defines a mapping from common names for HTTP statuses
+to their numerical codes, accessible either as attributes or as dictionary
+items.
+
+Example::
+
+ >>> import requests
+ >>> requests.codes['temporary_redirect']
+ 307
+ >>> requests.codes.teapot
+ 418
+ >>> requests.codes['\o/']
+ 200
+
+Some codes have multiple names, and both upper- and lower-case versions of
+the names are allowed. For example, ``codes.ok``, ``codes.OK``, and
+``codes.okay`` all correspond to the HTTP status code 200.
+"""
+
+from .structures import LookupDict
+
+_codes = {
+ # Informational.
+ 100: ("continue",),
+ 101: ("switching_protocols",),
+ 102: ("processing", "early-hints"),
+ 103: ("checkpoint",),
+ 122: ("uri_too_long", "request_uri_too_long"),
+ 200: ("ok", "okay", "all_ok", "all_okay", "all_good", "\\o/", "✓"),
+ 201: ("created",),
+ 202: ("accepted",),
+ 203: ("non_authoritative_info", "non_authoritative_information"),
+ 204: ("no_content",),
+ 205: ("reset_content", "reset"),
+ 206: ("partial_content", "partial"),
+ 207: ("multi_status", "multiple_status", "multi_stati", "multiple_stati"),
+ 208: ("already_reported",),
+ 226: ("im_used",),
+ # Redirection.
+ 300: ("multiple_choices",),
+ 301: ("moved_permanently", "moved", "\\o-"),
+ 302: ("found",),
+ 303: ("see_other", "other"),
+ 304: ("not_modified",),
+ 305: ("use_proxy",),
+ 306: ("switch_proxy",),
+ 307: ("temporary_redirect", "temporary_moved", "temporary"),
+ 308: (
+ "permanent_redirect",
+ "resume_incomplete",
+ "resume",
+ ), # "resume" and "resume_incomplete" to be removed in 3.0
+ # Client Error.
+ 400: ("bad_request", "bad"),
+ 401: ("unauthorized",),
+ 402: ("payment_required", "payment"),
+ 403: ("forbidden",),
+ 404: ("not_found", "-o-"),
+ 405: ("method_not_allowed", "not_allowed"),
+ 406: ("not_acceptable",),
+ 407: ("proxy_authentication_required", "proxy_auth", "proxy_authentication"),
+ 408: ("request_timeout", "timeout"),
+ 409: ("conflict",),
+ 410: ("gone",),
+ 411: ("length_required",),
+ 412: ("precondition_failed", "precondition"),
+ 413: ("request_entity_too_large", "content_too_large"),
+ 414: ("request_uri_too_large", "uri_too_long"),
+ 415: ("unsupported_media_type", "unsupported_media", "media_type"),
+ 416: (
+ "requested_range_not_satisfiable",
+ "requested_range",
+ "range_not_satisfiable",
+ ),
+ 417: ("expectation_failed",),
+ 418: ("im_a_teapot", "teapot", "i_am_a_teapot"),
+ 421: ("misdirected_request",),
+ 422: ("unprocessable_entity", "unprocessable", "unprocessable_content"),
+ 423: ("locked",),
+ 424: ("failed_dependency", "dependency"),
+ 425: ("unordered_collection", "unordered", "too_early"),
+ 426: ("upgrade_required", "upgrade"),
+ 428: ("precondition_required", "precondition"),
+ 429: ("too_many_requests", "too_many"),
+ 431: ("header_fields_too_large", "fields_too_large"),
+ 444: ("no_response", "none"),
+ 449: ("retry_with", "retry"),
+ 450: ("blocked_by_windows_parental_controls", "parental_controls"),
+ 451: ("unavailable_for_legal_reasons", "legal_reasons"),
+ 499: ("client_closed_request",),
+ # Server Error.
+ 500: ("internal_server_error", "server_error", "/o\\", "✗"),
+ 501: ("not_implemented",),
+ 502: ("bad_gateway",),
+ 503: ("service_unavailable", "unavailable"),
+ 504: ("gateway_timeout",),
+ 505: ("http_version_not_supported", "http_version"),
+ 506: ("variant_also_negotiates",),
+ 507: ("insufficient_storage",),
+ 509: ("bandwidth_limit_exceeded", "bandwidth"),
+ 510: ("not_extended",),
+ 511: ("network_authentication_required", "network_auth", "network_authentication"),
+}
+
+codes = LookupDict(name="status_codes")
+
+
+def _init():
+ for code, titles in _codes.items():
+ for title in titles:
+ setattr(codes, title, code)
+ if not title.startswith(("\\", "/")):
+ setattr(codes, title.upper(), code)
+
+ def doc(code):
+ names = ", ".join(f"``{n}``" for n in _codes[code])
+ return "* %d: %s" % (code, names)
+
+ global __doc__
+ __doc__ = (
+ __doc__ + "\n" + "\n".join(doc(code) for code in sorted(_codes))
+ if __doc__ is not None
+ else None
+ )
+
+
+_init()
diff --git a/testcline/lib/python3.12/site-packages/requests/structures.py b/testcline/lib/python3.12/site-packages/requests/structures.py
new file mode 100644
index 0000000..188e13e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/structures.py
@@ -0,0 +1,99 @@
+"""
+requests.structures
+~~~~~~~~~~~~~~~~~~~
+
+Data structures that power Requests.
+"""
+
+from collections import OrderedDict
+
+from .compat import Mapping, MutableMapping
+
+
+class CaseInsensitiveDict(MutableMapping):
+ """A case-insensitive ``dict``-like object.
+
+ Implements all methods and operations of
+ ``MutableMapping`` as well as dict's ``copy``. Also
+ provides ``lower_items``.
+
+ All keys are expected to be strings. The structure remembers the
+ case of the last key to be set, and ``iter(instance)``,
+ ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()``
+ will contain case-sensitive keys. However, querying and contains
+ testing is case insensitive::
+
+ cid = CaseInsensitiveDict()
+ cid['Accept'] = 'application/json'
+ cid['aCCEPT'] == 'application/json' # True
+ list(cid) == ['Accept'] # True
+
+ For example, ``headers['content-encoding']`` will return the
+ value of a ``'Content-Encoding'`` response header, regardless
+ of how the header name was originally stored.
+
+ If the constructor, ``.update``, or equality comparison
+ operations are given keys that have equal ``.lower()``s, the
+ behavior is undefined.
+ """
+
+ def __init__(self, data=None, **kwargs):
+ self._store = OrderedDict()
+ if data is None:
+ data = {}
+ self.update(data, **kwargs)
+
+ def __setitem__(self, key, value):
+ # Use the lowercased key for lookups, but store the actual
+ # key alongside the value.
+ self._store[key.lower()] = (key, value)
+
+ def __getitem__(self, key):
+ return self._store[key.lower()][1]
+
+ def __delitem__(self, key):
+ del self._store[key.lower()]
+
+ def __iter__(self):
+ return (casedkey for casedkey, mappedvalue in self._store.values())
+
+ def __len__(self):
+ return len(self._store)
+
+ def lower_items(self):
+ """Like iteritems(), but with all lowercase keys."""
+ return ((lowerkey, keyval[1]) for (lowerkey, keyval) in self._store.items())
+
+ def __eq__(self, other):
+ if isinstance(other, Mapping):
+ other = CaseInsensitiveDict(other)
+ else:
+ return NotImplemented
+ # Compare insensitively
+ return dict(self.lower_items()) == dict(other.lower_items())
+
+ # Copy is required
+ def copy(self):
+ return CaseInsensitiveDict(self._store.values())
+
+ def __repr__(self):
+ return str(dict(self.items()))
+
+
+class LookupDict(dict):
+ """Dictionary lookup object."""
+
+ def __init__(self, name=None):
+ self.name = name
+ super().__init__()
+
+ def __repr__(self):
+ return f""
+
+ def __getitem__(self, key):
+ # We allow fall-through here, so values default to None
+
+ return self.__dict__.get(key, None)
+
+ def get(self, key, default=None):
+ return self.__dict__.get(key, default)
diff --git a/testcline/lib/python3.12/site-packages/requests/utils.py b/testcline/lib/python3.12/site-packages/requests/utils.py
new file mode 100644
index 0000000..ae6c42f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/requests/utils.py
@@ -0,0 +1,1096 @@
+"""
+requests.utils
+~~~~~~~~~~~~~~
+
+This module provides utility functions that are used within Requests
+that are also useful for external consumption.
+"""
+
+import codecs
+import contextlib
+import io
+import os
+import re
+import socket
+import struct
+import sys
+import tempfile
+import warnings
+import zipfile
+from collections import OrderedDict
+
+from urllib3.util import make_headers, parse_url
+
+from . import certs
+from .__version__ import __version__
+
+# to_native_string is unused here, but imported here for backwards compatibility
+from ._internal_utils import ( # noqa: F401
+ _HEADER_VALIDATORS_BYTE,
+ _HEADER_VALIDATORS_STR,
+ HEADER_VALIDATORS,
+ to_native_string,
+)
+from .compat import (
+ Mapping,
+ basestring,
+ bytes,
+ getproxies,
+ getproxies_environment,
+ integer_types,
+)
+from .compat import parse_http_list as _parse_list_header
+from .compat import (
+ proxy_bypass,
+ proxy_bypass_environment,
+ quote,
+ str,
+ unquote,
+ urlparse,
+ urlunparse,
+)
+from .cookies import cookiejar_from_dict
+from .exceptions import (
+ FileModeWarning,
+ InvalidHeader,
+ InvalidURL,
+ UnrewindableBodyError,
+)
+from .structures import CaseInsensitiveDict
+
+NETRC_FILES = (".netrc", "_netrc")
+
+DEFAULT_CA_BUNDLE_PATH = certs.where()
+
+DEFAULT_PORTS = {"http": 80, "https": 443}
+
+# Ensure that ', ' is used to preserve previous delimiter behavior.
+DEFAULT_ACCEPT_ENCODING = ", ".join(
+ re.split(r",\s*", make_headers(accept_encoding=True)["accept-encoding"])
+)
+
+
+if sys.platform == "win32":
+ # provide a proxy_bypass version on Windows without DNS lookups
+
+ def proxy_bypass_registry(host):
+ try:
+ import winreg
+ except ImportError:
+ return False
+
+ try:
+ internetSettings = winreg.OpenKey(
+ winreg.HKEY_CURRENT_USER,
+ r"Software\Microsoft\Windows\CurrentVersion\Internet Settings",
+ )
+ # ProxyEnable could be REG_SZ or REG_DWORD, normalizing it
+ proxyEnable = int(winreg.QueryValueEx(internetSettings, "ProxyEnable")[0])
+ # ProxyOverride is almost always a string
+ proxyOverride = winreg.QueryValueEx(internetSettings, "ProxyOverride")[0]
+ except (OSError, ValueError):
+ return False
+ if not proxyEnable or not proxyOverride:
+ return False
+
+ # make a check value list from the registry entry: replace the
+ # '' string by the localhost entry and the corresponding
+ # canonical entry.
+ proxyOverride = proxyOverride.split(";")
+ # filter out empty strings to avoid re.match return true in the following code.
+ proxyOverride = filter(None, proxyOverride)
+ # now check if we match one of the registry values.
+ for test in proxyOverride:
+ if test == "":
+ if "." not in host:
+ return True
+ test = test.replace(".", r"\.") # mask dots
+ test = test.replace("*", r".*") # change glob sequence
+ test = test.replace("?", r".") # change glob char
+ if re.match(test, host, re.I):
+ return True
+ return False
+
+ def proxy_bypass(host): # noqa
+ """Return True, if the host should be bypassed.
+
+ Checks proxy settings gathered from the environment, if specified,
+ or the registry.
+ """
+ if getproxies_environment():
+ return proxy_bypass_environment(host)
+ else:
+ return proxy_bypass_registry(host)
+
+
+def dict_to_sequence(d):
+ """Returns an internal sequence dictionary update."""
+
+ if hasattr(d, "items"):
+ d = d.items()
+
+ return d
+
+
+def super_len(o):
+ total_length = None
+ current_position = 0
+
+ if isinstance(o, str):
+ o = o.encode("utf-8")
+
+ if hasattr(o, "__len__"):
+ total_length = len(o)
+
+ elif hasattr(o, "len"):
+ total_length = o.len
+
+ elif hasattr(o, "fileno"):
+ try:
+ fileno = o.fileno()
+ except (io.UnsupportedOperation, AttributeError):
+ # AttributeError is a surprising exception, seeing as how we've just checked
+ # that `hasattr(o, 'fileno')`. It happens for objects obtained via
+ # `Tarfile.extractfile()`, per issue 5229.
+ pass
+ else:
+ total_length = os.fstat(fileno).st_size
+
+ # Having used fstat to determine the file length, we need to
+ # confirm that this file was opened up in binary mode.
+ if "b" not in o.mode:
+ warnings.warn(
+ (
+ "Requests has determined the content-length for this "
+ "request using the binary size of the file: however, the "
+ "file has been opened in text mode (i.e. without the 'b' "
+ "flag in the mode). This may lead to an incorrect "
+ "content-length. In Requests 3.0, support will be removed "
+ "for files in text mode."
+ ),
+ FileModeWarning,
+ )
+
+ if hasattr(o, "tell"):
+ try:
+ current_position = o.tell()
+ except OSError:
+ # This can happen in some weird situations, such as when the file
+ # is actually a special file descriptor like stdin. In this
+ # instance, we don't know what the length is, so set it to zero and
+ # let requests chunk it instead.
+ if total_length is not None:
+ current_position = total_length
+ else:
+ if hasattr(o, "seek") and total_length is None:
+ # StringIO and BytesIO have seek but no usable fileno
+ try:
+ # seek to end of file
+ o.seek(0, 2)
+ total_length = o.tell()
+
+ # seek back to current position to support
+ # partially read file-like objects
+ o.seek(current_position or 0)
+ except OSError:
+ total_length = 0
+
+ if total_length is None:
+ total_length = 0
+
+ return max(0, total_length - current_position)
+
+
+def get_netrc_auth(url, raise_errors=False):
+ """Returns the Requests tuple auth for a given url from netrc."""
+
+ netrc_file = os.environ.get("NETRC")
+ if netrc_file is not None:
+ netrc_locations = (netrc_file,)
+ else:
+ netrc_locations = (f"~/{f}" for f in NETRC_FILES)
+
+ try:
+ from netrc import NetrcParseError, netrc
+
+ netrc_path = None
+
+ for f in netrc_locations:
+ try:
+ loc = os.path.expanduser(f)
+ except KeyError:
+ # os.path.expanduser can fail when $HOME is undefined and
+ # getpwuid fails. See https://bugs.python.org/issue20164 &
+ # https://github.com/psf/requests/issues/1846
+ return
+
+ if os.path.exists(loc):
+ netrc_path = loc
+ break
+
+ # Abort early if there isn't one.
+ if netrc_path is None:
+ return
+
+ ri = urlparse(url)
+
+ # Strip port numbers from netloc. This weird `if...encode`` dance is
+ # used for Python 3.2, which doesn't support unicode literals.
+ splitstr = b":"
+ if isinstance(url, str):
+ splitstr = splitstr.decode("ascii")
+ host = ri.netloc.split(splitstr)[0]
+
+ try:
+ _netrc = netrc(netrc_path).authenticators(host)
+ if _netrc:
+ # Return with login / password
+ login_i = 0 if _netrc[0] else 1
+ return (_netrc[login_i], _netrc[2])
+ except (NetrcParseError, OSError):
+ # If there was a parsing error or a permissions issue reading the file,
+ # we'll just skip netrc auth unless explicitly asked to raise errors.
+ if raise_errors:
+ raise
+
+ # App Engine hackiness.
+ except (ImportError, AttributeError):
+ pass
+
+
+def guess_filename(obj):
+ """Tries to guess the filename of the given object."""
+ name = getattr(obj, "name", None)
+ if name and isinstance(name, basestring) and name[0] != "<" and name[-1] != ">":
+ return os.path.basename(name)
+
+
+def extract_zipped_paths(path):
+ """Replace nonexistent paths that look like they refer to a member of a zip
+ archive with the location of an extracted copy of the target, or else
+ just return the provided path unchanged.
+ """
+ if os.path.exists(path):
+ # this is already a valid path, no need to do anything further
+ return path
+
+ # find the first valid part of the provided path and treat that as a zip archive
+ # assume the rest of the path is the name of a member in the archive
+ archive, member = os.path.split(path)
+ while archive and not os.path.exists(archive):
+ archive, prefix = os.path.split(archive)
+ if not prefix:
+ # If we don't check for an empty prefix after the split (in other words, archive remains unchanged after the split),
+ # we _can_ end up in an infinite loop on a rare corner case affecting a small number of users
+ break
+ member = "/".join([prefix, member])
+
+ if not zipfile.is_zipfile(archive):
+ return path
+
+ zip_file = zipfile.ZipFile(archive)
+ if member not in zip_file.namelist():
+ return path
+
+ # we have a valid zip archive and a valid member of that archive
+ tmp = tempfile.gettempdir()
+ extracted_path = os.path.join(tmp, member.split("/")[-1])
+ if not os.path.exists(extracted_path):
+ # use read + write to avoid the creating nested folders, we only want the file, avoids mkdir racing condition
+ with atomic_open(extracted_path) as file_handler:
+ file_handler.write(zip_file.read(member))
+ return extracted_path
+
+
+@contextlib.contextmanager
+def atomic_open(filename):
+ """Write a file to the disk in an atomic fashion"""
+ tmp_descriptor, tmp_name = tempfile.mkstemp(dir=os.path.dirname(filename))
+ try:
+ with os.fdopen(tmp_descriptor, "wb") as tmp_handler:
+ yield tmp_handler
+ os.replace(tmp_name, filename)
+ except BaseException:
+ os.remove(tmp_name)
+ raise
+
+
+def from_key_val_list(value):
+ """Take an object and test to see if it can be represented as a
+ dictionary. Unless it can not be represented as such, return an
+ OrderedDict, e.g.,
+
+ ::
+
+ >>> from_key_val_list([('key', 'val')])
+ OrderedDict([('key', 'val')])
+ >>> from_key_val_list('string')
+ Traceback (most recent call last):
+ ...
+ ValueError: cannot encode objects that are not 2-tuples
+ >>> from_key_val_list({'key': 'val'})
+ OrderedDict([('key', 'val')])
+
+ :rtype: OrderedDict
+ """
+ if value is None:
+ return None
+
+ if isinstance(value, (str, bytes, bool, int)):
+ raise ValueError("cannot encode objects that are not 2-tuples")
+
+ return OrderedDict(value)
+
+
+def to_key_val_list(value):
+ """Take an object and test to see if it can be represented as a
+ dictionary. If it can be, return a list of tuples, e.g.,
+
+ ::
+
+ >>> to_key_val_list([('key', 'val')])
+ [('key', 'val')]
+ >>> to_key_val_list({'key': 'val'})
+ [('key', 'val')]
+ >>> to_key_val_list('string')
+ Traceback (most recent call last):
+ ...
+ ValueError: cannot encode objects that are not 2-tuples
+
+ :rtype: list
+ """
+ if value is None:
+ return None
+
+ if isinstance(value, (str, bytes, bool, int)):
+ raise ValueError("cannot encode objects that are not 2-tuples")
+
+ if isinstance(value, Mapping):
+ value = value.items()
+
+ return list(value)
+
+
+# From mitsuhiko/werkzeug (used with permission).
+def parse_list_header(value):
+ """Parse lists as described by RFC 2068 Section 2.
+
+ In particular, parse comma-separated lists where the elements of
+ the list may include quoted-strings. A quoted-string could
+ contain a comma. A non-quoted string could have quotes in the
+ middle. Quotes are removed automatically after parsing.
+
+ It basically works like :func:`parse_set_header` just that items
+ may appear multiple times and case sensitivity is preserved.
+
+ The return value is a standard :class:`list`:
+
+ >>> parse_list_header('token, "quoted value"')
+ ['token', 'quoted value']
+
+ To create a header from the :class:`list` again, use the
+ :func:`dump_header` function.
+
+ :param value: a string with a list header.
+ :return: :class:`list`
+ :rtype: list
+ """
+ result = []
+ for item in _parse_list_header(value):
+ if item[:1] == item[-1:] == '"':
+ item = unquote_header_value(item[1:-1])
+ result.append(item)
+ return result
+
+
+# From mitsuhiko/werkzeug (used with permission).
+def parse_dict_header(value):
+ """Parse lists of key, value pairs as described by RFC 2068 Section 2 and
+ convert them into a python dict:
+
+ >>> d = parse_dict_header('foo="is a fish", bar="as well"')
+ >>> type(d) is dict
+ True
+ >>> sorted(d.items())
+ [('bar', 'as well'), ('foo', 'is a fish')]
+
+ If there is no value for a key it will be `None`:
+
+ >>> parse_dict_header('key_without_value')
+ {'key_without_value': None}
+
+ To create a header from the :class:`dict` again, use the
+ :func:`dump_header` function.
+
+ :param value: a string with a dict header.
+ :return: :class:`dict`
+ :rtype: dict
+ """
+ result = {}
+ for item in _parse_list_header(value):
+ if "=" not in item:
+ result[item] = None
+ continue
+ name, value = item.split("=", 1)
+ if value[:1] == value[-1:] == '"':
+ value = unquote_header_value(value[1:-1])
+ result[name] = value
+ return result
+
+
+# From mitsuhiko/werkzeug (used with permission).
+def unquote_header_value(value, is_filename=False):
+ r"""Unquotes a header value. (Reversal of :func:`quote_header_value`).
+ This does not use the real unquoting but what browsers are actually
+ using for quoting.
+
+ :param value: the header value to unquote.
+ :rtype: str
+ """
+ if value and value[0] == value[-1] == '"':
+ # this is not the real unquoting, but fixing this so that the
+ # RFC is met will result in bugs with internet explorer and
+ # probably some other browsers as well. IE for example is
+ # uploading files with "C:\foo\bar.txt" as filename
+ value = value[1:-1]
+
+ # if this is a filename and the starting characters look like
+ # a UNC path, then just return the value without quotes. Using the
+ # replace sequence below on a UNC path has the effect of turning
+ # the leading double slash into a single slash and then
+ # _fix_ie_filename() doesn't work correctly. See #458.
+ if not is_filename or value[:2] != "\\\\":
+ return value.replace("\\\\", "\\").replace('\\"', '"')
+ return value
+
+
+def dict_from_cookiejar(cj):
+ """Returns a key/value dictionary from a CookieJar.
+
+ :param cj: CookieJar object to extract cookies from.
+ :rtype: dict
+ """
+
+ cookie_dict = {cookie.name: cookie.value for cookie in cj}
+ return cookie_dict
+
+
+def add_dict_to_cookiejar(cj, cookie_dict):
+ """Returns a CookieJar from a key/value dictionary.
+
+ :param cj: CookieJar to insert cookies into.
+ :param cookie_dict: Dict of key/values to insert into CookieJar.
+ :rtype: CookieJar
+ """
+
+ return cookiejar_from_dict(cookie_dict, cj)
+
+
+def get_encodings_from_content(content):
+ """Returns encodings from given content string.
+
+ :param content: bytestring to extract encodings from.
+ """
+ warnings.warn(
+ (
+ "In requests 3.0, get_encodings_from_content will be removed. For "
+ "more information, please see the discussion on issue #2266. (This"
+ " warning should only appear once.)"
+ ),
+ DeprecationWarning,
+ )
+
+ charset_re = re.compile(r']', flags=re.I)
+ pragma_re = re.compile(r']', flags=re.I)
+ xml_re = re.compile(r'^<\?xml.*?encoding=["\']*(.+?)["\'>]')
+
+ return (
+ charset_re.findall(content)
+ + pragma_re.findall(content)
+ + xml_re.findall(content)
+ )
+
+
+def _parse_content_type_header(header):
+ """Returns content type and parameters from given header
+
+ :param header: string
+ :return: tuple containing content type and dictionary of
+ parameters
+ """
+
+ tokens = header.split(";")
+ content_type, params = tokens[0].strip(), tokens[1:]
+ params_dict = {}
+ items_to_strip = "\"' "
+
+ for param in params:
+ param = param.strip()
+ if param:
+ key, value = param, True
+ index_of_equals = param.find("=")
+ if index_of_equals != -1:
+ key = param[:index_of_equals].strip(items_to_strip)
+ value = param[index_of_equals + 1 :].strip(items_to_strip)
+ params_dict[key.lower()] = value
+ return content_type, params_dict
+
+
+def get_encoding_from_headers(headers):
+ """Returns encodings from given HTTP Header Dict.
+
+ :param headers: dictionary to extract encoding from.
+ :rtype: str
+ """
+
+ content_type = headers.get("content-type")
+
+ if not content_type:
+ return None
+
+ content_type, params = _parse_content_type_header(content_type)
+
+ if "charset" in params:
+ return params["charset"].strip("'\"")
+
+ if "text" in content_type:
+ return "ISO-8859-1"
+
+ if "application/json" in content_type:
+ # Assume UTF-8 based on RFC 4627: https://www.ietf.org/rfc/rfc4627.txt since the charset was unset
+ return "utf-8"
+
+
+def stream_decode_response_unicode(iterator, r):
+ """Stream decodes an iterator."""
+
+ if r.encoding is None:
+ yield from iterator
+ return
+
+ decoder = codecs.getincrementaldecoder(r.encoding)(errors="replace")
+ for chunk in iterator:
+ rv = decoder.decode(chunk)
+ if rv:
+ yield rv
+ rv = decoder.decode(b"", final=True)
+ if rv:
+ yield rv
+
+
+def iter_slices(string, slice_length):
+ """Iterate over slices of a string."""
+ pos = 0
+ if slice_length is None or slice_length <= 0:
+ slice_length = len(string)
+ while pos < len(string):
+ yield string[pos : pos + slice_length]
+ pos += slice_length
+
+
+def get_unicode_from_response(r):
+ """Returns the requested content back in unicode.
+
+ :param r: Response object to get unicode content from.
+
+ Tried:
+
+ 1. charset from content-type
+ 2. fall back and replace all unicode characters
+
+ :rtype: str
+ """
+ warnings.warn(
+ (
+ "In requests 3.0, get_unicode_from_response will be removed. For "
+ "more information, please see the discussion on issue #2266. (This"
+ " warning should only appear once.)"
+ ),
+ DeprecationWarning,
+ )
+
+ tried_encodings = []
+
+ # Try charset from content-type
+ encoding = get_encoding_from_headers(r.headers)
+
+ if encoding:
+ try:
+ return str(r.content, encoding)
+ except UnicodeError:
+ tried_encodings.append(encoding)
+
+ # Fall back:
+ try:
+ return str(r.content, encoding, errors="replace")
+ except TypeError:
+ return r.content
+
+
+# The unreserved URI characters (RFC 3986)
+UNRESERVED_SET = frozenset(
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789-._~"
+)
+
+
+def unquote_unreserved(uri):
+ """Un-escape any percent-escape sequences in a URI that are unreserved
+ characters. This leaves all reserved, illegal and non-ASCII bytes encoded.
+
+ :rtype: str
+ """
+ parts = uri.split("%")
+ for i in range(1, len(parts)):
+ h = parts[i][0:2]
+ if len(h) == 2 and h.isalnum():
+ try:
+ c = chr(int(h, 16))
+ except ValueError:
+ raise InvalidURL(f"Invalid percent-escape sequence: '{h}'")
+
+ if c in UNRESERVED_SET:
+ parts[i] = c + parts[i][2:]
+ else:
+ parts[i] = f"%{parts[i]}"
+ else:
+ parts[i] = f"%{parts[i]}"
+ return "".join(parts)
+
+
+def requote_uri(uri):
+ """Re-quote the given URI.
+
+ This function passes the given URI through an unquote/quote cycle to
+ ensure that it is fully and consistently quoted.
+
+ :rtype: str
+ """
+ safe_with_percent = "!#$%&'()*+,/:;=?@[]~"
+ safe_without_percent = "!#$&'()*+,/:;=?@[]~"
+ try:
+ # Unquote only the unreserved characters
+ # Then quote only illegal characters (do not quote reserved,
+ # unreserved, or '%')
+ return quote(unquote_unreserved(uri), safe=safe_with_percent)
+ except InvalidURL:
+ # We couldn't unquote the given URI, so let's try quoting it, but
+ # there may be unquoted '%'s in the URI. We need to make sure they're
+ # properly quoted so they do not cause issues elsewhere.
+ return quote(uri, safe=safe_without_percent)
+
+
+def address_in_network(ip, net):
+ """This function allows you to check if an IP belongs to a network subnet
+
+ Example: returns True if ip = 192.168.1.1 and net = 192.168.1.0/24
+ returns False if ip = 192.168.1.1 and net = 192.168.100.0/24
+
+ :rtype: bool
+ """
+ ipaddr = struct.unpack("=L", socket.inet_aton(ip))[0]
+ netaddr, bits = net.split("/")
+ netmask = struct.unpack("=L", socket.inet_aton(dotted_netmask(int(bits))))[0]
+ network = struct.unpack("=L", socket.inet_aton(netaddr))[0] & netmask
+ return (ipaddr & netmask) == (network & netmask)
+
+
+def dotted_netmask(mask):
+ """Converts mask from /xx format to xxx.xxx.xxx.xxx
+
+ Example: if mask is 24 function returns 255.255.255.0
+
+ :rtype: str
+ """
+ bits = 0xFFFFFFFF ^ (1 << 32 - mask) - 1
+ return socket.inet_ntoa(struct.pack(">I", bits))
+
+
+def is_ipv4_address(string_ip):
+ """
+ :rtype: bool
+ """
+ try:
+ socket.inet_aton(string_ip)
+ except OSError:
+ return False
+ return True
+
+
+def is_valid_cidr(string_network):
+ """
+ Very simple check of the cidr format in no_proxy variable.
+
+ :rtype: bool
+ """
+ if string_network.count("/") == 1:
+ try:
+ mask = int(string_network.split("/")[1])
+ except ValueError:
+ return False
+
+ if mask < 1 or mask > 32:
+ return False
+
+ try:
+ socket.inet_aton(string_network.split("/")[0])
+ except OSError:
+ return False
+ else:
+ return False
+ return True
+
+
+@contextlib.contextmanager
+def set_environ(env_name, value):
+ """Set the environment variable 'env_name' to 'value'
+
+ Save previous value, yield, and then restore the previous value stored in
+ the environment variable 'env_name'.
+
+ If 'value' is None, do nothing"""
+ value_changed = value is not None
+ if value_changed:
+ old_value = os.environ.get(env_name)
+ os.environ[env_name] = value
+ try:
+ yield
+ finally:
+ if value_changed:
+ if old_value is None:
+ del os.environ[env_name]
+ else:
+ os.environ[env_name] = old_value
+
+
+def should_bypass_proxies(url, no_proxy):
+ """
+ Returns whether we should bypass proxies or not.
+
+ :rtype: bool
+ """
+
+ # Prioritize lowercase environment variables over uppercase
+ # to keep a consistent behaviour with other http projects (curl, wget).
+ def get_proxy(key):
+ return os.environ.get(key) or os.environ.get(key.upper())
+
+ # First check whether no_proxy is defined. If it is, check that the URL
+ # we're getting isn't in the no_proxy list.
+ no_proxy_arg = no_proxy
+ if no_proxy is None:
+ no_proxy = get_proxy("no_proxy")
+ parsed = urlparse(url)
+
+ if parsed.hostname is None:
+ # URLs don't always have hostnames, e.g. file:/// urls.
+ return True
+
+ if no_proxy:
+ # We need to check whether we match here. We need to see if we match
+ # the end of the hostname, both with and without the port.
+ no_proxy = (host for host in no_proxy.replace(" ", "").split(",") if host)
+
+ if is_ipv4_address(parsed.hostname):
+ for proxy_ip in no_proxy:
+ if is_valid_cidr(proxy_ip):
+ if address_in_network(parsed.hostname, proxy_ip):
+ return True
+ elif parsed.hostname == proxy_ip:
+ # If no_proxy ip was defined in plain IP notation instead of cidr notation &
+ # matches the IP of the index
+ return True
+ else:
+ host_with_port = parsed.hostname
+ if parsed.port:
+ host_with_port += f":{parsed.port}"
+
+ for host in no_proxy:
+ if parsed.hostname.endswith(host) or host_with_port.endswith(host):
+ # The URL does match something in no_proxy, so we don't want
+ # to apply the proxies on this URL.
+ return True
+
+ with set_environ("no_proxy", no_proxy_arg):
+ # parsed.hostname can be `None` in cases such as a file URI.
+ try:
+ bypass = proxy_bypass(parsed.hostname)
+ except (TypeError, socket.gaierror):
+ bypass = False
+
+ if bypass:
+ return True
+
+ return False
+
+
+def get_environ_proxies(url, no_proxy=None):
+ """
+ Return a dict of environment proxies.
+
+ :rtype: dict
+ """
+ if should_bypass_proxies(url, no_proxy=no_proxy):
+ return {}
+ else:
+ return getproxies()
+
+
+def select_proxy(url, proxies):
+ """Select a proxy for the url, if applicable.
+
+ :param url: The url being for the request
+ :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs
+ """
+ proxies = proxies or {}
+ urlparts = urlparse(url)
+ if urlparts.hostname is None:
+ return proxies.get(urlparts.scheme, proxies.get("all"))
+
+ proxy_keys = [
+ urlparts.scheme + "://" + urlparts.hostname,
+ urlparts.scheme,
+ "all://" + urlparts.hostname,
+ "all",
+ ]
+ proxy = None
+ for proxy_key in proxy_keys:
+ if proxy_key in proxies:
+ proxy = proxies[proxy_key]
+ break
+
+ return proxy
+
+
+def resolve_proxies(request, proxies, trust_env=True):
+ """This method takes proxy information from a request and configuration
+ input to resolve a mapping of target proxies. This will consider settings
+ such as NO_PROXY to strip proxy configurations.
+
+ :param request: Request or PreparedRequest
+ :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs
+ :param trust_env: Boolean declaring whether to trust environment configs
+
+ :rtype: dict
+ """
+ proxies = proxies if proxies is not None else {}
+ url = request.url
+ scheme = urlparse(url).scheme
+ no_proxy = proxies.get("no_proxy")
+ new_proxies = proxies.copy()
+
+ if trust_env and not should_bypass_proxies(url, no_proxy=no_proxy):
+ environ_proxies = get_environ_proxies(url, no_proxy=no_proxy)
+
+ proxy = environ_proxies.get(scheme, environ_proxies.get("all"))
+
+ if proxy:
+ new_proxies.setdefault(scheme, proxy)
+ return new_proxies
+
+
+def default_user_agent(name="python-requests"):
+ """
+ Return a string representing the default user agent.
+
+ :rtype: str
+ """
+ return f"{name}/{__version__}"
+
+
+def default_headers():
+ """
+ :rtype: requests.structures.CaseInsensitiveDict
+ """
+ return CaseInsensitiveDict(
+ {
+ "User-Agent": default_user_agent(),
+ "Accept-Encoding": DEFAULT_ACCEPT_ENCODING,
+ "Accept": "*/*",
+ "Connection": "keep-alive",
+ }
+ )
+
+
+def parse_header_links(value):
+ """Return a list of parsed link headers proxies.
+
+ i.e. Link: ; rel=front; type="image/jpeg",; rel=back;type="image/jpeg"
+
+ :rtype: list
+ """
+
+ links = []
+
+ replace_chars = " '\""
+
+ value = value.strip(replace_chars)
+ if not value:
+ return links
+
+ for val in re.split(", *<", value):
+ try:
+ url, params = val.split(";", 1)
+ except ValueError:
+ url, params = val, ""
+
+ link = {"url": url.strip("<> '\"")}
+
+ for param in params.split(";"):
+ try:
+ key, value = param.split("=")
+ except ValueError:
+ break
+
+ link[key.strip(replace_chars)] = value.strip(replace_chars)
+
+ links.append(link)
+
+ return links
+
+
+# Null bytes; no need to recreate these on each call to guess_json_utf
+_null = "\x00".encode("ascii") # encoding to ASCII for Python 3
+_null2 = _null * 2
+_null3 = _null * 3
+
+
+def guess_json_utf(data):
+ """
+ :rtype: str
+ """
+ # JSON always starts with two ASCII characters, so detection is as
+ # easy as counting the nulls and from their location and count
+ # determine the encoding. Also detect a BOM, if present.
+ sample = data[:4]
+ if sample in (codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE):
+ return "utf-32" # BOM included
+ if sample[:3] == codecs.BOM_UTF8:
+ return "utf-8-sig" # BOM included, MS style (discouraged)
+ if sample[:2] in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE):
+ return "utf-16" # BOM included
+ nullcount = sample.count(_null)
+ if nullcount == 0:
+ return "utf-8"
+ if nullcount == 2:
+ if sample[::2] == _null2: # 1st and 3rd are null
+ return "utf-16-be"
+ if sample[1::2] == _null2: # 2nd and 4th are null
+ return "utf-16-le"
+ # Did not detect 2 valid UTF-16 ascii-range characters
+ if nullcount == 3:
+ if sample[:3] == _null3:
+ return "utf-32-be"
+ if sample[1:] == _null3:
+ return "utf-32-le"
+ # Did not detect a valid UTF-32 ascii-range character
+ return None
+
+
+def prepend_scheme_if_needed(url, new_scheme):
+ """Given a URL that may or may not have a scheme, prepend the given scheme.
+ Does not replace a present scheme with the one provided as an argument.
+
+ :rtype: str
+ """
+ parsed = parse_url(url)
+ scheme, auth, host, port, path, query, fragment = parsed
+
+ # A defect in urlparse determines that there isn't a netloc present in some
+ # urls. We previously assumed parsing was overly cautious, and swapped the
+ # netloc and path. Due to a lack of tests on the original defect, this is
+ # maintained with parse_url for backwards compatibility.
+ netloc = parsed.netloc
+ if not netloc:
+ netloc, path = path, netloc
+
+ if auth:
+ # parse_url doesn't provide the netloc with auth
+ # so we'll add it ourselves.
+ netloc = "@".join([auth, netloc])
+ if scheme is None:
+ scheme = new_scheme
+ if path is None:
+ path = ""
+
+ return urlunparse((scheme, netloc, path, "", query, fragment))
+
+
+def get_auth_from_url(url):
+ """Given a url with authentication components, extract them into a tuple of
+ username,password.
+
+ :rtype: (str,str)
+ """
+ parsed = urlparse(url)
+
+ try:
+ auth = (unquote(parsed.username), unquote(parsed.password))
+ except (AttributeError, TypeError):
+ auth = ("", "")
+
+ return auth
+
+
+def check_header_validity(header):
+ """Verifies that header parts don't contain leading whitespace
+ reserved characters, or return characters.
+
+ :param header: tuple, in the format (name, value).
+ """
+ name, value = header
+ _validate_header_part(header, name, 0)
+ _validate_header_part(header, value, 1)
+
+
+def _validate_header_part(header, header_part, header_validator_index):
+ if isinstance(header_part, str):
+ validator = _HEADER_VALIDATORS_STR[header_validator_index]
+ elif isinstance(header_part, bytes):
+ validator = _HEADER_VALIDATORS_BYTE[header_validator_index]
+ else:
+ raise InvalidHeader(
+ f"Header part ({header_part!r}) from {header} "
+ f"must be of type str or bytes, not {type(header_part)}"
+ )
+
+ if not validator.match(header_part):
+ header_kind = "name" if header_validator_index == 0 else "value"
+ raise InvalidHeader(
+ f"Invalid leading whitespace, reserved character(s), or return "
+ f"character(s) in header {header_kind}: {header_part!r}"
+ )
+
+
+def urldefragauth(url):
+ """
+ Given a url remove the fragment and the authentication part.
+
+ :rtype: str
+ """
+ scheme, netloc, path, params, query, fragment = urlparse(url)
+
+ # see func:`prepend_scheme_if_needed`
+ if not netloc:
+ netloc, path = path, netloc
+
+ netloc = netloc.rsplit("@", 1)[-1]
+
+ return urlunparse((scheme, netloc, path, params, query, ""))
+
+
+def rewind_body(prepared_request):
+ """Move file pointer back to its recorded starting position
+ so it can be read again on redirect.
+ """
+ body_seek = getattr(prepared_request.body, "seek", None)
+ if body_seek is not None and isinstance(
+ prepared_request._body_position, integer_types
+ ):
+ try:
+ body_seek(prepared_request._body_position)
+ except OSError:
+ raise UnrewindableBodyError(
+ "An error occurred when rewinding request body for redirect."
+ )
+ else:
+ raise UnrewindableBodyError("Unable to rewind request body for redirect.")
diff --git a/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/METADATA b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/METADATA
new file mode 100644
index 0000000..a710533
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/METADATA
@@ -0,0 +1,141 @@
+Metadata-Version: 2.4
+Name: setuptools
+Version: 78.0.2
+Summary: Easily download, build, install, upgrade, and uninstall Python packages
+Author-email: Python Packaging Authority
+Project-URL: Source, https://github.com/pypa/setuptools
+Project-URL: Documentation, https://setuptools.pypa.io/
+Project-URL: Changelog, https://setuptools.pypa.io/en/stable/history.html
+Keywords: CPAN PyPI distutils eggs package management
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: System :: Archiving :: Packaging
+Classifier: Topic :: System :: Systems Administration
+Classifier: Topic :: Utilities
+Requires-Python: >=3.9
+Description-Content-Type: text/x-rst
+License-File: LICENSE
+Provides-Extra: test
+Requires-Dist: pytest!=8.1.*,>=6; extra == "test"
+Requires-Dist: virtualenv>=13.0.0; extra == "test"
+Requires-Dist: wheel>=0.44.0; extra == "test"
+Requires-Dist: pip>=19.1; extra == "test"
+Requires-Dist: packaging>=24.2; extra == "test"
+Requires-Dist: jaraco.envs>=2.2; extra == "test"
+Requires-Dist: pytest-xdist>=3; extra == "test"
+Requires-Dist: jaraco.path>=3.7.2; extra == "test"
+Requires-Dist: build[virtualenv]>=1.0.3; extra == "test"
+Requires-Dist: filelock>=3.4.0; extra == "test"
+Requires-Dist: ini2toml[lite]>=0.14; extra == "test"
+Requires-Dist: tomli-w>=1.0.0; extra == "test"
+Requires-Dist: pytest-timeout; extra == "test"
+Requires-Dist: pytest-perf; sys_platform != "cygwin" and extra == "test"
+Requires-Dist: jaraco.develop>=7.21; (python_version >= "3.9" and sys_platform != "cygwin") and extra == "test"
+Requires-Dist: pytest-home>=0.5; extra == "test"
+Requires-Dist: pytest-subprocess; extra == "test"
+Requires-Dist: pyproject-hooks!=1.1; extra == "test"
+Requires-Dist: jaraco.test>=5.5; extra == "test"
+Provides-Extra: doc
+Requires-Dist: sphinx>=3.5; extra == "doc"
+Requires-Dist: jaraco.packaging>=9.3; extra == "doc"
+Requires-Dist: rst.linker>=1.9; extra == "doc"
+Requires-Dist: furo; extra == "doc"
+Requires-Dist: sphinx-lint; extra == "doc"
+Requires-Dist: jaraco.tidelift>=1.4; extra == "doc"
+Requires-Dist: pygments-github-lexers==0.0.5; extra == "doc"
+Requires-Dist: sphinx-favicon; extra == "doc"
+Requires-Dist: sphinx-inline-tabs; extra == "doc"
+Requires-Dist: sphinx-reredirects; extra == "doc"
+Requires-Dist: sphinxcontrib-towncrier; extra == "doc"
+Requires-Dist: sphinx-notfound-page<2,>=1; extra == "doc"
+Requires-Dist: pyproject-hooks!=1.1; extra == "doc"
+Requires-Dist: towncrier<24.7; extra == "doc"
+Provides-Extra: ssl
+Provides-Extra: certs
+Provides-Extra: core
+Requires-Dist: packaging>=24.2; extra == "core"
+Requires-Dist: more_itertools>=8.8; extra == "core"
+Requires-Dist: jaraco.text>=3.7; extra == "core"
+Requires-Dist: importlib_metadata>=6; python_version < "3.10" and extra == "core"
+Requires-Dist: tomli>=2.0.1; python_version < "3.11" and extra == "core"
+Requires-Dist: wheel>=0.43.0; extra == "core"
+Requires-Dist: platformdirs>=4.2.2; extra == "core"
+Requires-Dist: jaraco.functools>=4; extra == "core"
+Requires-Dist: more_itertools; extra == "core"
+Provides-Extra: check
+Requires-Dist: pytest-checkdocs>=2.4; extra == "check"
+Requires-Dist: pytest-ruff>=0.2.1; sys_platform != "cygwin" and extra == "check"
+Requires-Dist: ruff>=0.8.0; sys_platform != "cygwin" and extra == "check"
+Provides-Extra: cover
+Requires-Dist: pytest-cov; extra == "cover"
+Provides-Extra: enabler
+Requires-Dist: pytest-enabler>=2.2; extra == "enabler"
+Provides-Extra: type
+Requires-Dist: pytest-mypy; extra == "type"
+Requires-Dist: mypy==1.14.*; extra == "type"
+Requires-Dist: importlib_metadata>=7.0.2; python_version < "3.10" and extra == "type"
+Requires-Dist: jaraco.develop>=7.21; sys_platform != "cygwin" and extra == "type"
+Dynamic: license-file
+
+.. |pypi-version| image:: https://img.shields.io/pypi/v/setuptools.svg
+ :target: https://pypi.org/project/setuptools
+
+.. |py-version| image:: https://img.shields.io/pypi/pyversions/setuptools.svg
+
+.. |test-badge| image:: https://github.com/pypa/setuptools/actions/workflows/main.yml/badge.svg
+ :target: https://github.com/pypa/setuptools/actions?query=workflow%3A%22tests%22
+ :alt: tests
+
+.. |ruff-badge| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+ :target: https://github.com/astral-sh/ruff
+ :alt: Ruff
+
+.. |docs-badge| image:: https://img.shields.io/readthedocs/setuptools/latest.svg
+ :target: https://setuptools.pypa.io
+
+.. |skeleton-badge| image:: https://img.shields.io/badge/skeleton-2025-informational
+ :target: https://blog.jaraco.com/skeleton
+
+.. |codecov-badge| image:: https://img.shields.io/codecov/c/github/pypa/setuptools/master.svg?logo=codecov&logoColor=white
+ :target: https://codecov.io/gh/pypa/setuptools
+
+.. |tidelift-badge| 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
+
+.. |discord-badge| image:: https://img.shields.io/discord/803025117553754132
+ :target: https://discord.com/channels/803025117553754132/815945031150993468
+ :alt: Discord
+
+|pypi-version| |py-version| |test-badge| |ruff-badge| |docs-badge| |skeleton-badge| |codecov-badge| |discord-badge|
+
+See the `Quickstart `_
+and the `User's Guide `_ for
+instructions on how to use Setuptools.
+
+Questions and comments should be directed to `GitHub Discussions
+`_.
+Bug reports and especially tested patches may be
+submitted directly to the `bug tracker
+`_.
+
+
+Code of Conduct
+===============
+
+Everyone interacting in the setuptools project's codebases, issue trackers,
+chat rooms, and fora is expected to follow the
+`PSF Code of Conduct `_.
+
+
+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 `_.
diff --git a/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/RECORD b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/RECORD
new file mode 100644
index 0000000..fe68373
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/RECORD
@@ -0,0 +1,872 @@
+_distutils_hack/__init__.py,sha256=34HmvLo07j45Uvd2VR-2aRQ7lJD91sTK6zJgn5fphbQ,6755
+_distutils_hack/__pycache__/__init__.cpython-312.pyc,,
+_distutils_hack/__pycache__/override.cpython-312.pyc,,
+_distutils_hack/override.py,sha256=Eu_s-NF6VIZ4Cqd0tbbA5wtWky2IZPNd8et6GLt1mzo,44
+distutils-precedence.pth,sha256=JjjOniUA5XKl4N5_rtZmHrVp0baW_LoHsN0iPaX10iQ,151
+pkg_resources/__init__.py,sha256=-rh7XOnTxdGuC-_9FAyu5D6s8BL1UsBehxUtj7a-IVo,126203
+pkg_resources/__pycache__/__init__.cpython-312.pyc,,
+pkg_resources/api_tests.txt,sha256=XEdvy4igHHrq2qNHNMHnlfO6XSQKNqOyLHbl6QcpfAI,12595
+pkg_resources/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+pkg_resources/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+pkg_resources/tests/__pycache__/__init__.cpython-312.pyc,,
+pkg_resources/tests/__pycache__/test_find_distributions.cpython-312.pyc,,
+pkg_resources/tests/__pycache__/test_integration_zope_interface.cpython-312.pyc,,
+pkg_resources/tests/__pycache__/test_markers.cpython-312.pyc,,
+pkg_resources/tests/__pycache__/test_pkg_resources.cpython-312.pyc,,
+pkg_resources/tests/__pycache__/test_resources.cpython-312.pyc,,
+pkg_resources/tests/__pycache__/test_working_set.cpython-312.pyc,,
+pkg_resources/tests/data/my-test-package-source/__pycache__/setup.cpython-312.pyc,,
+pkg_resources/tests/data/my-test-package-source/setup.cfg,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+pkg_resources/tests/data/my-test-package-source/setup.py,sha256=1VobhAZbMb7M9mfhb_NE8PwDsvukoWLs9aUAS0pYhe8,105
+pkg_resources/tests/data/my-test-package-zip/my-test-package.zip,sha256=AYRcQ39GVePPnMT8TknP1gdDHyJnXhthESmpAjnzSCI,1809
+pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/PKG-INFO,sha256=JvWv9Io2PAuYwEEw2fBW4Qc5YvdbkscpKX1kmLzsoHk,187
+pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/SOURCES.txt,sha256=4ClkH8eTovZrdVrJFsVuxdbMEF--lBVSuKonDAPE5Jc,208
+pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/dependency_links.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
+pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/top_level.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
+pkg_resources/tests/data/my-test-package_unpacked-egg/my_test_package-1.0-py3.7.egg/EGG-INFO/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
+pkg_resources/tests/data/my-test-package_zipped-egg/my_test_package-1.0-py3.7.egg,sha256=ZTlMGxjRGiKDNkiA2c75jbQH2TWIteP00irF9gvczbo,843
+pkg_resources/tests/test_find_distributions.py,sha256=U91cov5L1COAIWLNq3Xy4plU7_MnOE1WtXMu6iV2waM,1972
+pkg_resources/tests/test_integration_zope_interface.py,sha256=nzVoK557KZQN0V3DIQ1sVeaCOgt4Kpl-CODAWsO7pmc,1652
+pkg_resources/tests/test_markers.py,sha256=0orKg7UMDf7fnuNQvRMOc-EF9EAP_JTQnk4mtGgbW50,241
+pkg_resources/tests/test_pkg_resources.py,sha256=5Mt4bJQhLCL8j8cC46Uv32Np2Xc1TTxLGawIfET55Fk,17111
+pkg_resources/tests/test_resources.py,sha256=K0LqMAUGpRQ9pUb9K0vyI7GesvtlQvTH074m-E2VQlo,31252
+pkg_resources/tests/test_working_set.py,sha256=lRtGJWIixSwSMSbjHgRxeJEQiLMRXcz3xzJL2qL7eXY,8602
+setuptools-78.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools-78.0.2.dist-info/METADATA,sha256=iMxFapDEf8mq6b5gYRBxz7_s3MUGtIGN0p5v_5NXKkc,6599
+setuptools-78.0.2.dist-info/RECORD,,
+setuptools-78.0.2.dist-info/WHEEL,sha256=DK49LOLCYiurdXXOXwGJm6U4DkHkg4lcxjhqwRa0CP4,91
+setuptools-78.0.2.dist-info/entry_points.txt,sha256=zkgthpf_Fa9NVE9p6FKT3Xk9DR1faAcRU4coggsV7jA,2449
+setuptools-78.0.2.dist-info/licenses/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+setuptools-78.0.2.dist-info/top_level.txt,sha256=d9yL39v_W7qmKDDSH6sT4bE0j_Ls1M3P161OGgdsm4g,41
+setuptools/__init__.py,sha256=AQsMeRFWz9CQ9aBtcSkbB4Dn8t2w86-GPriklpoAjew,10406
+setuptools/__pycache__/__init__.cpython-312.pyc,,
+setuptools/__pycache__/_core_metadata.cpython-312.pyc,,
+setuptools/__pycache__/_entry_points.cpython-312.pyc,,
+setuptools/__pycache__/_imp.cpython-312.pyc,,
+setuptools/__pycache__/_importlib.cpython-312.pyc,,
+setuptools/__pycache__/_itertools.cpython-312.pyc,,
+setuptools/__pycache__/_normalization.cpython-312.pyc,,
+setuptools/__pycache__/_path.cpython-312.pyc,,
+setuptools/__pycache__/_reqs.cpython-312.pyc,,
+setuptools/__pycache__/_shutil.cpython-312.pyc,,
+setuptools/__pycache__/_static.cpython-312.pyc,,
+setuptools/__pycache__/archive_util.cpython-312.pyc,,
+setuptools/__pycache__/build_meta.cpython-312.pyc,,
+setuptools/__pycache__/depends.cpython-312.pyc,,
+setuptools/__pycache__/discovery.cpython-312.pyc,,
+setuptools/__pycache__/dist.cpython-312.pyc,,
+setuptools/__pycache__/errors.cpython-312.pyc,,
+setuptools/__pycache__/extension.cpython-312.pyc,,
+setuptools/__pycache__/glob.cpython-312.pyc,,
+setuptools/__pycache__/installer.cpython-312.pyc,,
+setuptools/__pycache__/launch.cpython-312.pyc,,
+setuptools/__pycache__/logging.cpython-312.pyc,,
+setuptools/__pycache__/modified.cpython-312.pyc,,
+setuptools/__pycache__/monkey.cpython-312.pyc,,
+setuptools/__pycache__/msvc.cpython-312.pyc,,
+setuptools/__pycache__/namespaces.cpython-312.pyc,,
+setuptools/__pycache__/package_index.cpython-312.pyc,,
+setuptools/__pycache__/sandbox.cpython-312.pyc,,
+setuptools/__pycache__/unicode_utils.cpython-312.pyc,,
+setuptools/__pycache__/version.cpython-312.pyc,,
+setuptools/__pycache__/warnings.cpython-312.pyc,,
+setuptools/__pycache__/wheel.cpython-312.pyc,,
+setuptools/__pycache__/windows_support.cpython-312.pyc,,
+setuptools/_core_metadata.py,sha256=T7Tjp-WSoN881adev3R1wzXCPnkDHqbC2MgylN1yjS8,11978
+setuptools/_distutils/__init__.py,sha256=xGYuhWwLG07J0Q49BVnEjPy6wyDcd6veJMDJX7ljlyM,359
+setuptools/_distutils/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/_log.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/_macos_compat.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/_modified.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/_msvccompiler.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/archive_util.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/ccompiler.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/cmd.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/core.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/cygwinccompiler.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/debug.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/dep_util.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/dir_util.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/dist.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/errors.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/extension.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/fancy_getopt.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/file_util.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/filelist.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/log.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/spawn.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/sysconfig.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/text_file.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/unixccompiler.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/util.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/version.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/versionpredicate.cpython-312.pyc,,
+setuptools/_distutils/__pycache__/zosccompiler.cpython-312.pyc,,
+setuptools/_distutils/_log.py,sha256=i-lNTTcXS8TmWITJ6DODGvtW5z5tMattJQ76h8rZxQU,42
+setuptools/_distutils/_macos_compat.py,sha256=JzUGhF4E5yIITHbUaPobZEWjGHdrrcNV63z86S4RjBc,239
+setuptools/_distutils/_modified.py,sha256=RF1n1CexyDYV3lvGbeXS0s-XCJVboDOIUbA8wEQqYTY,3211
+setuptools/_distutils/_msvccompiler.py,sha256=QdFAH4JlMIxLoOaHUzm-ngK3H8jAoTo924XJ3Fe7SCQ,88
+setuptools/_distutils/archive_util.py,sha256=Qw2z-Pt-NV8lNUQrzjs3XDGWCWHMPnqHLyt8TiD2XEA,8884
+setuptools/_distutils/ccompiler.py,sha256=FKVjqzGJ7c-FtouNjhLiaMPm5LKMZHHAruXf8LU216c,524
+setuptools/_distutils/cmd.py,sha256=hXtaRaH7QBnfNOIqEvCt47iwZzD9MVvBdhhdQctHsxM,22186
+setuptools/_distutils/command/__init__.py,sha256=GfFAzbBqk1qxSH4BdaKioKS4hRRnD44BAmwEN85C4u8,386
+setuptools/_distutils/command/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/_framework_compat.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/bdist.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/build.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/build_clib.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/build_ext.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/build_py.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/build_scripts.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/check.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/clean.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/config.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/install.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/install_data.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/install_egg_info.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/install_headers.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/install_lib.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/install_scripts.cpython-312.pyc,,
+setuptools/_distutils/command/__pycache__/sdist.cpython-312.pyc,,
+setuptools/_distutils/command/_framework_compat.py,sha256=0iZdSJYzGRWCCvzRDKE-R0-_yaAYvFMd1ylXb2eYXug,1609
+setuptools/_distutils/command/bdist.py,sha256=jWtk61R7fWNUUNxJV0thTZzU5n80L3Ay1waSiP9kiLA,5854
+setuptools/_distutils/command/bdist_dumb.py,sha256=Hx1jAqoZNxYIy4N5TLzUp6J5fi8Ls18py7UlLNFhO2E,4631
+setuptools/_distutils/command/bdist_rpm.py,sha256=nxcXXv5a7B-1ntWu4DbGmCtES4EBINrJaBQcRNAYCJI,21785
+setuptools/_distutils/command/build.py,sha256=SpHlagf0iNaKVyIhxDfhPFZ8X1-LAWOCQACy-yt2K0w,5923
+setuptools/_distutils/command/build_clib.py,sha256=aMqZcUfCbOAu_xr-A9iW-Q9YZHzpDGLRTezOgMQJmSQ,7777
+setuptools/_distutils/command/build_ext.py,sha256=zrrsu9HXnzV6bXYbJuZCK4SwVZMjKnl4pG1o3bNcxtc,32710
+setuptools/_distutils/command/build_py.py,sha256=Vfq-INemoMbg6f003BTy_Ufp8bjOZhmFIhpKMcfXLgs,16696
+setuptools/_distutils/command/build_scripts.py,sha256=tUpEzwTsnrP8qrNory3ldPB240QDCFkMp-pdYPs2wTk,5118
+setuptools/_distutils/command/check.py,sha256=yoNe2MPY4JcTM7rwoIQdfZ75q5Ri058I2coi-Gq9CjM,4946
+setuptools/_distutils/command/clean.py,sha256=dQAacOabwBXU9JoZ-1GFusq3eFltDaeXJFSYncqGbvE,2644
+setuptools/_distutils/command/config.py,sha256=BuUdPu91Vo9w44xzD1RQfiyXfSfVcNpeX3aeoKcGAOw,12818
+setuptools/_distutils/command/install.py,sha256=-JenB-mua4hc2RI_-W8F9PnP_J-OaFO7E0PJGKxLo1o,30072
+setuptools/_distutils/command/install_data.py,sha256=GzBlUWWKubTYJlP-L0auUriq9cL-5RKOcoyHTttKj0Q,2875
+setuptools/_distutils/command/install_egg_info.py,sha256=ffiLoU1ivQJ8q2_WL7ZygZbUcOsgdFLKL7otEIJWWkI,2868
+setuptools/_distutils/command/install_headers.py,sha256=5ciKCj8c3XKsYNKdkdMvnypaUCKcoWCDeeZij3fD-Z4,1272
+setuptools/_distutils/command/install_lib.py,sha256=2s9-m5-b1qKm51F28lB5L39Z6vv_GHMlv9dNBSupok0,8588
+setuptools/_distutils/command/install_scripts.py,sha256=M0pPdiaqB7TGmqTMujpGGeiL0Iq_CTeGjMFtrmDmwzM,2002
+setuptools/_distutils/command/sdist.py,sha256=cRIF6Ht1hJ6ayOOFVycMFBUNxjo94e_rFYPx4Hi8Ahc,19151
+setuptools/_distutils/compat/__init__.py,sha256=J20aXGjJ86Rg41xFLIWlcWCgZ9edMdJ9vvdNEQ87vPQ,522
+setuptools/_distutils/compat/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_distutils/compat/__pycache__/numpy.cpython-312.pyc,,
+setuptools/_distutils/compat/__pycache__/py39.cpython-312.pyc,,
+setuptools/_distutils/compat/numpy.py,sha256=UFgneZw9w97g4c-yGoAIOyLxUOWQ-fPRIhhfMs7_Ouc,167
+setuptools/_distutils/compat/py39.py,sha256=hOsD6lwZLqZoMnacNJ3P6nUA-LJQhEpVtYTzVH0o96M,1964
+setuptools/_distutils/compilers/C/__pycache__/base.cpython-312.pyc,,
+setuptools/_distutils/compilers/C/__pycache__/cygwin.cpython-312.pyc,,
+setuptools/_distutils/compilers/C/__pycache__/errors.cpython-312.pyc,,
+setuptools/_distutils/compilers/C/__pycache__/msvc.cpython-312.pyc,,
+setuptools/_distutils/compilers/C/__pycache__/unix.cpython-312.pyc,,
+setuptools/_distutils/compilers/C/__pycache__/zos.cpython-312.pyc,,
+setuptools/_distutils/compilers/C/base.py,sha256=XR1rBCStCquqm7QOYXD41-LfvsFcPpGxrwxeXzJyn_w,54876
+setuptools/_distutils/compilers/C/cygwin.py,sha256=DUlwQSb55aj7OdcmcddrmCmVEjEaxIiJ5hHUO3GBPNs,11844
+setuptools/_distutils/compilers/C/errors.py,sha256=sKOVzJajMUmNdfywo9UM_QQGsKFcclDhtI5TlCiXMLc,573
+setuptools/_distutils/compilers/C/msvc.py,sha256=elzG8v9jN5QytLMwLCdUdSuZ3eZ3R98VUvnm9Y2PBCA,21404
+setuptools/_distutils/compilers/C/tests/__pycache__/test_base.cpython-312.pyc,,
+setuptools/_distutils/compilers/C/tests/__pycache__/test_cygwin.cpython-312.pyc,,
+setuptools/_distutils/compilers/C/tests/__pycache__/test_mingw.cpython-312.pyc,,
+setuptools/_distutils/compilers/C/tests/__pycache__/test_msvc.cpython-312.pyc,,
+setuptools/_distutils/compilers/C/tests/__pycache__/test_unix.cpython-312.pyc,,
+setuptools/_distutils/compilers/C/tests/test_base.py,sha256=rdhHc56bhXtm5NnN9BSHwr6c69UqzMItZQzlw2AsdMc,2706
+setuptools/_distutils/compilers/C/tests/test_cygwin.py,sha256=UgV2VgUXj3VulcbDc0UBWfEyJDx42tgSwS4LzHix3mY,2701
+setuptools/_distutils/compilers/C/tests/test_mingw.py,sha256=hCmwyywISpRoyOySbFHBL4TprWRV0mUWDKmOLO8XBXE,1900
+setuptools/_distutils/compilers/C/tests/test_msvc.py,sha256=DlGjmZ1mBSMXIgmlu80BKc7V-EJOZuYucwJwFh5dn28,4151
+setuptools/_distutils/compilers/C/tests/test_unix.py,sha256=ErbYWio7ejY2ZqQmPk4AwOu1HFW4-_-aZdUvGa1W2Fw,11834
+setuptools/_distutils/compilers/C/unix.py,sha256=l7CxY4rDJAECJo-vcv6io0SBmmPJ9JmN5mSmZcin2VU,16502
+setuptools/_distutils/compilers/C/zos.py,sha256=vnNeWLRZkdIkdZ-YyBnL8idTUfcCOn0tLMW5OBJ0ScU,6586
+setuptools/_distutils/core.py,sha256=GEHKaFC48T3o-_SmH4864GvKyx1IgbVC6ISIPVlx7a4,9364
+setuptools/_distutils/cygwinccompiler.py,sha256=mG_cU8SVZ4amD_VtF5vH6BXP0-kghGsDPbDSXrQ963c,594
+setuptools/_distutils/debug.py,sha256=N6MrTAqK6l9SVk6tWweR108PM8Ol7qNlfyV-nHcLhsY,139
+setuptools/_distutils/dep_util.py,sha256=xN75p6ZpHhMiHEc-rpL2XilJQynHnDNiafHteaZ4tjU,349
+setuptools/_distutils/dir_util.py,sha256=DXPUlfVVGsg9B-Jgg4At_j9T7vM60OgwNXkQHqTo7-I,7236
+setuptools/_distutils/dist.py,sha256=gW598UE0WMkzXQQ31Nr-8L7MPw0oIOz5OSSRzYZlwrM,55794
+setuptools/_distutils/errors.py,sha256=PPE2oDRh5y9Q1beKK9rhdvDaCzQhi4HCXs4KcqfqgZY,3092
+setuptools/_distutils/extension.py,sha256=Foyu4gULcPqm1_U9zrYYHxNk4NqglXv1rbsOk_QrSds,11155
+setuptools/_distutils/fancy_getopt.py,sha256=PjdO-bWCW0imV_UN-MGEw9R2GP2OiE8pHjITgmTAY3Q,17895
+setuptools/_distutils/file_util.py,sha256=YFQL_pD3hLuER9II_H6-hDC_YIGEookdd4wedLuiTW0,7978
+setuptools/_distutils/filelist.py,sha256=MBeSRJmPcKmDv8ooZgSU4BiQPZ0Khwv8l_jhD50XycI,15337
+setuptools/_distutils/log.py,sha256=VyBs5j7z4-K6XTEEBThUc9HyMpoPLGtQpERqbz5ylww,1200
+setuptools/_distutils/spawn.py,sha256=zseCh9sEifyp0I5Vg719JNIASlROJ2ehXqQnHlpt89Q,4086
+setuptools/_distutils/sysconfig.py,sha256=KeI8OHbMuEzHJ8Q0cBez9KZny8iRy6Z6Y0AkMz1jlsU,19728
+setuptools/_distutils/tests/__init__.py,sha256=j-IoPZEtQv3EOPuqNTwalr6GLyRjzCC-OOaNvZzmHsI,1485
+setuptools/_distutils/tests/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/support.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_archive_util.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_bdist.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_bdist_dumb.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_bdist_rpm.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_build.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_build_clib.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_build_ext.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_build_py.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_build_scripts.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_check.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_clean.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_cmd.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_config_cmd.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_core.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_dir_util.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_dist.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_extension.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_file_util.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_filelist.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_install.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_install_data.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_install_headers.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_install_lib.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_install_scripts.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_log.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_modified.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_sdist.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_spawn.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_sysconfig.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_text_file.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_util.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_version.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/test_versionpredicate.cpython-312.pyc,,
+setuptools/_distutils/tests/__pycache__/unix_compat.cpython-312.pyc,,
+setuptools/_distutils/tests/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_distutils/tests/compat/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_distutils/tests/compat/__pycache__/py39.cpython-312.pyc,,
+setuptools/_distutils/tests/compat/py39.py,sha256=t0GBTM-30jX-9zCfkwlNBFtzzabemx6065mJ0d9_VRw,1026
+setuptools/_distutils/tests/support.py,sha256=tjsYsyxvpTK4NrkCseh2ujvDIGV0Mf_b5SI5fP2T0yM,4099
+setuptools/_distutils/tests/test_archive_util.py,sha256=jozimSwPBF-JoJfN_vDaiVGZp66BNcWZGh34FlW57DQ,11787
+setuptools/_distutils/tests/test_bdist.py,sha256=xNHxUsLlHsZQRwkzLb_iSD24s-9Mk-NX2ffBWwOyPyc,1396
+setuptools/_distutils/tests/test_bdist_dumb.py,sha256=QF05MHNhPOdZyh88Xpw8KsO64s7pRFkl8KL-RoV4XK0,2247
+setuptools/_distutils/tests/test_bdist_rpm.py,sha256=Hdm-pwWgyaoGdGbEcGZa8cRhGU45y8gHK8umOanTjik,3932
+setuptools/_distutils/tests/test_build.py,sha256=JJY5XpOZco25ZY0pstxl-iI8mHsWP0ujf5o8aOtuZYY,1742
+setuptools/_distutils/tests/test_build_clib.py,sha256=Mo1ZFb4C1VXBYOGvnallwN7YCnTtr24akLDO8Zi4CsY,4331
+setuptools/_distutils/tests/test_build_ext.py,sha256=QFO9qYVhWWdJu17HXc4x9RMnLZlhk0lAHi9HVppbuX4,22545
+setuptools/_distutils/tests/test_build_py.py,sha256=NsfmRrojOHBXNMqWR_mp5g4PLTgjhD7iZFUffGZFIdw,6882
+setuptools/_distutils/tests/test_build_scripts.py,sha256=cD-FRy-oX55sXRX5Ez5xQCaeHrWajyKc4Xuwv2fe48w,2880
+setuptools/_distutils/tests/test_check.py,sha256=hHSV07qf7YoSxGsTbbsUQ9tssZz5RRNdbrY1s2SwaFI,6226
+setuptools/_distutils/tests/test_clean.py,sha256=hPH6jfIpGFUrvWbF1txkiNVSNaAxt2wq5XjV499zO4E,1240
+setuptools/_distutils/tests/test_cmd.py,sha256=bgRB79mitoOKR1OiyZHnCogvGxt3pWkxeTqIC04lQWQ,3254
+setuptools/_distutils/tests/test_config_cmd.py,sha256=Zs6WX0IfxDvmuC19XzuVNnYCnTr9Y-hl73TAmDSBN4Y,2664
+setuptools/_distutils/tests/test_core.py,sha256=L7XKVAxa-MGoAZeANopnuK9fRKneYhkSQpgw8XQvcF8,3829
+setuptools/_distutils/tests/test_dir_util.py,sha256=E84lC-k4riVUwURyWaQ0Jqx2ui2-io-0RuJa3M7qkJs,4500
+setuptools/_distutils/tests/test_dist.py,sha256=a6wlc5fQJd5qQ6HOndzcupNhjTxvj6-_JLtpuYvaP1M,18793
+setuptools/_distutils/tests/test_extension.py,sha256=-YejLgZCuycFrOBd64pVH0JvwMc9NwhzHvQxvvjXHqk,3670
+setuptools/_distutils/tests/test_file_util.py,sha256=livjnl3FkilQlrB2rFdFQq9nvjEVZHynNya0bfzv_b4,3522
+setuptools/_distutils/tests/test_filelist.py,sha256=rJwkqCUfkGDgWlD22TozsT8ycbupMHB8DXqThzwT1T4,10766
+setuptools/_distutils/tests/test_install.py,sha256=TfCB0ykhIxydIC2Q4SuTAZzSHvteMHgrBL9whoSgK9Q,8618
+setuptools/_distutils/tests/test_install_data.py,sha256=vKq3K97k0hBAnOg38nmwEdf7cEDVr9rTVyCeJolgb4A,2464
+setuptools/_distutils/tests/test_install_headers.py,sha256=PVAYpo_tYl980Qf64DPOmmSvyefIHdU06f7VsJeZykE,936
+setuptools/_distutils/tests/test_install_lib.py,sha256=qri6Rl-maNTQrNDV8DbeXNl0hjsfRIKiI4rfZLrmWBI,3612
+setuptools/_distutils/tests/test_install_scripts.py,sha256=KE3v0cDkFW-90IOID-OmZZGM2mhy-ZkEuuW7UXS2SHw,1600
+setuptools/_distutils/tests/test_log.py,sha256=isFtOufloCyEdZaQOV7cVUr46GwtdVMj43mGBB5XH7k,323
+setuptools/_distutils/tests/test_modified.py,sha256=h1--bOWmtJo1bpVV6uRhdnS9br71CBiNDM1MDwSGpug,4221
+setuptools/_distutils/tests/test_sdist.py,sha256=cfzUhlCA418-1vH9ta3IBs26c_jUBbkJoFOK5GnAyNk,15062
+setuptools/_distutils/tests/test_spawn.py,sha256=eS8w9D7bTxyFLSyRahJWeuh8Kc1F8RWWiY_dSG5B5Bc,4803
+setuptools/_distutils/tests/test_sysconfig.py,sha256=lxM8LsUi1TomjDV4HoYK8u5nUoBkeNL60Uq8PY1DcwU,11986
+setuptools/_distutils/tests/test_text_file.py,sha256=WQWSB5AfdBDZaMA8BFgipJPnsJb_2SKMfL90fSkRVtw,3460
+setuptools/_distutils/tests/test_util.py,sha256=H9zlZ4z4Vh4TfjNYDBsxP7wguQLpxCfJYyOcm1yZU3c,7988
+setuptools/_distutils/tests/test_version.py,sha256=ahfg_mP8wRy1sgwY-_Px5hrjgf6_upTIpnCgpR4yWRk,2750
+setuptools/_distutils/tests/test_versionpredicate.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_distutils/tests/unix_compat.py,sha256=z-op6C2iVdX1aq5BIBR7cqOxijKE97alNwJqHNdLpoI,386
+setuptools/_distutils/text_file.py,sha256=z4dkOJBr9Bo2LG0TNqm8sD63LEEaKSSP0J0bWBrFG3c,12101
+setuptools/_distutils/unixccompiler.py,sha256=1bXJWH4fiu_A2WfriHzf88xjllQTXnnjUkZdRKs9cWU,212
+setuptools/_distutils/util.py,sha256=Njfnqk60zMdkiAjRnGcTWX3t49-obHapOlbNvyIl02I,18094
+setuptools/_distutils/version.py,sha256=vImT5-ECXkQ21oKL0XYFiTqK6NyM09cpzBNoA_34CQU,12619
+setuptools/_distutils/versionpredicate.py,sha256=qBWQ6wTj12ODytoTmIydefIY2jb4uY1sdbgbuLn-IJM,5205
+setuptools/_distutils/zosccompiler.py,sha256=svdiXZ2kdcwKrJKfhUhib03y8gz7aGZKukXH3I7YkBc,58
+setuptools/_entry_points.py,sha256=Y3QUE9JKFW_YyquDnpffNWSs6f3jKEt1e-dnx--9-Kw,2310
+setuptools/_imp.py,sha256=YY1EjZEN-0zYci1cxO10B_adAEOr7i8eK8JoCc9Ierc,2435
+setuptools/_importlib.py,sha256=aKIjcK0HKXNz2D-XTrxaixGn_juTkONwmu3dcheMOF0,223
+setuptools/_itertools.py,sha256=jWRfsIrpC7myooz3hDURj9GtvpswZeKXg2HakmEhNjo,657
+setuptools/_normalization.py,sha256=kAmGfrwjF5djydEfLLyKgjkXCbL_0_ZxUPO-DlLlmIY,5824
+setuptools/_path.py,sha256=cPv41v03HD7uEYqCIo-E_cGRfpPVr4lywBCiK-HSrCg,2685
+setuptools/_reqs.py,sha256=QI3C9uOBSNRccu208qPnixHx51nxCry7_nPTIJaSYxM,1438
+setuptools/_shutil.py,sha256=cAOllcoyMTXs5JLoybQi29yI5gABk82hepJyOBv2bMw,1496
+setuptools/_static.py,sha256=GTR79gESF1_JaK4trLkpDrEuCeEtPlwQW0MRv7VNQX4,4855
+setuptools/_vendor/__pycache__/typing_extensions.cpython-312.pyc,,
+setuptools/_vendor/autocommand-2.2.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/autocommand-2.2.2.dist-info/LICENSE,sha256=reeNBJgtaZctREqOFKlPh6IzTdOFXMgDSOqOJAqg3y0,7634
+setuptools/_vendor/autocommand-2.2.2.dist-info/METADATA,sha256=OADZuR3O6iBlpu1ieTgzYul6w4uOVrk0P0BO5TGGAJk,15006
+setuptools/_vendor/autocommand-2.2.2.dist-info/RECORD,sha256=giu6ZrQVJvpUcYa4AiH4XaUNZSvuVJPb_l0UCFES8MM,1308
+setuptools/_vendor/autocommand-2.2.2.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
+setuptools/_vendor/autocommand-2.2.2.dist-info/top_level.txt,sha256=AzfhgKKS8EdAwWUTSF8mgeVQbXOY9kokHB6kSqwwqu0,12
+setuptools/_vendor/autocommand/__init__.py,sha256=zko5Rnvolvb-UXjCx_2ArPTGBWwUK5QY4LIQIKYR7As,1037
+setuptools/_vendor/autocommand/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/autocommand/__pycache__/autoasync.cpython-312.pyc,,
+setuptools/_vendor/autocommand/__pycache__/autocommand.cpython-312.pyc,,
+setuptools/_vendor/autocommand/__pycache__/automain.cpython-312.pyc,,
+setuptools/_vendor/autocommand/__pycache__/autoparse.cpython-312.pyc,,
+setuptools/_vendor/autocommand/__pycache__/errors.cpython-312.pyc,,
+setuptools/_vendor/autocommand/autoasync.py,sha256=AMdyrxNS4pqWJfP_xuoOcImOHWD-qT7x06wmKN1Vp-U,5680
+setuptools/_vendor/autocommand/autocommand.py,sha256=hmkEmQ72HtL55gnURVjDOnsfYlGd5lLXbvT4KG496Qw,2505
+setuptools/_vendor/autocommand/automain.py,sha256=A2b8i754Mxc_DjU9WFr6vqYDWlhz0cn8miu8d8EsxV8,2076
+setuptools/_vendor/autocommand/autoparse.py,sha256=WVWmZJPcbzUKXP40raQw_0HD8qPJ2V9VG1eFFmmnFxw,11642
+setuptools/_vendor/autocommand/errors.py,sha256=7aa3roh9Herd6nIKpQHNWEslWE8oq7GiHYVUuRqORnA,886
+setuptools/_vendor/backports.tarfile-1.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/backports.tarfile-1.2.0.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+setuptools/_vendor/backports.tarfile-1.2.0.dist-info/METADATA,sha256=ghXFTq132dxaEIolxr3HK1mZqm9iyUmaRANZQSr6WlE,2020
+setuptools/_vendor/backports.tarfile-1.2.0.dist-info/RECORD,sha256=JYofHISeEXUGmlWl1s41ev3QTjTNXeJwk-Ss7HqdLOE,1360
+setuptools/_vendor/backports.tarfile-1.2.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/backports.tarfile-1.2.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+setuptools/_vendor/backports.tarfile-1.2.0.dist-info/top_level.txt,sha256=cGjaLMOoBR1FK0ApojtzWVmViTtJ7JGIK_HwXiEsvtU,10
+setuptools/_vendor/backports/__init__.py,sha256=iOEMwnlORWezdO8-2vxBIPSR37D7JGjluZ8f55vzxls,81
+setuptools/_vendor/backports/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/backports/tarfile/__init__.py,sha256=Pwf2qUIfB0SolJPCKcx3vz3UEu_aids4g4sAfxy94qg,108491
+setuptools/_vendor/backports/tarfile/__main__.py,sha256=Yw2oGT1afrz2eBskzdPYL8ReB_3liApmhFkN2EbDmc4,59
+setuptools/_vendor/backports/tarfile/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/backports/tarfile/__pycache__/__main__.cpython-312.pyc,,
+setuptools/_vendor/backports/tarfile/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/backports/tarfile/compat/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/backports/tarfile/compat/__pycache__/py38.cpython-312.pyc,,
+setuptools/_vendor/backports/tarfile/compat/py38.py,sha256=iYkyt_gvWjLzGUTJD9TuTfMMjOk-ersXZmRlvQYN2qE,568
+setuptools/_vendor/importlib_metadata-8.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/importlib_metadata-8.0.0.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
+setuptools/_vendor/importlib_metadata-8.0.0.dist-info/METADATA,sha256=anuQ7_7h4J1bSEzfcjIBakPi2cyVQ7y7jklLHsBeH1k,4648
+setuptools/_vendor/importlib_metadata-8.0.0.dist-info/RECORD,sha256=DY08buueu-hsrH1ghhVSQzwynanqUSSLYdAr4uXmQDA,2518
+setuptools/_vendor/importlib_metadata-8.0.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/importlib_metadata-8.0.0.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
+setuptools/_vendor/importlib_metadata-8.0.0.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19
+setuptools/_vendor/importlib_metadata/__init__.py,sha256=tZNB-23h8Bixi9uCrQqj9Yf0aeC--Josdy3IZRIQeB0,33798
+setuptools/_vendor/importlib_metadata/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/__pycache__/_adapters.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/__pycache__/_collections.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/__pycache__/_compat.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/__pycache__/_functools.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/__pycache__/_itertools.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/__pycache__/_meta.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/__pycache__/_text.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/__pycache__/diagnose.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/_adapters.py,sha256=rIhWTwBvYA1bV7i-5FfVX38qEXDTXFeS5cb5xJtP3ks,2317
+setuptools/_vendor/importlib_metadata/_collections.py,sha256=CJ0OTCHIjWA0ZIVS4voORAsn2R4R2cQBEtPsZEJpASY,743
+setuptools/_vendor/importlib_metadata/_compat.py,sha256=73QKrN9KNoaZzhbX5yPCCZa-FaALwXe8TPlDR72JgBU,1314
+setuptools/_vendor/importlib_metadata/_functools.py,sha256=PsY2-4rrKX4RVeRC1oGp1lB1pmC9eKN88_f-bD9uOoA,2895
+setuptools/_vendor/importlib_metadata/_itertools.py,sha256=cvr_2v8BRbxcIl5x5ldfqdHjhI8Yi8s8yk50G_nm6jQ,2068
+setuptools/_vendor/importlib_metadata/_meta.py,sha256=nxZ7C8GVlcBFAKWyVOn_dn7ot_twBcbm1NmvjIetBHI,1801
+setuptools/_vendor/importlib_metadata/_text.py,sha256=HCsFksZpJLeTP3NEk_ngrAeXVRRtTrtyh9eOABoRP4A,2166
+setuptools/_vendor/importlib_metadata/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/importlib_metadata/compat/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/compat/__pycache__/py311.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/compat/__pycache__/py39.cpython-312.pyc,,
+setuptools/_vendor/importlib_metadata/compat/py311.py,sha256=uqm-K-uohyj1042TH4a9Er_I5o7667DvulcD-gC_fSA,608
+setuptools/_vendor/importlib_metadata/compat/py39.py,sha256=cPkMv6-0ilK-0Jw_Tkn0xYbOKJZc4WJKQHow0c2T44w,1102
+setuptools/_vendor/importlib_metadata/diagnose.py,sha256=nkSRMiowlmkhLYhKhvCg9glmt_11Cox-EmLzEbqYTa8,379
+setuptools/_vendor/importlib_metadata/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/inflect-7.3.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/inflect-7.3.1.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+setuptools/_vendor/inflect-7.3.1.dist-info/METADATA,sha256=ZgMNY0WAZRs-U8wZiV2SMfjSKqBrMngXyDMs_CAwMwg,21079
+setuptools/_vendor/inflect-7.3.1.dist-info/RECORD,sha256=XXg0rBuiYSxoAQUP3lenuYsPNqz4jDwtTzdv2JEbMJE,943
+setuptools/_vendor/inflect-7.3.1.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
+setuptools/_vendor/inflect-7.3.1.dist-info/top_level.txt,sha256=m52ujdp10CqT6jh1XQxZT6kEntcnv-7Tl7UiGNTzWZA,8
+setuptools/_vendor/inflect/__init__.py,sha256=Jxy1HJXZiZ85kHeLAhkmvz6EMTdFqBe-duvt34R6IOc,103796
+setuptools/_vendor/inflect/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/inflect/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/inflect/compat/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/inflect/compat/__pycache__/py38.cpython-312.pyc,,
+setuptools/_vendor/inflect/compat/py38.py,sha256=oObVfVnWX9_OpnOuEJn1mFbJxVhwyR5epbiTNXDDaso,160
+setuptools/_vendor/inflect/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/jaraco.collections-5.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/jaraco.collections-5.1.0.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+setuptools/_vendor/jaraco.collections-5.1.0.dist-info/METADATA,sha256=IMUaliNsA5X1Ox9MXUWOagch5R4Wwb_3M7erp29dBtg,3933
+setuptools/_vendor/jaraco.collections-5.1.0.dist-info/RECORD,sha256=HptivXDkpfom6VlMu4CGD_7KPev-6Hc9rvp3TNJZygY,873
+setuptools/_vendor/jaraco.collections-5.1.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/jaraco.collections-5.1.0.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
+setuptools/_vendor/jaraco.collections-5.1.0.dist-info/top_level.txt,sha256=0JnN3LfXH4LIRfXL-QFOGCJzQWZO3ELx4R1d_louoQM,7
+setuptools/_vendor/jaraco.context-5.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/jaraco.context-5.3.0.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+setuptools/_vendor/jaraco.context-5.3.0.dist-info/METADATA,sha256=xDtguJej0tN9iEXCUvxEJh2a7xceIRVBEakBLSr__tY,4020
+setuptools/_vendor/jaraco.context-5.3.0.dist-info/RECORD,sha256=VRl7iKeEQyl7stgnp1uq50CzOJYlHYcoNdS0x17C9X4,641
+setuptools/_vendor/jaraco.context-5.3.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+setuptools/_vendor/jaraco.context-5.3.0.dist-info/top_level.txt,sha256=0JnN3LfXH4LIRfXL-QFOGCJzQWZO3ELx4R1d_louoQM,7
+setuptools/_vendor/jaraco.functools-4.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/jaraco.functools-4.0.1.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+setuptools/_vendor/jaraco.functools-4.0.1.dist-info/METADATA,sha256=i4aUaQDX-jjdEQK5wevhegyx8JyLfin2HyvaSk3FHso,2891
+setuptools/_vendor/jaraco.functools-4.0.1.dist-info/RECORD,sha256=YyqnwE98S8wBwCevW5vHb-iVj0oYEDW5V6O9MBS6JIs,843
+setuptools/_vendor/jaraco.functools-4.0.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+setuptools/_vendor/jaraco.functools-4.0.1.dist-info/top_level.txt,sha256=0JnN3LfXH4LIRfXL-QFOGCJzQWZO3ELx4R1d_louoQM,7
+setuptools/_vendor/jaraco.text-3.12.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/jaraco.text-3.12.1.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+setuptools/_vendor/jaraco.text-3.12.1.dist-info/METADATA,sha256=AzWdm6ViMfDOPoQMfLWn2zgBQSGJScyqeN29TcuWXVI,3658
+setuptools/_vendor/jaraco.text-3.12.1.dist-info/RECORD,sha256=gW2UV0HcokYJk4jKPu10_AZnrLqjb3C1WbJJTDl5sfY,1500
+setuptools/_vendor/jaraco.text-3.12.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/jaraco.text-3.12.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+setuptools/_vendor/jaraco.text-3.12.1.dist-info/top_level.txt,sha256=0JnN3LfXH4LIRfXL-QFOGCJzQWZO3ELx4R1d_louoQM,7
+setuptools/_vendor/jaraco/__pycache__/context.cpython-312.pyc,,
+setuptools/_vendor/jaraco/collections/__init__.py,sha256=Pc1-SqjWm81ad1P0-GttpkwO_LWlnaY6gUq8gcKh2v0,26640
+setuptools/_vendor/jaraco/collections/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/jaraco/collections/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/jaraco/context.py,sha256=REoLIxDkO5MfEYowt_WoupNCRoxBS5v7YX2PbW8lIcs,9552
+setuptools/_vendor/jaraco/functools/__init__.py,sha256=hEAJaS2uSZRuF_JY4CxCHIYh79ZpxaPp9OiHyr9EJ1w,16642
+setuptools/_vendor/jaraco/functools/__init__.pyi,sha256=gk3dsgHzo5F_U74HzAvpNivFAPCkPJ1b2-yCd62dfnw,3878
+setuptools/_vendor/jaraco/functools/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/jaraco/functools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/jaraco/text/Lorem ipsum.txt,sha256=N_7c_79zxOufBY9HZ3yzMgOkNv-TkOTTio4BydrSjgs,1335
+setuptools/_vendor/jaraco/text/__init__.py,sha256=Y2YUqXR_orUoDaY4SkPRe6ZZhb5HUHB_Ah9RCNsVyho,16250
+setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/jaraco/text/__pycache__/layouts.cpython-312.pyc,,
+setuptools/_vendor/jaraco/text/__pycache__/show-newlines.cpython-312.pyc,,
+setuptools/_vendor/jaraco/text/__pycache__/strip-prefix.cpython-312.pyc,,
+setuptools/_vendor/jaraco/text/__pycache__/to-dvorak.cpython-312.pyc,,
+setuptools/_vendor/jaraco/text/__pycache__/to-qwerty.cpython-312.pyc,,
+setuptools/_vendor/jaraco/text/layouts.py,sha256=HTC8aSTLZ7uXipyOXapRMC158juecjK6RVwitfmZ9_w,643
+setuptools/_vendor/jaraco/text/show-newlines.py,sha256=WGQa65e8lyhb92LUOLqVn6KaCtoeVgVws6WtSRmLk6w,904
+setuptools/_vendor/jaraco/text/strip-prefix.py,sha256=NfVXV8JVNo6nqcuYASfMV7_y4Eo8zMQqlCOGvAnRIVw,412
+setuptools/_vendor/jaraco/text/to-dvorak.py,sha256=1SNcbSsvISpXXg-LnybIHHY-RUFOQr36zcHkY1pWFqw,119
+setuptools/_vendor/jaraco/text/to-qwerty.py,sha256=s4UMQUnPwFn_dB5uZC27BurHOQcYondBfzIpVL5pEzw,119
+setuptools/_vendor/more_itertools-10.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/more_itertools-10.3.0.dist-info/LICENSE,sha256=CfHIyelBrz5YTVlkHqm4fYPAyw_QB-te85Gn4mQ8GkY,1053
+setuptools/_vendor/more_itertools-10.3.0.dist-info/METADATA,sha256=BFO90O-fLNiVQMpj7oIS5ztzgJUUQZ3TA32P5HH3N-A,36293
+setuptools/_vendor/more_itertools-10.3.0.dist-info/RECORD,sha256=d8jnPgGNwP1-ntbICwWkQEVF9kH7CFIgzkKzaLWao9M,1259
+setuptools/_vendor/more_itertools-10.3.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/more_itertools-10.3.0.dist-info/WHEEL,sha256=rSgq_JpHF9fHR1lx53qwg_1-2LypZE_qmcuXbVUq948,81
+setuptools/_vendor/more_itertools/__init__.py,sha256=dtAbGjTDmn_ghiU5YXfhyDy0phAlXVdt5klZA5fUa-Q,149
+setuptools/_vendor/more_itertools/__init__.pyi,sha256=5B3eTzON1BBuOLob1vCflyEb2lSd6usXQQ-Cv-hXkeA,43
+setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/more_itertools/__pycache__/more.cpython-312.pyc,,
+setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-312.pyc,,
+setuptools/_vendor/more_itertools/more.py,sha256=1E5kzFncRKTDw0cYv1yRXMgDdunstLQd1QStcnL6U90,148370
+setuptools/_vendor/more_itertools/more.pyi,sha256=iXXeqt48Nxe8VGmIWpkVXuKpR2FYNuu2DU8nQLWCCu0,21484
+setuptools/_vendor/more_itertools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/more_itertools/recipes.py,sha256=WedhhfhGVgr6zii8fIbGJVmRTw0ZKRiLKnYBDGJv4nY,28591
+setuptools/_vendor/more_itertools/recipes.pyi,sha256=T_mdGpcFdfrP3JSWbwzYP9JyNV-Go-7RPfpxfftAWlA,4617
+setuptools/_vendor/packaging-24.2.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2
+setuptools/_vendor/packaging-24.2.dist-info/LICENSE,sha256=ytHvW9NA1z4HS6YU0m996spceUDD2MNIUuZcSQlobEg,197
+setuptools/_vendor/packaging-24.2.dist-info/LICENSE.APACHE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174
+setuptools/_vendor/packaging-24.2.dist-info/LICENSE.BSD,sha256=tw5-m3QvHMb5SLNMFqo5_-zpQZY2S8iP8NIYDwAo-sU,1344
+setuptools/_vendor/packaging-24.2.dist-info/METADATA,sha256=ohH86s6k5mIfQxY2TS0LcSfADeOFa4BiCC-bxZV-pNs,3204
+setuptools/_vendor/packaging-24.2.dist-info/RECORD,sha256=Y4DrXM0KY0ArfzhbAEa1LYFPwW3WEgEeL4iCqXe-A-M,2009
+setuptools/_vendor/packaging-24.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/packaging-24.2.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
+setuptools/_vendor/packaging/__init__.py,sha256=dk4Ta_vmdVJxYHDcfyhvQNw8V3PgSBomKNXqg-D2JDY,494
+setuptools/_vendor/packaging/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/_elffile.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/_parser.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/_structures.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/_tokenizer.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/markers.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/metadata.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/requirements.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/tags.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/utils.cpython-312.pyc,,
+setuptools/_vendor/packaging/__pycache__/version.cpython-312.pyc,,
+setuptools/_vendor/packaging/_elffile.py,sha256=cflAQAkE25tzhYmq_aCi72QfbT_tn891tPzfpbeHOwE,3306
+setuptools/_vendor/packaging/_manylinux.py,sha256=vl5OCoz4kx80H5rwXKeXWjl9WNISGmr4ZgTpTP9lU9c,9612
+setuptools/_vendor/packaging/_musllinux.py,sha256=p9ZqNYiOItGee8KcZFeHF_YcdhVwGHdK6r-8lgixvGQ,2694
+setuptools/_vendor/packaging/_parser.py,sha256=s_TvTvDNK0NrM2QB3VKThdWFM4Nc0P6JnkObkl3MjpM,10236
+setuptools/_vendor/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431
+setuptools/_vendor/packaging/_tokenizer.py,sha256=J6v5H7Jzvb-g81xp_2QACKwO7LxHQA6ikryMU7zXwN8,5273
+setuptools/_vendor/packaging/licenses/__init__.py,sha256=1x5M1nEYjcgwEbLt0dXwz2ukjr18DiCzC0sraQqJ-Ww,5715
+setuptools/_vendor/packaging/licenses/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/packaging/licenses/__pycache__/_spdx.cpython-312.pyc,,
+setuptools/_vendor/packaging/licenses/_spdx.py,sha256=oAm1ztPFwlsmCKe7lAAsv_OIOfS1cWDu9bNBkeu-2ns,48398
+setuptools/_vendor/packaging/markers.py,sha256=c89TNzB7ZdGYhkovm6PYmqGyHxXlYVaLW591PHUNKD8,10561
+setuptools/_vendor/packaging/metadata.py,sha256=YJibM7GYe4re8-0a3OlXmGS-XDgTEoO4tlBt2q25Bng,34762
+setuptools/_vendor/packaging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/packaging/requirements.py,sha256=gYyRSAdbrIyKDY66ugIDUQjRMvxkH2ALioTmX3tnL6o,2947
+setuptools/_vendor/packaging/specifiers.py,sha256=GG1wPNMcL0fMJO68vF53wKMdwnfehDcaI-r9NpTfilA,40074
+setuptools/_vendor/packaging/tags.py,sha256=CFqrJzAzc2XNGexerH__T-Y5Iwq7WbsYXsiLERLWxY0,21014
+setuptools/_vendor/packaging/utils.py,sha256=0F3Hh9OFuRgrhTgGZUl5K22Fv1YP2tZl1z_2gO6kJiA,5050
+setuptools/_vendor/packaging/version.py,sha256=olfyuk_DPbflNkJ4wBWetXQ17c74x3DB501degUv7DY,16676
+setuptools/_vendor/platformdirs-4.2.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/platformdirs-4.2.2.dist-info/METADATA,sha256=zmsie01G1MtXR0wgIv5XpVeTO7idr0WWvfmxKsKWuGk,11429
+setuptools/_vendor/platformdirs-4.2.2.dist-info/RECORD,sha256=TCEddtQu1A78Os_Mhm2JEqcYr7yit-UYSUQjZtbpn-g,1642
+setuptools/_vendor/platformdirs-4.2.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/platformdirs-4.2.2.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
+setuptools/_vendor/platformdirs-4.2.2.dist-info/licenses/LICENSE,sha256=KeD9YukphQ6G6yjD_czwzv30-pSHkBHP-z0NS-1tTbY,1089
+setuptools/_vendor/platformdirs/__init__.py,sha256=EMGE8qeHRR9CzDFr8kL3tA8hdZZniYjXBVZd0UGTWK0,22225
+setuptools/_vendor/platformdirs/__main__.py,sha256=HnsUQHpiBaiTxwcmwVw-nFaPdVNZtQIdi1eWDtI-MzI,1493
+setuptools/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc,,
+setuptools/_vendor/platformdirs/__pycache__/android.cpython-312.pyc,,
+setuptools/_vendor/platformdirs/__pycache__/api.cpython-312.pyc,,
+setuptools/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc,,
+setuptools/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc,,
+setuptools/_vendor/platformdirs/__pycache__/version.cpython-312.pyc,,
+setuptools/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc,,
+setuptools/_vendor/platformdirs/android.py,sha256=xZXY9Jd46WOsxT2U6-5HsNtDZ-IQqxcEUrBLl3hYk4o,9016
+setuptools/_vendor/platformdirs/api.py,sha256=QBYdUac2eC521ek_y53uD1Dcq-lJX8IgSRVd4InC6uc,8996
+setuptools/_vendor/platformdirs/macos.py,sha256=wftsbsvq6nZ0WORXSiCrZNkRHz_WKuktl0a6mC7MFkI,5580
+setuptools/_vendor/platformdirs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/platformdirs/unix.py,sha256=Cci9Wqt35dAMsg6HT9nRGHSBW5obb0pR3AE1JJnsCXg,10643
+setuptools/_vendor/platformdirs/version.py,sha256=r7F76tZRjgQKzrpx_I0_ZMQOMU-PS7eGnHD7zEK3KB0,411
+setuptools/_vendor/platformdirs/windows.py,sha256=IFpiohUBwxPtCzlyKwNtxyW4Jk8haa6W8o59mfrDXVo,10125
+setuptools/_vendor/tomli-2.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/tomli-2.0.1.dist-info/LICENSE,sha256=uAgWsNUwuKzLTCIReDeQmEpuO2GSLCte6S8zcqsnQv4,1072
+setuptools/_vendor/tomli-2.0.1.dist-info/METADATA,sha256=zPDceKmPwJGLWtZykrHixL7WVXWmJGzZ1jyRT5lCoPI,8875
+setuptools/_vendor/tomli-2.0.1.dist-info/RECORD,sha256=DLn5pFGh42WsVLTIhmLh2gy1SnLRalJY-wq_-dPhwCI,999
+setuptools/_vendor/tomli-2.0.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/tomli-2.0.1.dist-info/WHEEL,sha256=jPMR_Dzkc4X4icQtmz81lnNY_kAsfog7ry7qoRvYLXw,81
+setuptools/_vendor/tomli/__init__.py,sha256=JhUwV66DB1g4Hvt1UQCVMdfCu-IgAV8FXmvDU9onxd4,396
+setuptools/_vendor/tomli/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/tomli/__pycache__/_parser.cpython-312.pyc,,
+setuptools/_vendor/tomli/__pycache__/_re.cpython-312.pyc,,
+setuptools/_vendor/tomli/__pycache__/_types.cpython-312.pyc,,
+setuptools/_vendor/tomli/_parser.py,sha256=g9-ENaALS-B8dokYpCuzUFalWlog7T-SIYMjLZSWrtM,22633
+setuptools/_vendor/tomli/_re.py,sha256=dbjg5ChZT23Ka9z9DHOXfdtSpPwUfdgMXnj8NOoly-w,2943
+setuptools/_vendor/tomli/_types.py,sha256=-GTG2VUqkpxwMqzmVO4F7ybKddIbAnuAHXfmWQcTi3Q,254
+setuptools/_vendor/tomli/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26
+setuptools/_vendor/typeguard-4.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/typeguard-4.3.0.dist-info/LICENSE,sha256=YWP3mH37ONa8MgzitwsvArhivEESZRbVUu8c1DJH51g,1130
+setuptools/_vendor/typeguard-4.3.0.dist-info/METADATA,sha256=z2dcHAp0TwhYCFU5Deh8x31nazElgujUz9tbuP0pjSE,3717
+setuptools/_vendor/typeguard-4.3.0.dist-info/RECORD,sha256=SKUZWVgkeDUidUKM7s1473fXmsna55bjmi6vJUAoJVI,2402
+setuptools/_vendor/typeguard-4.3.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+setuptools/_vendor/typeguard-4.3.0.dist-info/entry_points.txt,sha256=qp7NQ1aLtiSgMQqo6gWlfGpy0IIXzoMJmeQTLpzqFZQ,48
+setuptools/_vendor/typeguard-4.3.0.dist-info/top_level.txt,sha256=4z28AhuDodwRS_c1J_l8H51t5QuwfTseskYzlxp6grs,10
+setuptools/_vendor/typeguard/__init__.py,sha256=Onh4w38elPCjtlcU3JY9k3h70NjsxXIkAflmQn-Z0FY,2071
+setuptools/_vendor/typeguard/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_checkers.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_config.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_decorators.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_exceptions.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_functions.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_importhook.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_memo.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_pytest_plugin.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_suppression.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_transformer.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_union_transformer.cpython-312.pyc,,
+setuptools/_vendor/typeguard/__pycache__/_utils.cpython-312.pyc,,
+setuptools/_vendor/typeguard/_checkers.py,sha256=JRrgKicdOEfIBoNEtegYCEIlhpad-a1u1Em7GCj0WCI,31360
+setuptools/_vendor/typeguard/_config.py,sha256=nIz8QwDa-oFO3L9O8_6srzlmd99pSby2wOM4Wb7F_B0,2846
+setuptools/_vendor/typeguard/_decorators.py,sha256=v6dsIeWvPhExGLP_wXF-RmDUyjZf_Ak28g7gBJ_v0-0,9033
+setuptools/_vendor/typeguard/_exceptions.py,sha256=ZIPeiV-FBd5Emw2EaWd2Fvlsrwi4ocwT2fVGBIAtHcQ,1121
+setuptools/_vendor/typeguard/_functions.py,sha256=ibgSAKa5ptIm1eR9ARG0BSozAFJPFNASZqhPVyQeqig,10393
+setuptools/_vendor/typeguard/_importhook.py,sha256=ugjCDvFcdWMU7UugqlJG91IpVNpEIxtRr-99s0h1k7M,6389
+setuptools/_vendor/typeguard/_memo.py,sha256=1juQV_vxnD2JYKbSrebiQuj4oKHz6n67v9pYA-CCISg,1303
+setuptools/_vendor/typeguard/_pytest_plugin.py,sha256=-fcSqkv54rIfIF8pDavY5YQPkj4OX8GMt_lL7CQSD4I,4416
+setuptools/_vendor/typeguard/_suppression.py,sha256=VQfzxcwIbu3if0f7VBkKM7hkYOA7tNFw9a7jMBsmMg4,2266
+setuptools/_vendor/typeguard/_transformer.py,sha256=9Ha7_QhdwoUni_6hvdY-hZbuEergowHrNL2vzHIakFY,44937
+setuptools/_vendor/typeguard/_union_transformer.py,sha256=v_42r7-6HuRX2SoFwnyJ-E5PlxXpVeUJPJR1-HU9qSo,1354
+setuptools/_vendor/typeguard/_utils.py,sha256=5HhO1rPn5f1M6ymkVAEv7Xmlz1cX-j0OnTMlyHqqrR8,5270
+setuptools/_vendor/typeguard/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/typing_extensions-4.12.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/typing_extensions-4.12.2.dist-info/LICENSE,sha256=Oy-B_iHRgcSZxZolbI4ZaEVdZonSaaqFNzv7avQdo78,13936
+setuptools/_vendor/typing_extensions-4.12.2.dist-info/METADATA,sha256=BeUQIa8cnYbrjWx-N8TOznM9UGW5Gm2DicVpDtRA8W0,3018
+setuptools/_vendor/typing_extensions-4.12.2.dist-info/RECORD,sha256=dxAALYGXHmMqpqL8M9xddKr118quIgQKZdPjFQOwXuk,571
+setuptools/_vendor/typing_extensions-4.12.2.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
+setuptools/_vendor/typing_extensions.py,sha256=gwekpyG9DVG3lxWKX4ni8u7nk3We5slG98mA9F3DJQw,134451
+setuptools/_vendor/wheel-0.45.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/wheel-0.45.1.dist-info/LICENSE.txt,sha256=MMI2GGeRCPPo6h0qZYx8pBe9_IkcmO8aifpP8MmChlQ,1107
+setuptools/_vendor/wheel-0.45.1.dist-info/METADATA,sha256=mKz84H7m7jsxJyzeIcTVORiTb0NPMV39KvOIYhGgmjA,2313
+setuptools/_vendor/wheel-0.45.1.dist-info/RECORD,sha256=1jnxrHyZPDcVvULyfGFhiba4Z5L9_RsXr9dxcNbhaYQ,4900
+setuptools/_vendor/wheel-0.45.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/wheel-0.45.1.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
+setuptools/_vendor/wheel-0.45.1.dist-info/entry_points.txt,sha256=rTY1BbkPHhkGMm4Q3F0pIzJBzW2kMxoG1oriffvGdA0,104
+setuptools/_vendor/wheel/__init__.py,sha256=mrxMnvdXACur_LWegbUfh5g5ysWZrd63UJn890wvGNk,59
+setuptools/_vendor/wheel/__main__.py,sha256=NkMUnuTCGcOkgY0IBLgBCVC_BGGcWORx2K8jYGS12UE,455
+setuptools/_vendor/wheel/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/wheel/__pycache__/__main__.cpython-312.pyc,,
+setuptools/_vendor/wheel/__pycache__/_bdist_wheel.cpython-312.pyc,,
+setuptools/_vendor/wheel/__pycache__/_setuptools_logging.cpython-312.pyc,,
+setuptools/_vendor/wheel/__pycache__/bdist_wheel.cpython-312.pyc,,
+setuptools/_vendor/wheel/__pycache__/macosx_libfile.cpython-312.pyc,,
+setuptools/_vendor/wheel/__pycache__/metadata.cpython-312.pyc,,
+setuptools/_vendor/wheel/__pycache__/util.cpython-312.pyc,,
+setuptools/_vendor/wheel/__pycache__/wheelfile.cpython-312.pyc,,
+setuptools/_vendor/wheel/_bdist_wheel.py,sha256=UghCQjSH_pVfcZh6oRjzSw_TQhcf3anSx1OkiLSL82M,21694
+setuptools/_vendor/wheel/_setuptools_logging.py,sha256=-5KC-lne0ilOUWIDfOkqapUWGMFZhuKYDIavIZiB5kM,781
+setuptools/_vendor/wheel/bdist_wheel.py,sha256=tpf9WufiSO1RuEMg5oPhIfSG8DMziCZ_4muCKF69Cqo,1107
+setuptools/_vendor/wheel/cli/__init__.py,sha256=Npq6_jKi03dhIcRnmbuFhwviVJxwO0tYEnEhWMv9cJo,4402
+setuptools/_vendor/wheel/cli/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/wheel/cli/__pycache__/convert.cpython-312.pyc,,
+setuptools/_vendor/wheel/cli/__pycache__/pack.cpython-312.pyc,,
+setuptools/_vendor/wheel/cli/__pycache__/tags.cpython-312.pyc,,
+setuptools/_vendor/wheel/cli/__pycache__/unpack.cpython-312.pyc,,
+setuptools/_vendor/wheel/cli/convert.py,sha256=Bi0ntEXb9nTllCxWeTRQ4j-nPs3szWSEKipG_GgnMkQ,12634
+setuptools/_vendor/wheel/cli/pack.py,sha256=CAFcHdBVulvsHYJlndKVO7KMI9JqBTZz5ii0PKxxCOs,3103
+setuptools/_vendor/wheel/cli/tags.py,sha256=lHw-LaWrkS5Jy_qWcw-6pSjeNM6yAjDnqKI3E5JTTCU,4760
+setuptools/_vendor/wheel/cli/unpack.py,sha256=Y_J7ynxPSoFFTT7H0fMgbBlVErwyDGcObgme5MBuz58,1021
+setuptools/_vendor/wheel/macosx_libfile.py,sha256=k1x7CE3LPtOVGqj6NXQ1nTGYVPaeRrhVzUG_KPq3zDs,16572
+setuptools/_vendor/wheel/metadata.py,sha256=JC4p7jlQZu2bUTAQ2fevkqLjg_X6gnNyRhLn6OUO1tc,6171
+setuptools/_vendor/wheel/util.py,sha256=aL7aibHwYUgfc8WlolL5tXdkV4DatbJxZHb1kwHFJAU,423
+setuptools/_vendor/wheel/vendored/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/wheel/vendored/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/LICENSE,sha256=ytHvW9NA1z4HS6YU0m996spceUDD2MNIUuZcSQlobEg,197
+setuptools/_vendor/wheel/vendored/packaging/LICENSE.APACHE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174
+setuptools/_vendor/wheel/vendored/packaging/LICENSE.BSD,sha256=tw5-m3QvHMb5SLNMFqo5_-zpQZY2S8iP8NIYDwAo-sU,1344
+setuptools/_vendor/wheel/vendored/packaging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/_elffile.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/_manylinux.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/_musllinux.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/_parser.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/_structures.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/_tokenizer.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/markers.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/requirements.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/specifiers.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/tags.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/utils.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/__pycache__/version.cpython-312.pyc,,
+setuptools/_vendor/wheel/vendored/packaging/_elffile.py,sha256=hbmK8OD6Z7fY6hwinHEUcD1by7czkGiNYu7ShnFEk2k,3266
+setuptools/_vendor/wheel/vendored/packaging/_manylinux.py,sha256=P7sdR5_7XBY09LVYYPhHmydMJIIwPXWsh4olk74Uuj4,9588
+setuptools/_vendor/wheel/vendored/packaging/_musllinux.py,sha256=z1s8To2hQ0vpn_d-O2i5qxGwEK8WmGlLt3d_26V7NeY,2674
+setuptools/_vendor/wheel/vendored/packaging/_parser.py,sha256=4tT4emSl2qTaU7VTQE1Xa9o1jMPCsBezsYBxyNMUN-s,10347
+setuptools/_vendor/wheel/vendored/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431
+setuptools/_vendor/wheel/vendored/packaging/_tokenizer.py,sha256=alCtbwXhOFAmFGZ6BQ-wCTSFoRAJ2z-ysIf7__MTJ_k,5292
+setuptools/_vendor/wheel/vendored/packaging/markers.py,sha256=_TSPI1BhJYO7Bp9AzTmHQxIqHEVXaTjmDh9G-w8qzPA,8232
+setuptools/_vendor/wheel/vendored/packaging/requirements.py,sha256=dgoBeVprPu2YE6Q8nGfwOPTjATHbRa_ZGLyXhFEln6Q,2933
+setuptools/_vendor/wheel/vendored/packaging/specifiers.py,sha256=IWSt0SrLSP72heWhAC8UL0eGvas7XIQHjqiViVfmPKE,39778
+setuptools/_vendor/wheel/vendored/packaging/tags.py,sha256=fedHXiOHkBxNZTXotXv8uXPmMFU9ae-TKBujgYHigcA,18950
+setuptools/_vendor/wheel/vendored/packaging/utils.py,sha256=XgdmP3yx9-wQEFjO7OvMj9RjEf5JlR5HFFR69v7SQ9E,5268
+setuptools/_vendor/wheel/vendored/packaging/version.py,sha256=PFJaYZDxBgyxkfYhH3SQw4qfE9ICCWrTmitvq14y3bs,16234
+setuptools/_vendor/wheel/vendored/vendor.txt,sha256=Z2ENjB1i5prfez8CdM1Sdr3c6Zxv2rRRolMpLmBncAE,16
+setuptools/_vendor/wheel/wheelfile.py,sha256=USCttNlJwafxt51YYFFKG7jnxz8dfhbyqAZL6jMTA9s,8411
+setuptools/_vendor/zipp-3.19.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+setuptools/_vendor/zipp-3.19.2.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+setuptools/_vendor/zipp-3.19.2.dist-info/METADATA,sha256=UIrk_kMIHGSwsKKChYizqMw0MMZpPRZ2ZiVpQAsN_bE,3575
+setuptools/_vendor/zipp-3.19.2.dist-info/RECORD,sha256=8xby4D_ZrefrvAsVRwaEjiu4_VaLkJNRCfDY484rm_4,1039
+setuptools/_vendor/zipp-3.19.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/zipp-3.19.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+setuptools/_vendor/zipp-3.19.2.dist-info/top_level.txt,sha256=iAbdoSHfaGqBfVb2XuR9JqSQHCoOsOtG6y9C_LSpqFw,5
+setuptools/_vendor/zipp/__init__.py,sha256=QuI1g00G4fRAcGt-HqbV0oWIkmSgedCGGYsHHYzNa8A,13412
+setuptools/_vendor/zipp/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/zipp/__pycache__/glob.cpython-312.pyc,,
+setuptools/_vendor/zipp/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/_vendor/zipp/compat/__pycache__/__init__.cpython-312.pyc,,
+setuptools/_vendor/zipp/compat/__pycache__/py310.cpython-312.pyc,,
+setuptools/_vendor/zipp/compat/py310.py,sha256=eZpkW0zRtunkhEh8jjX3gCGe22emoKCBJw72Zt4RkhA,219
+setuptools/_vendor/zipp/glob.py,sha256=etWpnfEoRyfUvrUsi6sTiGmErvPwe6HzY6pT8jg_lUI,3082
+setuptools/archive_util.py,sha256=Tl_64hSTtc4y8x7xa98rFVUbG24oArpjzLAYGYP2_sI,7356
+setuptools/build_meta.py,sha256=rry-LowqvWFsxG6Qm5QWetHJGeETzRdiQ5-bs4bOkjo,20446
+setuptools/cli-32.exe,sha256=MqzBvFQxFsviz_EMuGd3LfLyVP8mNMhwrvC0bEtpb9s,11776
+setuptools/cli-64.exe,sha256=u7PeVwdinmpgoMI4zUd7KPB_AGaYL9qVP6b87DkHOko,14336
+setuptools/cli-arm64.exe,sha256=uafQjaiA36yLz1SOuksG-1m28JsX0zFIoPZhgyiSbGE,13824
+setuptools/cli.exe,sha256=MqzBvFQxFsviz_EMuGd3LfLyVP8mNMhwrvC0bEtpb9s,11776
+setuptools/command/__init__.py,sha256=wdSrlNR0P6nCz9_oFtCAiAkeFJMsZa1jPcpXT53f0SM,803
+setuptools/command/__pycache__/__init__.cpython-312.pyc,,
+setuptools/command/__pycache__/_requirestxt.cpython-312.pyc,,
+setuptools/command/__pycache__/alias.cpython-312.pyc,,
+setuptools/command/__pycache__/bdist_egg.cpython-312.pyc,,
+setuptools/command/__pycache__/bdist_rpm.cpython-312.pyc,,
+setuptools/command/__pycache__/bdist_wheel.cpython-312.pyc,,
+setuptools/command/__pycache__/build.cpython-312.pyc,,
+setuptools/command/__pycache__/build_clib.cpython-312.pyc,,
+setuptools/command/__pycache__/build_ext.cpython-312.pyc,,
+setuptools/command/__pycache__/build_py.cpython-312.pyc,,
+setuptools/command/__pycache__/develop.cpython-312.pyc,,
+setuptools/command/__pycache__/dist_info.cpython-312.pyc,,
+setuptools/command/__pycache__/easy_install.cpython-312.pyc,,
+setuptools/command/__pycache__/editable_wheel.cpython-312.pyc,,
+setuptools/command/__pycache__/egg_info.cpython-312.pyc,,
+setuptools/command/__pycache__/install.cpython-312.pyc,,
+setuptools/command/__pycache__/install_egg_info.cpython-312.pyc,,
+setuptools/command/__pycache__/install_lib.cpython-312.pyc,,
+setuptools/command/__pycache__/install_scripts.cpython-312.pyc,,
+setuptools/command/__pycache__/rotate.cpython-312.pyc,,
+setuptools/command/__pycache__/saveopts.cpython-312.pyc,,
+setuptools/command/__pycache__/sdist.cpython-312.pyc,,
+setuptools/command/__pycache__/setopt.cpython-312.pyc,,
+setuptools/command/__pycache__/test.cpython-312.pyc,,
+setuptools/command/_requirestxt.py,sha256=ItYMTJGh_i5TlQstX_nFopqEhkC4PJFadBL2Zd3V670,4228
+setuptools/command/alias.py,sha256=rDdrMt32DS6qf3K7tjZZyHD_dMKrm77AXcAtx-nBQ0I,2380
+setuptools/command/bdist_egg.py,sha256=3eDucQ4fdeYMsLO9PhBfY1JkcMLhZXgnAI_9FdFNsEE,16972
+setuptools/command/bdist_rpm.py,sha256=LyqI49w48SKk0FmuHsE9MLzX1SuXjL7YMNbZMFZqFII,1435
+setuptools/command/bdist_wheel.py,sha256=_LfGHB7CV_uyncqlOTSETEi2gjVCoPKuAXcyRFoq7Cs,22246
+setuptools/command/build.py,sha256=eI7STMERGGZEpzk1tvJN8p9IOjAAXMcGLzljv2mwI3M,6052
+setuptools/command/build_clib.py,sha256=AbgpPIF_3qL8fZr3JIebI-WHTMTBiMfrFkVQz8K40G4,4528
+setuptools/command/build_ext.py,sha256=bUH4M0NizaJJrv10wK-ZD3uY0TxCSZlYQDhiwwzHslM,18377
+setuptools/command/build_py.py,sha256=DCbjvB18kkL-xUK5rvlzm0C6twTeOxNhyvJDxxa7fII,15539
+setuptools/command/develop.py,sha256=zX22119sI1G1gfJ1gNCE4hkg2zbLKx0uUwvNmC5bIu8,6886
+setuptools/command/dist_info.py,sha256=HU752iLLmmYMHbsDBgz2ubRjkgJobugOp8H71LzzDys,3450
+setuptools/command/easy_install.py,sha256=0Z4kFlE78Ae2AfHXYTxZFUa2t3qlNqXCtQu4J1Nx8iA,87870
+setuptools/command/editable_wheel.py,sha256=3bBipRZA3E4poQ8LEWhMYEjHjCzqU_pIdO86C3t7oNY,35624
+setuptools/command/egg_info.py,sha256=WWUozR3DZCrWsTQhHXOygMiEUcrjLWphET0-Zsocsm4,25982
+setuptools/command/install.py,sha256=MmTGb8m1R8fJ0cc5FTWCF6uq-s1ZJmvpYm-N_CtqEaI,7046
+setuptools/command/install_egg_info.py,sha256=3I9IPCH7D59Sh-6aVYz-h6wwyxq-wkxrKwKg3nDdJqs,2075
+setuptools/command/install_lib.py,sha256=9n1_U83eHcERL_a_rv_LhHCkhXlLdqyZ4SdBow-9qcE,4319
+setuptools/command/install_scripts.py,sha256=tVOCj3e8OTIrkoL_bGbT5pOksdxZfQblH_bdI4DtVV4,2637
+setuptools/command/launcher manifest.xml,sha256=xlLbjWrB01tKC0-hlVkOKkiSPbzMml2eOPtJ_ucCnbE,628
+setuptools/command/rotate.py,sha256=XNd_BEEOWAJHW1FcLTMUWWl4QB6zAuk7b8VWQg3FHos,2187
+setuptools/command/saveopts.py,sha256=Np0PVb7SD7oTbu9Z9sosS7D-CkkIkU7x4glu5Es1tjA,692
+setuptools/command/sdist.py,sha256=JaQm2-ebXI2kvyrBjJKP8yNLPa5eMbMeis88CXBMYlk,7374
+setuptools/command/setopt.py,sha256=xZF2RCc4ABvE9eHHAzF50-fkQg3au8fcRUVVGd58k3U,5100
+setuptools/command/test.py,sha256=k7xcq7D7bEehgxarbw-dW3AtmGZORqz8HjKR6FGJ3jk,1343
+setuptools/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/compat/__pycache__/__init__.cpython-312.pyc,,
+setuptools/compat/__pycache__/py310.cpython-312.pyc,,
+setuptools/compat/__pycache__/py311.cpython-312.pyc,,
+setuptools/compat/__pycache__/py312.cpython-312.pyc,,
+setuptools/compat/__pycache__/py39.cpython-312.pyc,,
+setuptools/compat/py310.py,sha256=8sqwWczIcrkzeAbhaim4pKVd4tXZdcqmebgdvzji0rc,141
+setuptools/compat/py311.py,sha256=e6tJAFwZEP82hmMBl10HYeSypelo_Ti2wTjKZVKLwOE,790
+setuptools/compat/py312.py,sha256=vYKVtdrdOTsO_R90dJkEXsFwfMJFuIFJflhIgHrjJ-Y,366
+setuptools/compat/py39.py,sha256=BJMtnkfcqyTfccqjYQxfoRtU2nTnWaEESBVkshTiXqY,493
+setuptools/config/NOTICE,sha256=Ld3wiBgpejuJ1D2V_2WdjahXQRCMkTbfo6TYVsBiO9g,493
+setuptools/config/__init__.py,sha256=aiPnL9BJn1O6MfmuNXyn8W2Lp8u9qizRVqwPiOdPIjY,1499
+setuptools/config/__pycache__/__init__.cpython-312.pyc,,
+setuptools/config/__pycache__/_apply_pyprojecttoml.cpython-312.pyc,,
+setuptools/config/__pycache__/expand.cpython-312.pyc,,
+setuptools/config/__pycache__/pyprojecttoml.cpython-312.pyc,,
+setuptools/config/__pycache__/setupcfg.cpython-312.pyc,,
+setuptools/config/_apply_pyprojecttoml.py,sha256=SUyTw7A2btZ1lBuWKN5o42-Diyv95eGTiYJ3rZOnGSc,19120
+setuptools/config/_validate_pyproject/NOTICE,sha256=XTANv6ZDE4sBO3WsnK7uWR-VG4sO4kKIw0zNkmxHgMg,18737
+setuptools/config/_validate_pyproject/__init__.py,sha256=dnp6T7ePP1R5z4OuC7Fd2dkFlIrtIfizUfvpGJP6nz0,1042
+setuptools/config/_validate_pyproject/__pycache__/__init__.cpython-312.pyc,,
+setuptools/config/_validate_pyproject/__pycache__/error_reporting.cpython-312.pyc,,
+setuptools/config/_validate_pyproject/__pycache__/extra_validations.cpython-312.pyc,,
+setuptools/config/_validate_pyproject/__pycache__/fastjsonschema_exceptions.cpython-312.pyc,,
+setuptools/config/_validate_pyproject/__pycache__/fastjsonschema_validations.cpython-312.pyc,,
+setuptools/config/_validate_pyproject/__pycache__/formats.cpython-312.pyc,,
+setuptools/config/_validate_pyproject/error_reporting.py,sha256=meldD7nBQdolQhvG-43r1Ue-gU1n7ORAJR86vh3Rrvk,11813
+setuptools/config/_validate_pyproject/extra_validations.py,sha256=-GUG5S--ijY8WfXbdXPoHl6ywGsyEF9dtDpenSoJPHg,2858
+setuptools/config/_validate_pyproject/fastjsonschema_exceptions.py,sha256=w749JgqKi8clBFcObdcbZVqsmF4oJ_QByhZ1SGbUFNw,1612
+setuptools/config/_validate_pyproject/fastjsonschema_validations.py,sha256=FihD5ZcM6p77BPZ04CGqh3BEwVNoPMKJZJAyuJpkAU0,354682
+setuptools/config/_validate_pyproject/formats.py,sha256=TETokJBK9hjl-cVg1olsojkJwLxfP7_chgJQNmzAB98,13564
+setuptools/config/distutils.schema.json,sha256=Tcp32kRnhwORGw_9p6GEi08lj2h15tQRzOYBbzGmcBU,972
+setuptools/config/expand.py,sha256=JNAktRCsyyRB-rQodbPnCucmLWqcYvzCDC8Ebn2Z7xM,16041
+setuptools/config/pyprojecttoml.py,sha256=YMu5PdbJJI5azp6kR_boM1mflf5nqOA-InF4s6LnLgw,18320
+setuptools/config/setupcfg.py,sha256=VZDkwE7DYv45SbadJD8CwKrDtiXvjgllL8PYSvoRCyg,26575
+setuptools/config/setuptools.schema.json,sha256=dZBRuSEnZkatoVlt1kVwG8ocTeRdO7BD0xvOWKH54PY,16071
+setuptools/depends.py,sha256=jKYfjmt_2ZQYVghb8L9bU7LJ6erHJ5ze-K_fKV1BMXk,5965
+setuptools/discovery.py,sha256=-42c3XhwzkfodDKKP50C2YBzr11fncAgmUzBdBRb0-Q,21258
+setuptools/dist.py,sha256=RZz7aj9RxqSYriqgFoZOu-7KIV82cmlaMFx9owZrApQ,44897
+setuptools/errors.py,sha256=gY2x2PIaIgy01yRANRC-zcCwxDCqCScgJoCOZFe0yio,3024
+setuptools/extension.py,sha256=KCnv9p3tgm0ZVqtgE451fyILsm4hCyvOiUtOu787D-4,6683
+setuptools/glob.py,sha256=AC_B33DY8g-CHELxDsJrtwFrpiucSAZsakPFdSOQzhc,6062
+setuptools/gui-32.exe,sha256=hdrh6V13hF8stZvKw9Sv50u-TJGpvMW_SnHNQxBNvnw,11776
+setuptools/gui-64.exe,sha256=NHG2FA6txkEid9u-_j_vjDRaDxpZd2CGuAo2GMOoPjs,14336
+setuptools/gui-arm64.exe,sha256=5pT0dDQFyLWSb_RX22_n8aEt7HwWqcOGR4TT9OB64Jc,13824
+setuptools/gui.exe,sha256=hdrh6V13hF8stZvKw9Sv50u-TJGpvMW_SnHNQxBNvnw,11776
+setuptools/installer.py,sha256=_4Wegx4r3L05sMo3-IlqFp-OuxnWyBqjyMZ7LWQXmh8,5110
+setuptools/launch.py,sha256=IBb5lEv69CyuZ9ewIrmKlXh154kdLmP29LKfTMkximE,820
+setuptools/logging.py,sha256=W16iHJ1HcCXYQ0RxyrEfJ83FT4175tCtoYg-E6uSpVI,1261
+setuptools/modified.py,sha256=ZwbfBfCFP88ltvbv_dJDz-t1LsQjnM-JUpgZnnQZjjM,568
+setuptools/monkey.py,sha256=FwMWl2n1v2bHbeqBy-o9g8yUNaAkYFbszCbXe9d5Za8,3717
+setuptools/msvc.py,sha256=vmM0qL4rIzrtD9pia9ZEwtqZ4LbbrgL0dU0EANVYRm8,41631
+setuptools/namespaces.py,sha256=2GGqYY1BNDEhMtBc1rHTv7klgmNVRdksJeW-L1f--ys,3171
+setuptools/package_index.py,sha256=yHXj4Z_QaUeh8W6rwq08I5LxnyHrSkNf01uXHwdE8K0,39095
+setuptools/sandbox.py,sha256=fMqtcOuipHO6RKPh1YB5o7d985dLKo76Whp3vrIei2E,14906
+setuptools/script (dev).tmpl,sha256=RUzQzCQUaXtwdLtYHWYbIQmOaES5Brqq1FvUA_tu-5I,218
+setuptools/script.tmpl,sha256=WGTt5piezO27c-Dbx6l5Q4T3Ff20A5z7872hv3aAhYY,138
+setuptools/tests/__init__.py,sha256=AnBfls2iJbTDQzmMKeLRt-9lxhaOHUVOZEgXv89Uwvs,335
+setuptools/tests/__pycache__/__init__.cpython-312.pyc,,
+setuptools/tests/__pycache__/contexts.cpython-312.pyc,,
+setuptools/tests/__pycache__/environment.cpython-312.pyc,,
+setuptools/tests/__pycache__/fixtures.cpython-312.pyc,,
+setuptools/tests/__pycache__/mod_with_constant.cpython-312.pyc,,
+setuptools/tests/__pycache__/namespaces.cpython-312.pyc,,
+setuptools/tests/__pycache__/script-with-bom.cpython-312.pyc,,
+setuptools/tests/__pycache__/server.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_archive_util.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_bdist_deprecations.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_bdist_egg.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_bdist_wheel.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_build.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_build_clib.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_build_ext.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_build_meta.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_build_py.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_config_discovery.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_core_metadata.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_depends.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_develop.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_dist.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_dist_info.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_distutils_adoption.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_easy_install.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_editable_install.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_egg_info.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_extern.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_find_packages.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_find_py_modules.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_glob.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_install_scripts.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_logging.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_manifest.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_namespaces.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_packageindex.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_sandbox.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_sdist.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_setopt.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_setuptools.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_shutil_wrapper.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_unicode_utils.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_virtualenv.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_warnings.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_wheel.cpython-312.pyc,,
+setuptools/tests/__pycache__/test_windows_wrappers.cpython-312.pyc,,
+setuptools/tests/__pycache__/text.cpython-312.pyc,,
+setuptools/tests/__pycache__/textwrap.cpython-312.pyc,,
+setuptools/tests/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/tests/compat/__pycache__/__init__.cpython-312.pyc,,
+setuptools/tests/compat/__pycache__/py39.cpython-312.pyc,,
+setuptools/tests/compat/py39.py,sha256=eUy7_F-6KRTOIKl-veshUu6I0EdTSdBZMh0EV0lZ1-g,135
+setuptools/tests/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/tests/config/__pycache__/__init__.cpython-312.pyc,,
+setuptools/tests/config/__pycache__/test_apply_pyprojecttoml.cpython-312.pyc,,
+setuptools/tests/config/__pycache__/test_expand.cpython-312.pyc,,
+setuptools/tests/config/__pycache__/test_pyprojecttoml.cpython-312.pyc,,
+setuptools/tests/config/__pycache__/test_pyprojecttoml_dynamic_deps.cpython-312.pyc,,
+setuptools/tests/config/__pycache__/test_setupcfg.cpython-312.pyc,,
+setuptools/tests/config/downloads/__init__.py,sha256=9ixnDEdyL_arKbUzfuiJftAj9bGxKz8M9alOFZMjx9Y,1827
+setuptools/tests/config/downloads/__pycache__/__init__.cpython-312.pyc,,
+setuptools/tests/config/downloads/__pycache__/preload.cpython-312.pyc,,
+setuptools/tests/config/downloads/preload.py,sha256=sIGGZpY3cmMpMwiJYYYYHG2ifZJkvJgEotRFtiulV1I,450
+setuptools/tests/config/setupcfg_examples.txt,sha256=cAbVvCbkFZuTUL6xRRzRgqyB0rLvJTfvw3D30glo2OE,1912
+setuptools/tests/config/test_apply_pyprojecttoml.py,sha256=l6nE4d8WLU_eSWRic7VSoqeKv9Bi7CZGHcEuB2ehk2w,28807
+setuptools/tests/config/test_expand.py,sha256=S0oT6JvgA_oujR4YS4RUuf5gmOt1CTQV66RQDzV8xd4,8933
+setuptools/tests/config/test_pyprojecttoml.py,sha256=0LefSljUhA6MqtJ5AVzLhomqZcYiFKdu_1ckDeMT1LY,12406
+setuptools/tests/config/test_pyprojecttoml_dynamic_deps.py,sha256=9W73-yLhZJmvCiO4rTiQoBpZT5wNA90Xbd5n2HCshd4,3271
+setuptools/tests/config/test_setupcfg.py,sha256=ZvN-O-2Dgon1adp6oM6il8JWdgT9y196fRvqESU5ELI,33427
+setuptools/tests/contexts.py,sha256=TAdZKxmmodx1ExMVo01o4QpRjpIpo4X3IWKq_BnjxpU,3480
+setuptools/tests/environment.py,sha256=95_UtTaRiuvwYC9eXKEHbn02kDtZysvZq3UZJmPUj1I,3102
+setuptools/tests/fixtures.py,sha256=-V7iD6BeE2E0Rw6dVvTOCm36JG8ZTTnrXhN0GISlgrg,5197
+setuptools/tests/indexes/test_links_priority/external.html,sha256=eL9euOuE93JKZdqlXxBOlHbKwIuNuIdq7GBRpsaPMcU,92
+setuptools/tests/indexes/test_links_priority/simple/foobar/index.html,sha256=DD-TKr7UU4zAjHHz4VexYDNSAzR27levSh1c-k3ZdLE,174
+setuptools/tests/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+setuptools/tests/integration/__pycache__/__init__.cpython-312.pyc,,
+setuptools/tests/integration/__pycache__/helpers.cpython-312.pyc,,
+setuptools/tests/integration/__pycache__/test_pip_install_sdist.cpython-312.pyc,,
+setuptools/tests/integration/helpers.py,sha256=3PHcS9SCA-fwVJmUP2ad5NQOttJAETI5Nnoc_xroO5k,2522
+setuptools/tests/integration/test_pip_install_sdist.py,sha256=SFbvuYF_hDzt6OtsQ5GjFNnxmoJ_eElfvpYsiyyGJ-g,8256
+setuptools/tests/mod_with_constant.py,sha256=X_Kj80M55w1tmQ4f7uZY91ZTALo4hKVT6EHxgYocUMQ,22
+setuptools/tests/namespaces.py,sha256=HPcI3nR5MCFWXpaADIJ1fwKxymcQgBkuw87Ic5PUSAQ,2774
+setuptools/tests/script-with-bom.py,sha256=hRRgIizEULGiG_ZTNoMY46HhKhxpWfy5FGcD6Qbh5fc,18
+setuptools/tests/server.py,sha256=0FDZf0cSInCP5n1haK7AxHo3jD261RK7D3-RjP-F53k,2397
+setuptools/tests/test_archive_util.py,sha256=buuKdY8XkW26Pe3IKAoBRGHG0MDumnuNoPg2WsAQzIg,845
+setuptools/tests/test_bdist_deprecations.py,sha256=75Xq3gYn79LIIyusEltbHan0bEgAt2e_CaL7KLS8-KQ,775
+setuptools/tests/test_bdist_egg.py,sha256=6PaYN1F3JDbIh1uK0urv7yJFcx98z5dn9SOJ8Mv91l8,1957
+setuptools/tests/test_bdist_wheel.py,sha256=dZ9a7OT_UyRvLnoCi2KGEIbtzhEQjM3YutYMA6ZCezs,23083
+setuptools/tests/test_build.py,sha256=wJgMz2hwHADcLFg-nXrwRVhus7hjmAeEGgrpIQwCGnA,798
+setuptools/tests/test_build_clib.py,sha256=bX51XRAf4uO7IuHFpjePnoK8mE74N2gsoeEqF-ofgws,3123
+setuptools/tests/test_build_ext.py,sha256=e4ZSxsYPB5zq1KSqGEuATZ0t0PJQzMhjjkKJ-hIjcgc,10099
+setuptools/tests/test_build_meta.py,sha256=Iakpp9Micvhxi9_F2RPyY2NnCB1G90a38s4O5A3CuiE,34118
+setuptools/tests/test_build_py.py,sha256=gobME_Cvzf6Ugxq70iWfXekb_xyyT61khwjFq8zkwfw,14186
+setuptools/tests/test_config_discovery.py,sha256=FqV-lOtkqaI-ayzU2zocSdD5TaRAgCZnixNDilKA6FQ,22580
+setuptools/tests/test_core_metadata.py,sha256=vbVJ5_Lsx_hsO_GdB6nQEXJRjA2ydx6_qSbr5LpheAA,20881
+setuptools/tests/test_depends.py,sha256=yQBXoQbNQlJit6mbRVoz6Bb553f3sNrq02lZimNz5XY,424
+setuptools/tests/test_develop.py,sha256=CLzXZ8-b5-VFTuau4P4yXEdLx1UdyTFcOfrV0qyUIdE,5142
+setuptools/tests/test_dist.py,sha256=GFjyL2etAxvVM3q7NhFEGcXS5gyKj8VzbqcbKzpqbOk,8901
+setuptools/tests/test_dist_info.py,sha256=5kBRj9tuBsVreBsY22H2feMO_JQZsSoOZMU_MJfUevY,7077
+setuptools/tests/test_distutils_adoption.py,sha256=_eynrOfyEqXFEmjUJhzpe8GXPyTUPvNSObs4qAAmBy8,5987
+setuptools/tests/test_easy_install.py,sha256=jx4lpFyee0G432cdnwBow3AkL4ibw-0QILwldwv5SCI,53534
+setuptools/tests/test_editable_install.py,sha256=7eTEtpT0k7QeVyZg64eh3kZn-SjckuB9LcokOuV37DI,43383
+setuptools/tests/test_egg_info.py,sha256=QCzoUOkFocmbkwS6XU7F8WNzKE8CGEMRxYBqKLgfUrc,44866
+setuptools/tests/test_extern.py,sha256=rpKU6oCcksumLwf5TeKlDluFQ0TUfbPwTLQbpxcFrCU,296
+setuptools/tests/test_find_packages.py,sha256=CTLAcTzWGWBLCcd2aAsUVkvO3ibrlqexFBdDKOWPoq8,7819
+setuptools/tests/test_find_py_modules.py,sha256=zQjuhIG5TQN2SJPix9ARo4DL_w84Ln8QsHDUjjbrtAQ,2404
+setuptools/tests/test_glob.py,sha256=P3JvpH-kXQ4BZ3zvRF-zKxOgwyWzwIaQIz0WHdxS0kk,887
+setuptools/tests/test_install_scripts.py,sha256=scIrJ6a_ssKqg4vIBNaUjmAKHEYLUUZ9WKnPeKnE6gc,3433
+setuptools/tests/test_logging.py,sha256=zlE5DlldukC7Jc54FNvDV_7ux3ErAkrfrN5CSsnNOUQ,2099
+setuptools/tests/test_manifest.py,sha256=eMg65pIA52DizB6mpktSU-b8CjwaNCS5MSgL_V1LrFI,18562
+setuptools/tests/test_namespaces.py,sha256=Y6utoe5PHHqL_DlgawqB9F8XpsUDPvvw1sQMenK04e0,4515
+setuptools/tests/test_packageindex.py,sha256=qEjLHpSu2gAkegwEstzHQT-Om1uQIYjA8zeNzEX79uo,8775
+setuptools/tests/test_sandbox.py,sha256=shUWE7fLTWe7Jzdfi6NheBWauG3oUukbUV46cArD0u0,4330
+setuptools/tests/test_sdist.py,sha256=RYLvPa_nfyC1ZmoinzqMzJynTDG4RtPYC19_0LU6pvs,32872
+setuptools/tests/test_setopt.py,sha256=3VxxM4ATfP-P4AGnDjoWCnHr5-i9CSEQTFYU1-FTnvI,1365
+setuptools/tests/test_setuptools.py,sha256=_eIhqKf45-OtHqxRf20KndOZJlJdS0PuFLXBO3M-LN8,9008
+setuptools/tests/test_shutil_wrapper.py,sha256=g15E11PtZxG-InB2BWNFyH-svObXx2XcMhgMLJPuFnc,641
+setuptools/tests/test_unicode_utils.py,sha256=xWfEEl8jkQCt9othUTXJfFmdyATAFggJs2tTxjbumbw,316
+setuptools/tests/test_virtualenv.py,sha256=g-njC_9JTAs1YVx_1dGJ_Q6RlInO4qKVu9-XAgNb6TY,3730
+setuptools/tests/test_warnings.py,sha256=zwR2zcnCeCeDqILZlJOPAcuyPHoDvGu1OtOVYiLMk74,3347
+setuptools/tests/test_wheel.py,sha256=J-83W1KdXTgAjFZE3H-ytohhvDE1iqdbE5YF5jLQlGQ,19370
+setuptools/tests/test_windows_wrappers.py,sha256=aF6UTowN3yzCgdBh9nDQVvYIfSYogrTK776TEyXEBqg,7881
+setuptools/tests/text.py,sha256=a12197pMVTvB6FAWQ0ujT8fIQiLIWJlFAl1UCaDUDfg,123
+setuptools/tests/textwrap.py,sha256=FNNNq_MiaEJx88PnsbJQIRxmj1qmgcAOCXXRsODPJN4,98
+setuptools/unicode_utils.py,sha256=ukMGh8pEAw6F_Ezb-K5D3c-078RgA_GcF0oW6lg4lSs,3189
+setuptools/version.py,sha256=WJCeUuyq74Aok2TeK9-OexZOu8XrlQy7-y0BEuWNovQ,161
+setuptools/warnings.py,sha256=oY0Se5eOqje_FEyjTgonUc0XGwgsrI5cgm1kkwulz_w,3796
+setuptools/wheel.py,sha256=xkAtvgm7uPTyYV2zqVmQ0wA8kLwOyRT2Jes1zAy07Ks,8624
+setuptools/windows_support.py,sha256=wW4IYLM1Bv7Z1MaauP2xmPjyy-wkmQnXdyvXscAf9fw,726
diff --git a/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/WHEEL
new file mode 100644
index 0000000..91720dd
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: setuptools (78.0.2)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/entry_points.txt b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/entry_points.txt
new file mode 100644
index 0000000..0db0a6c
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/entry_points.txt
@@ -0,0 +1,51 @@
+[distutils.commands]
+alias = setuptools.command.alias:alias
+bdist_egg = setuptools.command.bdist_egg:bdist_egg
+bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm
+bdist_wheel = setuptools.command.bdist_wheel:bdist_wheel
+build = setuptools.command.build:build
+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
+editable_wheel = setuptools.command.editable_wheel:editable_wheel
+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
+
+[distutils.setup_keywords]
+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
+use_2to3 = setuptools.dist:invalid_unless_false
+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
+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]
+keywords = setuptools.dist:Distribution._finalize_setup_keywords
+parent_finalize = setuptools.dist:_Distribution.finalize_options
diff --git a/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/licenses/LICENSE b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/licenses/LICENSE
new file mode 100644
index 0000000..1bb5a44
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/licenses/LICENSE
@@ -0,0 +1,17 @@
+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/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/top_level.txt
new file mode 100644
index 0000000..b5ac107
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools-78.0.2.dist-info/top_level.txt
@@ -0,0 +1,3 @@
+_distutils_hack
+pkg_resources
+setuptools
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/__init__.py
new file mode 100644
index 0000000..64464df
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/__init__.py
@@ -0,0 +1,286 @@
+"""Extensions to the 'distutils' for large or complex distributions"""
+# mypy: disable_error_code=override
+# Command.reinitialize_command has an extra **kw param that distutils doesn't have
+# Can't disable on the exact line because distutils doesn't exists on Python 3.12
+# and mypy isn't aware of distutils_hack, causing distutils.core.Command to be Any,
+# and a [unused-ignore] to be raised on 3.12+
+
+from __future__ import annotations
+
+import functools
+import os
+import re
+import sys
+from abc import abstractmethod
+from collections.abc import Mapping
+from typing import TYPE_CHECKING, TypeVar, overload
+
+sys.path.extend(((vendor_path := os.path.join(os.path.dirname(os.path.dirname(__file__)), 'setuptools', '_vendor')) not in sys.path) * [vendor_path]) # fmt: skip
+# workaround for #4476
+sys.modules.pop('backports', None)
+
+import _distutils_hack.override # noqa: F401
+
+from . import logging, monkey
+from .depends import Require
+from .discovery import PackageFinder, PEP420PackageFinder
+from .dist import Distribution
+from .extension import Extension
+from .version import __version__ as __version__
+from .warnings import SetuptoolsDeprecationWarning
+
+import distutils.core
+from distutils.errors import DistutilsOptionError
+
+__all__ = [
+ 'setup',
+ 'Distribution',
+ 'Command',
+ 'Extension',
+ 'Require',
+ 'SetuptoolsDeprecationWarning',
+ 'find_packages',
+ 'find_namespace_packages',
+]
+
+_CommandT = TypeVar("_CommandT", bound="_Command")
+
+bootstrap_install_from = None
+
+find_packages = PackageFinder.find
+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: Mapping[str, object]) -> None:
+ _incl = 'dependency_links', 'setup_requires'
+ filtered = {k: attrs[k] for k in set(_incl) & set(attrs)}
+ super().__init__(filtered)
+ # Prevent accidentally triggering discovery with incomplete set of attrs
+ self.set_defaults._disable()
+
+ def _get_project_config_files(self, filenames=None):
+ """Ignore ``pyproject.toml``, they are not related to setup_requires"""
+ try:
+ cfg, _toml = super()._split_standard_project_metadata(filenames)
+ except Exception:
+ return filenames, ()
+ return cfg, ()
+
+ 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:
+ _fetch_build_eggs(dist)
+
+
+def _fetch_build_eggs(dist: Distribution):
+ try:
+ dist.fetch_build_eggs(dist.setup_requires)
+ except Exception as ex:
+ msg = """
+ It is possible a package already installed in your system
+ contains an version that is invalid according to PEP 440.
+ You can try `pip install --use-pep517` as a workaround for this problem,
+ or rely on a new virtual environment.
+
+ If the problem refers to a package that is not installed yet,
+ please contact that package's maintainers or distributors.
+ """
+ if "InvalidVersion" in ex.__class__.__name__:
+ if hasattr(ex, "add_note"):
+ ex.add_note(msg) # PEP 678
+ else:
+ dist.announce(f"\n{msg}\n")
+ raise
+
+
+def setup(**attrs):
+ logging.configure()
+ # 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__
+
+if TYPE_CHECKING:
+ # Work around a mypy issue where type[T] can't be used as a base: https://github.com/python/mypy/issues/10962
+ from distutils.core import Command as _Command
+else:
+ _Command = monkey.get_unpatched(distutils.core.Command)
+
+
+class Command(_Command):
+ """
+ Setuptools internal actions are organized using a *command design pattern*.
+ This means that each action (or group of closely related actions) executed during
+ the build should be implemented as a ``Command`` subclass.
+
+ These commands are abstractions and do not necessarily correspond to a command that
+ can (or should) be executed via a terminal, in a CLI fashion (although historically
+ they would).
+
+ When creating a new command from scratch, custom defined classes **SHOULD** inherit
+ from ``setuptools.Command`` and implement a few mandatory methods.
+ Between these mandatory methods, are listed:
+ :meth:`initialize_options`, :meth:`finalize_options` and :meth:`run`.
+
+ A useful analogy for command classes is to think of them as subroutines with local
+ variables called "options". The options are "declared" in :meth:`initialize_options`
+ and "defined" (given their final values, aka "finalized") in :meth:`finalize_options`,
+ both of which must be defined by every command class. The "body" of the subroutine,
+ (where it does all the work) is the :meth:`run` method.
+ Between :meth:`initialize_options` and :meth:`finalize_options`, ``setuptools`` may set
+ the values for options/attributes based on user's input (or circumstance),
+ which means that the implementation should be careful to not overwrite values in
+ :meth:`finalize_options` unless necessary.
+
+ Please note that other commands (or other parts of setuptools) may also overwrite
+ the values of the command's options/attributes multiple times during the build
+ process.
+ Therefore it is important to consistently implement :meth:`initialize_options` and
+ :meth:`finalize_options`. For example, all derived attributes (or attributes that
+ depend on the value of other attributes) **SHOULD** be recomputed in
+ :meth:`finalize_options`.
+
+ When overwriting existing commands, custom defined classes **MUST** abide by the
+ same APIs implemented by the original class. They also **SHOULD** inherit from the
+ original class.
+ """
+
+ command_consumes_arguments = False
+ distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution
+
+ def __init__(self, dist: Distribution, **kw) -> None:
+ """
+ Construct the command for dist, updating
+ vars(self) with any keyword parameters.
+ """
+ super().__init__(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, str):
+ raise DistutilsOptionError(f"'{option}' must be a {what} (got `{val}`)")
+ return val
+
+ def ensure_string_list(self, option: str) -> None:
+ 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"].
+
+ ..
+ TODO: This method seems to be similar to the one in ``distutils.cmd``
+ Probably it is just here for backward compatibility with old Python versions?
+
+ :meta private:
+ """
+ val = getattr(self, option)
+ if val is None:
+ return
+ elif isinstance(val, str):
+ setattr(self, option, re.split(r',\s*|\s+', val))
+ else:
+ if isinstance(val, list):
+ ok = all(isinstance(v, str) for v in val)
+ else:
+ ok = False
+ if not ok:
+ raise DistutilsOptionError(
+ f"'{option}' must be a list of strings (got {val!r})"
+ )
+
+ @overload
+ def reinitialize_command(
+ self, command: str, reinit_subcommands: bool = False, **kw
+ ) -> _Command: ...
+ @overload
+ def reinitialize_command(
+ self, command: _CommandT, reinit_subcommands: bool = False, **kw
+ ) -> _CommandT: ...
+ def reinitialize_command(
+ self, command: str | _Command, reinit_subcommands: bool = False, **kw
+ ) -> _Command:
+ cmd = _Command.reinitialize_command(self, command, reinit_subcommands)
+ vars(cmd).update(kw)
+ return cmd # pyright: ignore[reportReturnType] # pypa/distutils#307
+
+ @abstractmethod
+ def initialize_options(self) -> None:
+ """
+ Set or (reset) all options/attributes/caches used by the command
+ to their default values. Note that these values may be overwritten during
+ the build.
+ """
+ raise NotImplementedError
+
+ @abstractmethod
+ def finalize_options(self) -> None:
+ """
+ Set final values for all options/attributes used by the command.
+ Most of the time, each option/attribute/cache should only be set if it does not
+ have any value yet (e.g. ``if self.attr is None: self.attr = val``).
+ """
+ raise NotImplementedError
+
+ @abstractmethod
+ def run(self) -> None:
+ """
+ Execute the actions intended by the command.
+ (Side effects **SHOULD** only take place when :meth:`run` is executed,
+ for example, creating new files or writing to the terminal output).
+ """
+ raise NotImplementedError
+
+
+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)
+
+
+class sic(str):
+ """Treat this string as-is (https://en.wikipedia.org/wiki/Sic)"""
+
+
+# Apply monkey patches
+monkey.patch_all()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..48e7282
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_core_metadata.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_core_metadata.cpython-312.pyc
new file mode 100644
index 0000000..fd361a2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_core_metadata.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_entry_points.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_entry_points.cpython-312.pyc
new file mode 100644
index 0000000..ee9e63e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_entry_points.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_imp.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_imp.cpython-312.pyc
new file mode 100644
index 0000000..1d39a94
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_imp.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_importlib.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_importlib.cpython-312.pyc
new file mode 100644
index 0000000..c0a857f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_importlib.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_itertools.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_itertools.cpython-312.pyc
new file mode 100644
index 0000000..28bf600
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_itertools.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_normalization.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_normalization.cpython-312.pyc
new file mode 100644
index 0000000..52d9d74
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_normalization.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_path.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_path.cpython-312.pyc
new file mode 100644
index 0000000..d720311
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_path.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_reqs.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_reqs.cpython-312.pyc
new file mode 100644
index 0000000..e2ff74c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_reqs.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_shutil.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_shutil.cpython-312.pyc
new file mode 100644
index 0000000..ff0444d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_shutil.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_static.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_static.cpython-312.pyc
new file mode 100644
index 0000000..9ca2bbe
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/_static.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/archive_util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/archive_util.cpython-312.pyc
new file mode 100644
index 0000000..02e3c89
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/archive_util.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/build_meta.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/build_meta.cpython-312.pyc
new file mode 100644
index 0000000..c6520f6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/build_meta.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/depends.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/depends.cpython-312.pyc
new file mode 100644
index 0000000..098d062
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/depends.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/discovery.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/discovery.cpython-312.pyc
new file mode 100644
index 0000000..56098b8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/discovery.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/dist.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/dist.cpython-312.pyc
new file mode 100644
index 0000000..5a76b5b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/dist.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/errors.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/errors.cpython-312.pyc
new file mode 100644
index 0000000..e4d9a68
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/errors.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/extension.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/extension.cpython-312.pyc
new file mode 100644
index 0000000..5189a14
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/extension.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/glob.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/glob.cpython-312.pyc
new file mode 100644
index 0000000..d25fa80
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/glob.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/installer.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/installer.cpython-312.pyc
new file mode 100644
index 0000000..47baece
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/installer.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/launch.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/launch.cpython-312.pyc
new file mode 100644
index 0000000..17263d4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/launch.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/logging.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/logging.cpython-312.pyc
new file mode 100644
index 0000000..a66940e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/logging.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/modified.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/modified.cpython-312.pyc
new file mode 100644
index 0000000..660284b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/modified.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/monkey.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/monkey.cpython-312.pyc
new file mode 100644
index 0000000..ef52eee
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/monkey.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/msvc.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/msvc.cpython-312.pyc
new file mode 100644
index 0000000..20bfedb
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/msvc.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/namespaces.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/namespaces.cpython-312.pyc
new file mode 100644
index 0000000..e68a63e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/namespaces.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/package_index.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/package_index.cpython-312.pyc
new file mode 100644
index 0000000..aeeeaea
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/package_index.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/sandbox.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/sandbox.cpython-312.pyc
new file mode 100644
index 0000000..fdaf442
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/sandbox.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/unicode_utils.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/unicode_utils.cpython-312.pyc
new file mode 100644
index 0000000..dcc7958
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/unicode_utils.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/version.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/version.cpython-312.pyc
new file mode 100644
index 0000000..8c98975
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/version.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/warnings.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/warnings.cpython-312.pyc
new file mode 100644
index 0000000..464a020
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/warnings.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/wheel.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/wheel.cpython-312.pyc
new file mode 100644
index 0000000..f2bead9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/wheel.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/__pycache__/windows_support.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/windows_support.cpython-312.pyc
new file mode 100644
index 0000000..c1cd327
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/__pycache__/windows_support.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_core_metadata.py b/testcline/lib/python3.12/site-packages/setuptools/_core_metadata.py
new file mode 100644
index 0000000..a52d5cf
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_core_metadata.py
@@ -0,0 +1,337 @@
+"""
+Handling of Core Metadata for Python packages (including reading and writing).
+
+See: https://packaging.python.org/en/latest/specifications/core-metadata/
+"""
+
+from __future__ import annotations
+
+import os
+import stat
+import textwrap
+from email import message_from_file
+from email.message import Message
+from tempfile import NamedTemporaryFile
+
+from packaging.markers import Marker
+from packaging.requirements import Requirement
+from packaging.utils import canonicalize_name, canonicalize_version
+from packaging.version import Version
+
+from . import _normalization, _reqs
+from ._static import is_static
+from .warnings import SetuptoolsDeprecationWarning
+
+from distutils.util import rfc822_escape
+
+
+def get_metadata_version(self):
+ mv = getattr(self, 'metadata_version', None)
+ if mv is None:
+ mv = Version('2.4')
+ self.metadata_version = mv
+ return mv
+
+
+def rfc822_unescape(content: str) -> str:
+ """Reverse RFC-822 escaping by removing leading whitespaces from content."""
+ lines = content.splitlines()
+ if len(lines) == 1:
+ return lines[0].lstrip()
+ return '\n'.join((lines[0].lstrip(), textwrap.dedent('\n'.join(lines[1:]))))
+
+
+def _read_field_from_msg(msg: Message, field: str) -> str | None:
+ """Read Message header field."""
+ value = msg[field]
+ if value == 'UNKNOWN':
+ return None
+ return value
+
+
+def _read_field_unescaped_from_msg(msg: Message, field: str) -> str | None:
+ """Read Message header field and apply rfc822_unescape."""
+ value = _read_field_from_msg(msg, field)
+ if value is None:
+ return value
+ return rfc822_unescape(value)
+
+
+def _read_list_from_msg(msg: Message, field: str) -> list[str] | None:
+ """Read Message header field and return all results as list."""
+ values = msg.get_all(field, None)
+ if values == []:
+ return None
+ return values
+
+
+def _read_payload_from_msg(msg: Message) -> str | None:
+ value = str(msg.get_payload()).strip()
+ if value == 'UNKNOWN' or not value:
+ return None
+ return value
+
+
+def read_pkg_file(self, file):
+ """Reads the metadata values from a file object."""
+ msg = message_from_file(file)
+
+ self.metadata_version = Version(msg['metadata-version'])
+ self.name = _read_field_from_msg(msg, 'name')
+ self.version = _read_field_from_msg(msg, 'version')
+ self.description = _read_field_from_msg(msg, 'summary')
+ # we are filling author only.
+ self.author = _read_field_from_msg(msg, 'author')
+ self.maintainer = None
+ self.author_email = _read_field_from_msg(msg, 'author-email')
+ self.maintainer_email = None
+ self.url = _read_field_from_msg(msg, 'home-page')
+ self.download_url = _read_field_from_msg(msg, 'download-url')
+ self.license = _read_field_unescaped_from_msg(msg, 'license')
+ self.license_expression = _read_field_unescaped_from_msg(msg, 'license-expression')
+
+ self.long_description = _read_field_unescaped_from_msg(msg, 'description')
+ if self.long_description is None and self.metadata_version >= Version('2.1'):
+ self.long_description = _read_payload_from_msg(msg)
+ self.description = _read_field_from_msg(msg, 'summary')
+
+ if 'keywords' in msg:
+ self.keywords = _read_field_from_msg(msg, 'keywords').split(',')
+
+ self.platforms = _read_list_from_msg(msg, 'platform')
+ self.classifiers = _read_list_from_msg(msg, 'classifier')
+
+ # PEP 314 - these fields only exist in 1.1
+ if self.metadata_version == Version('1.1'):
+ self.requires = _read_list_from_msg(msg, 'requires')
+ self.provides = _read_list_from_msg(msg, 'provides')
+ self.obsoletes = _read_list_from_msg(msg, 'obsoletes')
+ else:
+ self.requires = None
+ self.provides = None
+ self.obsoletes = None
+
+ self.license_files = _read_list_from_msg(msg, 'license-file')
+
+
+def single_line(val):
+ """
+ Quick and dirty validation for Summary pypa/setuptools#1390.
+ """
+ if '\n' in val:
+ # TODO: Replace with `raise ValueError("newlines not allowed")`
+ # after reviewing #2893.
+ msg = "newlines are not allowed in `summary` and will break in the future"
+ SetuptoolsDeprecationWarning.emit("Invalid config.", msg)
+ # due_date is undefined. Controversial change, there was a lot of push back.
+ val = val.strip().split('\n')[0]
+ return val
+
+
+def write_pkg_info(self, base_dir):
+ """Write the PKG-INFO file into the release tree."""
+ temp = ""
+ final = os.path.join(base_dir, 'PKG-INFO')
+ try:
+ # Use a temporary file while writing to avoid race conditions
+ # (e.g. `importlib.metadata` reading `.egg-info/PKG-INFO`):
+ with NamedTemporaryFile("w", encoding="utf-8", dir=base_dir, delete=False) as f:
+ temp = f.name
+ self.write_pkg_file(f)
+ permissions = stat.S_IMODE(os.lstat(temp).st_mode)
+ os.chmod(temp, permissions | stat.S_IRGRP | stat.S_IROTH)
+ os.replace(temp, final) # atomic operation.
+ finally:
+ if temp and os.path.exists(temp):
+ os.remove(temp)
+
+
+# Based on Python 3.5 version
+def write_pkg_file(self, file): # noqa: C901 # is too complex (14) # FIXME
+ """Write the PKG-INFO format data to a file object."""
+ version = self.get_metadata_version()
+
+ def write_field(key, value):
+ file.write(f"{key}: {value}\n")
+
+ write_field('Metadata-Version', str(version))
+ write_field('Name', self.get_name())
+ write_field('Version', self.get_version())
+
+ summary = self.get_description()
+ if summary:
+ write_field('Summary', single_line(summary))
+
+ optional_fields = (
+ ('Home-page', 'url'),
+ ('Download-URL', 'download_url'),
+ ('Author', 'author'),
+ ('Author-email', 'author_email'),
+ ('Maintainer', 'maintainer'),
+ ('Maintainer-email', 'maintainer_email'),
+ )
+
+ for field, attr in optional_fields:
+ attr_val = getattr(self, attr, None)
+ if attr_val is not None:
+ write_field(field, attr_val)
+
+ if license_expression := self.license_expression:
+ write_field('License-Expression', license_expression)
+ elif license := self.get_license():
+ write_field('License', rfc822_escape(license))
+
+ for label, url in self.project_urls.items():
+ write_field('Project-URL', f'{label}, {url}')
+
+ keywords = ','.join(self.get_keywords())
+ if keywords:
+ write_field('Keywords', keywords)
+
+ platforms = self.get_platforms() or []
+ for platform in platforms:
+ write_field('Platform', platform)
+
+ self._write_list(file, 'Classifier', self.get_classifiers())
+
+ # PEP 314
+ self._write_list(file, 'Requires', self.get_requires())
+ self._write_list(file, 'Provides', self.get_provides())
+ self._write_list(file, 'Obsoletes', self.get_obsoletes())
+
+ # Setuptools specific for PEP 345
+ if hasattr(self, 'python_requires'):
+ write_field('Requires-Python', self.python_requires)
+
+ # PEP 566
+ if self.long_description_content_type:
+ write_field('Description-Content-Type', self.long_description_content_type)
+
+ safe_license_files = map(_safe_license_file, self.license_files or [])
+ self._write_list(file, 'License-File', safe_license_files)
+ _write_requirements(self, file)
+
+ for field, attr in _POSSIBLE_DYNAMIC_FIELDS.items():
+ if (val := getattr(self, attr, None)) and not is_static(val):
+ write_field('Dynamic', field)
+
+ long_description = self.get_long_description()
+ if long_description:
+ file.write(f"\n{long_description}")
+ if not long_description.endswith("\n"):
+ file.write("\n")
+
+
+def _write_requirements(self, file):
+ for req in _reqs.parse(self.install_requires):
+ file.write(f"Requires-Dist: {req}\n")
+
+ processed_extras = {}
+ for augmented_extra, reqs in self.extras_require.items():
+ # Historically, setuptools allows "augmented extras": `:`
+ unsafe_extra, _, condition = augmented_extra.partition(":")
+ unsafe_extra = unsafe_extra.strip()
+ extra = _normalization.safe_extra(unsafe_extra)
+
+ if extra:
+ _write_provides_extra(file, processed_extras, extra, unsafe_extra)
+ for req in _reqs.parse_strings(reqs):
+ r = _include_extra(req, extra, condition.strip())
+ file.write(f"Requires-Dist: {r}\n")
+
+ return processed_extras
+
+
+def _include_extra(req: str, extra: str, condition: str) -> Requirement:
+ r = Requirement(req) # create a fresh object that can be modified
+ parts = (
+ f"({r.marker})" if r.marker else None,
+ f"({condition})" if condition else None,
+ f"extra == {extra!r}" if extra else None,
+ )
+ r.marker = Marker(" and ".join(x for x in parts if x))
+ return r
+
+
+def _write_provides_extra(file, processed_extras, safe, unsafe):
+ previous = processed_extras.get(safe)
+ if previous == unsafe:
+ SetuptoolsDeprecationWarning.emit(
+ 'Ambiguity during "extra" normalization for dependencies.',
+ f"""
+ {previous!r} and {unsafe!r} normalize to the same value:\n
+ {safe!r}\n
+ In future versions, setuptools might halt the build process.
+ """,
+ see_url="https://peps.python.org/pep-0685/",
+ )
+ else:
+ processed_extras[safe] = unsafe
+ file.write(f"Provides-Extra: {safe}\n")
+
+
+# from pypa/distutils#244; needed only until that logic is always available
+def get_fullname(self):
+ return _distribution_fullname(self.get_name(), self.get_version())
+
+
+def _distribution_fullname(name: str, version: str) -> str:
+ """
+ >>> _distribution_fullname('setup.tools', '1.0-2')
+ 'setup_tools-1.0.post2'
+ >>> _distribution_fullname('setup-tools', '1.2post2')
+ 'setup_tools-1.2.post2'
+ >>> _distribution_fullname('setup-tools', '1.0-r2')
+ 'setup_tools-1.0.post2'
+ >>> _distribution_fullname('setup.tools', '1.0.post')
+ 'setup_tools-1.0.post0'
+ >>> _distribution_fullname('setup.tools', '1.0+ubuntu-1')
+ 'setup_tools-1.0+ubuntu.1'
+ """
+ return "{}-{}".format(
+ canonicalize_name(name).replace('-', '_'),
+ canonicalize_version(version, strip_trailing_zero=False),
+ )
+
+
+def _safe_license_file(file):
+ # XXX: Do we need this after the deprecation discussed in #4892, #4896??
+ normalized = os.path.normpath(file).replace(os.sep, "/")
+ if "../" in normalized:
+ return os.path.basename(normalized) # Temporarily restore pre PEP639 behaviour
+ return normalized
+
+
+_POSSIBLE_DYNAMIC_FIELDS = {
+ # Core Metadata Field x related Distribution attribute
+ "author": "author",
+ "author-email": "author_email",
+ "classifier": "classifiers",
+ "description": "long_description",
+ "description-content-type": "long_description_content_type",
+ "download-url": "download_url",
+ "home-page": "url",
+ "keywords": "keywords",
+ "license": "license",
+ # XXX: License-File is complicated because the user gives globs that are expanded
+ # during the build. Without special handling it is likely always
+ # marked as Dynamic, which is an acceptable outcome according to:
+ # https://github.com/pypa/setuptools/issues/4629#issuecomment-2331233677
+ "license-file": "license_files",
+ "license-expression": "license_expression", # PEP 639
+ "maintainer": "maintainer",
+ "maintainer-email": "maintainer_email",
+ "obsoletes": "obsoletes",
+ # "obsoletes-dist": "obsoletes_dist", # NOT USED
+ "platform": "platforms",
+ "project-url": "project_urls",
+ "provides": "provides",
+ # "provides-dist": "provides_dist", # NOT USED
+ "provides-extra": "extras_require",
+ "requires": "requires",
+ "requires-dist": "install_requires",
+ # "requires-external": "requires_external", # NOT USED
+ "requires-python": "python_requires",
+ "summary": "description",
+ # "supported-platform": "supported_platforms", # NOT USED
+}
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__init__.py
new file mode 100644
index 0000000..e374d5c
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__init__.py
@@ -0,0 +1,14 @@
+import importlib
+import sys
+
+__version__, _, _ = sys.version.partition(' ')
+
+
+try:
+ # Allow Debian and pkgsrc (only) to customize system
+ # behavior. Ref pypa/distutils#2 and pypa/distutils#16.
+ # This hook is deprecated and no other environments
+ # should use it.
+ importlib.import_module('_distutils_system_mod')
+except ImportError:
+ pass
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..2075762
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_log.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_log.cpython-312.pyc
new file mode 100644
index 0000000..c1836b0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_log.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_macos_compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_macos_compat.cpython-312.pyc
new file mode 100644
index 0000000..0bc3835
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_macos_compat.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_modified.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_modified.cpython-312.pyc
new file mode 100644
index 0000000..dbdfdb4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_modified.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-312.pyc
new file mode 100644
index 0000000..363a919
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-312.pyc
new file mode 100644
index 0000000..0f4dd7c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-312.pyc
new file mode 100644
index 0000000..9f0ea96
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-312.pyc
new file mode 100644
index 0000000..0ac0d50
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/core.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/core.cpython-312.pyc
new file mode 100644
index 0000000..b1d5ea0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/core.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-312.pyc
new file mode 100644
index 0000000..e4b041d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/debug.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/debug.cpython-312.pyc
new file mode 100644
index 0000000..889b038
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/debug.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-312.pyc
new file mode 100644
index 0000000..5bbabb8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-312.pyc
new file mode 100644
index 0000000..b89b4ab
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dist.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dist.cpython-312.pyc
new file mode 100644
index 0000000..f967e69
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dist.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/errors.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/errors.cpython-312.pyc
new file mode 100644
index 0000000..8e7106d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/errors.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/extension.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/extension.cpython-312.pyc
new file mode 100644
index 0000000..e876309
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/extension.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-312.pyc
new file mode 100644
index 0000000..3f7fa5b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-312.pyc
new file mode 100644
index 0000000..1eef2fe
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-312.pyc
new file mode 100644
index 0000000..6f8c95e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/log.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/log.cpython-312.pyc
new file mode 100644
index 0000000..fe67eb9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/log.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-312.pyc
new file mode 100644
index 0000000..70bb59c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-312.pyc
new file mode 100644
index 0000000..d23548f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-312.pyc
new file mode 100644
index 0000000..12bae03
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-312.pyc
new file mode 100644
index 0000000..2ee7279
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/util.cpython-312.pyc
new file mode 100644
index 0000000..6f2d0ed
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/util.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/version.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/version.cpython-312.pyc
new file mode 100644
index 0000000..81a8764
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/version.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-312.pyc
new file mode 100644
index 0000000..972b2e3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/zosccompiler.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/zosccompiler.cpython-312.pyc
new file mode 100644
index 0000000..a3795ee
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/__pycache__/zosccompiler.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/_log.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/_log.py
new file mode 100644
index 0000000..0148f15
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/_log.py
@@ -0,0 +1,3 @@
+import logging
+
+log = logging.getLogger()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/_macos_compat.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/_macos_compat.py
new file mode 100644
index 0000000..76ecb96
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/_macos_compat.py
@@ -0,0 +1,12 @@
+import importlib
+import sys
+
+
+def bypass_compiler_fixup(cmd, args):
+ return cmd
+
+
+if sys.platform == 'darwin':
+ compiler_fixup = importlib.import_module('_osx_support').compiler_fixup
+else:
+ compiler_fixup = bypass_compiler_fixup
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/_modified.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/_modified.py
new file mode 100644
index 0000000..f64cab7
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/_modified.py
@@ -0,0 +1,95 @@
+"""Timestamp comparison of files and groups of files."""
+
+from __future__ import annotations
+
+import functools
+import os.path
+from collections.abc import Callable, Iterable
+from typing import Literal, TypeVar
+
+from jaraco.functools import splat
+
+from .compat.py39 import zip_strict
+from .errors import DistutilsFileError
+
+_SourcesT = TypeVar(
+ "_SourcesT", bound="str | bytes | os.PathLike[str] | os.PathLike[bytes]"
+)
+_TargetsT = TypeVar(
+ "_TargetsT", bound="str | bytes | os.PathLike[str] | os.PathLike[bytes]"
+)
+
+
+def _newer(source, target):
+ return not os.path.exists(target) or (
+ os.path.getmtime(source) > os.path.getmtime(target)
+ )
+
+
+def newer(
+ source: str | bytes | os.PathLike[str] | os.PathLike[bytes],
+ target: str | bytes | os.PathLike[str] | os.PathLike[bytes],
+) -> bool:
+ """
+ Is source modified more recently than target.
+
+ Returns True if 'source' is modified more recently than
+ 'target' or if 'target' does not exist.
+
+ Raises DistutilsFileError if 'source' does not exist.
+ """
+ if not os.path.exists(source):
+ raise DistutilsFileError(f"file {os.path.abspath(source)!r} does not exist")
+
+ return _newer(source, target)
+
+
+def newer_pairwise(
+ sources: Iterable[_SourcesT],
+ targets: Iterable[_TargetsT],
+ newer: Callable[[_SourcesT, _TargetsT], bool] = newer,
+) -> tuple[list[_SourcesT], list[_TargetsT]]:
+ """
+ Filter filenames where sources are newer than targets.
+
+ Walk two filename iterables in parallel, testing if each source is newer
+ than its corresponding target. Returns a pair of lists (sources,
+ targets) where source is newer than target, according to the semantics
+ of 'newer()'.
+ """
+ newer_pairs = filter(splat(newer), zip_strict(sources, targets))
+ return tuple(map(list, zip(*newer_pairs))) or ([], [])
+
+
+def newer_group(
+ sources: Iterable[str | bytes | os.PathLike[str] | os.PathLike[bytes]],
+ target: str | bytes | os.PathLike[str] | os.PathLike[bytes],
+ missing: Literal["error", "ignore", "newer"] = "error",
+) -> bool:
+ """
+ Is target out-of-date with respect to any file in sources.
+
+ Return True if 'target' is out-of-date with respect to any file
+ listed in 'sources'. In other words, if 'target' exists and is newer
+ than every file in 'sources', return False; otherwise return True.
+ ``missing`` controls how to handle a missing source file:
+
+ - error (default): allow the ``stat()`` call to fail.
+ - ignore: silently disregard any missing source files.
+ - newer: treat missing source files as "target out of date". This
+ mode is handy in "dry-run" mode: it will pretend to carry out
+ commands that wouldn't work because inputs are missing, but
+ that doesn't matter because dry-run won't run the commands.
+ """
+
+ def missing_as_newer(source):
+ return missing == 'newer' and not os.path.exists(source)
+
+ ignored = os.path.exists if missing == 'ignore' else None
+ return not os.path.exists(target) or any(
+ missing_as_newer(source) or _newer(source, target)
+ for source in filter(ignored, sources)
+ )
+
+
+newer_pairwise_group = functools.partial(newer_pairwise, newer=newer_group)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/_msvccompiler.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/_msvccompiler.py
new file mode 100644
index 0000000..8471cca
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/_msvccompiler.py
@@ -0,0 +1,5 @@
+from .compilers.C import msvc
+
+__all__ = ["MSVCCompiler"]
+
+MSVCCompiler = msvc.Compiler
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/archive_util.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/archive_util.py
new file mode 100644
index 0000000..d860f55
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/archive_util.py
@@ -0,0 +1,294 @@
+"""distutils.archive_util
+
+Utility functions for creating archive files (tarballs, zip files,
+that sort of thing)."""
+
+from __future__ import annotations
+
+import os
+from typing import Literal, overload
+
+try:
+ import zipfile
+except ImportError:
+ zipfile = None
+
+
+from ._log import log
+from .dir_util import mkpath
+from .errors import DistutilsExecError
+from .spawn import spawn
+
+try:
+ from pwd import getpwnam
+except ImportError:
+ getpwnam = None
+
+try:
+ from grp import getgrnam
+except ImportError:
+ getgrnam = None
+
+
+def _get_gid(name):
+ """Returns a gid, given a group name."""
+ if getgrnam is None or name is None:
+ return None
+ try:
+ result = getgrnam(name)
+ except KeyError:
+ result = None
+ if result is not None:
+ return result[2]
+ return None
+
+
+def _get_uid(name):
+ """Returns an uid, given a user name."""
+ if getpwnam is None or name is None:
+ return None
+ try:
+ result = getpwnam(name)
+ except KeyError:
+ result = None
+ if result is not None:
+ return result[2]
+ return None
+
+
+def make_tarball(
+ base_name: str,
+ base_dir: str | os.PathLike[str],
+ compress: Literal["gzip", "bzip2", "xz"] | None = "gzip",
+ verbose: bool = False,
+ dry_run: bool = False,
+ owner: str | None = None,
+ group: str | None = None,
+) -> str:
+ """Create a (possibly compressed) tar file from all the files under
+ 'base_dir'.
+
+ 'compress' must be "gzip" (the default), "bzip2", "xz", or None.
+
+ 'owner' and 'group' can be used to define an owner and a group for the
+ archive that is being built. If not provided, the current owner and group
+ will be used.
+
+ The output tar file will be named 'base_dir' + ".tar", possibly plus
+ the appropriate compression extension (".gz", ".bz2", ".xz" or ".Z").
+
+ Returns the output filename.
+ """
+ tar_compression = {
+ 'gzip': 'gz',
+ 'bzip2': 'bz2',
+ 'xz': 'xz',
+ None: '',
+ }
+ compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'xz': '.xz'}
+
+ # flags for compression program, each element of list will be an argument
+ if compress is not None and compress not in compress_ext.keys():
+ raise ValueError(
+ "bad value for 'compress': must be None, 'gzip', 'bzip2', 'xz'"
+ )
+
+ archive_name = base_name + '.tar'
+ archive_name += compress_ext.get(compress, '')
+
+ mkpath(os.path.dirname(archive_name), dry_run=dry_run)
+
+ # creating the tarball
+ import tarfile # late import so Python build itself doesn't break
+
+ log.info('Creating tar archive')
+
+ uid = _get_uid(owner)
+ gid = _get_gid(group)
+
+ def _set_uid_gid(tarinfo):
+ if gid is not None:
+ tarinfo.gid = gid
+ tarinfo.gname = group
+ if uid is not None:
+ tarinfo.uid = uid
+ tarinfo.uname = owner
+ return tarinfo
+
+ if not dry_run:
+ tar = tarfile.open(archive_name, f'w|{tar_compression[compress]}')
+ try:
+ tar.add(base_dir, filter=_set_uid_gid)
+ finally:
+ tar.close()
+
+ return archive_name
+
+
+def make_zipfile( # noqa: C901
+ base_name: str,
+ base_dir: str | os.PathLike[str],
+ verbose: bool = False,
+ dry_run: bool = False,
+) -> str:
+ """Create a zip file from all the files under 'base_dir'.
+
+ The output zip file will be named 'base_name' + ".zip". Uses either the
+ "zipfile" Python module (if available) or the InfoZIP "zip" utility
+ (if installed and found on the default search path). If neither tool is
+ available, raises DistutilsExecError. Returns the name of the output zip
+ file.
+ """
+ zip_filename = base_name + ".zip"
+ mkpath(os.path.dirname(zip_filename), dry_run=dry_run)
+
+ # If zipfile module is not available, try spawning an external
+ # 'zip' command.
+ if zipfile is None:
+ if verbose:
+ zipoptions = "-r"
+ else:
+ zipoptions = "-rq"
+
+ try:
+ spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
+ except DistutilsExecError:
+ # XXX really should distinguish between "couldn't find
+ # external 'zip' command" and "zip failed".
+ raise DistutilsExecError(
+ f"unable to create zip file '{zip_filename}': "
+ "could neither import the 'zipfile' module nor "
+ "find a standalone zip utility"
+ )
+
+ else:
+ log.info("creating '%s' and adding '%s' to it", zip_filename, base_dir)
+
+ if not dry_run:
+ try:
+ zip = zipfile.ZipFile(
+ zip_filename, "w", compression=zipfile.ZIP_DEFLATED
+ )
+ except RuntimeError:
+ zip = zipfile.ZipFile(zip_filename, "w", compression=zipfile.ZIP_STORED)
+
+ with zip:
+ if base_dir != os.curdir:
+ path = os.path.normpath(os.path.join(base_dir, ''))
+ zip.write(path, path)
+ log.info("adding '%s'", path)
+ for dirpath, dirnames, filenames in os.walk(base_dir):
+ for name in dirnames:
+ path = os.path.normpath(os.path.join(dirpath, name, ''))
+ zip.write(path, path)
+ log.info("adding '%s'", path)
+ for name in filenames:
+ path = os.path.normpath(os.path.join(dirpath, name))
+ if os.path.isfile(path):
+ zip.write(path, path)
+ log.info("adding '%s'", path)
+
+ return zip_filename
+
+
+ARCHIVE_FORMATS = {
+ 'gztar': (make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
+ 'bztar': (make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"),
+ 'xztar': (make_tarball, [('compress', 'xz')], "xz'ed tar-file"),
+ 'ztar': (make_tarball, [('compress', 'compress')], "compressed tar file"),
+ 'tar': (make_tarball, [('compress', None)], "uncompressed tar file"),
+ 'zip': (make_zipfile, [], "ZIP file"),
+}
+
+
+def check_archive_formats(formats):
+ """Returns the first format from the 'format' list that is unknown.
+
+ If all formats are known, returns None
+ """
+ for format in formats:
+ if format not in ARCHIVE_FORMATS:
+ return format
+ return None
+
+
+@overload
+def make_archive(
+ base_name: str,
+ format: str,
+ root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes] | None = None,
+ base_dir: str | None = None,
+ verbose: bool = False,
+ dry_run: bool = False,
+ owner: str | None = None,
+ group: str | None = None,
+) -> str: ...
+@overload
+def make_archive(
+ base_name: str | os.PathLike[str],
+ format: str,
+ root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes],
+ base_dir: str | None = None,
+ verbose: bool = False,
+ dry_run: bool = False,
+ owner: str | None = None,
+ group: str | None = None,
+) -> str: ...
+def make_archive(
+ base_name: str | os.PathLike[str],
+ format: str,
+ root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes] | None = None,
+ base_dir: str | None = None,
+ verbose: bool = False,
+ dry_run: bool = False,
+ owner: str | None = None,
+ group: str | None = None,
+) -> str:
+ """Create an archive file (eg. zip or tar).
+
+ 'base_name' is the name of the file to create, minus any format-specific
+ extension; 'format' is the archive format: one of "zip", "tar", "gztar",
+ "bztar", "xztar", or "ztar".
+
+ 'root_dir' is a directory that will be the root directory of the
+ archive; ie. we typically chdir into 'root_dir' before creating the
+ archive. 'base_dir' is the directory where we start archiving from;
+ ie. 'base_dir' will be the common prefix of all files and
+ directories in the archive. 'root_dir' and 'base_dir' both default
+ to the current directory. Returns the name of the archive file.
+
+ 'owner' and 'group' are used when creating a tar archive. By default,
+ uses the current owner and group.
+ """
+ save_cwd = os.getcwd()
+ if root_dir is not None:
+ log.debug("changing into '%s'", root_dir)
+ base_name = os.path.abspath(base_name)
+ if not dry_run:
+ os.chdir(root_dir)
+
+ if base_dir is None:
+ base_dir = os.curdir
+
+ kwargs = {'dry_run': dry_run}
+
+ try:
+ format_info = ARCHIVE_FORMATS[format]
+ except KeyError:
+ raise ValueError(f"unknown archive format '{format}'")
+
+ func = format_info[0]
+ kwargs.update(format_info[1])
+
+ if format != 'zip':
+ kwargs['owner'] = owner
+ kwargs['group'] = group
+
+ try:
+ filename = func(base_name, base_dir, **kwargs)
+ finally:
+ if root_dir is not None:
+ log.debug("changing back to '%s'", save_cwd)
+ os.chdir(save_cwd)
+
+ return filename
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/ccompiler.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/ccompiler.py
new file mode 100644
index 0000000..58bc6a5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/ccompiler.py
@@ -0,0 +1,26 @@
+from .compat.numpy import ( # noqa: F401
+ _default_compilers,
+ compiler_class,
+)
+from .compilers.C import base
+from .compilers.C.base import (
+ gen_lib_options,
+ gen_preprocess_options,
+ get_default_compiler,
+ new_compiler,
+ show_compilers,
+)
+from .compilers.C.errors import CompileError, LinkError
+
+__all__ = [
+ 'CompileError',
+ 'LinkError',
+ 'gen_lib_options',
+ 'gen_preprocess_options',
+ 'get_default_compiler',
+ 'new_compiler',
+ 'show_compilers',
+]
+
+
+CCompiler = base.Compiler
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/cmd.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/cmd.py
new file mode 100644
index 0000000..241621b
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/cmd.py
@@ -0,0 +1,554 @@
+"""distutils.cmd
+
+Provides the Command class, the base class for the command classes
+in the distutils.command package.
+"""
+
+from __future__ import annotations
+
+import logging
+import os
+import re
+import sys
+from abc import abstractmethod
+from collections.abc import Callable, MutableSequence
+from typing import TYPE_CHECKING, Any, ClassVar, TypeVar, overload
+
+from . import _modified, archive_util, dir_util, file_util, util
+from ._log import log
+from .errors import DistutilsOptionError
+
+if TYPE_CHECKING:
+ # type-only import because of mutual dependence between these classes
+ from distutils.dist import Distribution
+
+ from typing_extensions import TypeVarTuple, Unpack
+
+ _Ts = TypeVarTuple("_Ts")
+
+_StrPathT = TypeVar("_StrPathT", bound="str | os.PathLike[str]")
+_BytesPathT = TypeVar("_BytesPathT", bound="bytes | os.PathLike[bytes]")
+_CommandT = TypeVar("_CommandT", bound="Command")
+
+
+class Command:
+ """Abstract base class for defining command classes, the "worker bees"
+ of the Distutils. A useful analogy for command classes is to think of
+ them as subroutines with local variables called "options". The options
+ are "declared" in 'initialize_options()' and "defined" (given their
+ final values, aka "finalized") in 'finalize_options()', both of which
+ must be defined by every command class. The distinction between the
+ two is necessary because option values might come from the outside
+ world (command line, config file, ...), and any options dependent on
+ other options must be computed *after* these outside influences have
+ been processed -- hence 'finalize_options()'. The "body" of the
+ subroutine, where it does all its work based on the values of its
+ options, is the 'run()' method, which must also be implemented by every
+ command class.
+ """
+
+ # 'sub_commands' formalizes the notion of a "family" of commands,
+ # eg. "install" as the parent with sub-commands "install_lib",
+ # "install_headers", etc. The parent of a family of commands
+ # defines 'sub_commands' as a class attribute; it's a list of
+ # (command_name : string, predicate : unbound_method | string | None)
+ # tuples, where 'predicate' is a method of the parent command that
+ # determines whether the corresponding command is applicable in the
+ # current situation. (Eg. we "install_headers" is only applicable if
+ # we have any C header files to install.) If 'predicate' is None,
+ # that command is always applicable.
+ #
+ # 'sub_commands' is usually defined at the *end* of a class, because
+ # predicates can be unbound methods, so they must already have been
+ # defined. The canonical example is the "install" command.
+ sub_commands: ClassVar[ # Any to work around variance issues
+ list[tuple[str, Callable[[Any], bool] | None]]
+ ] = []
+
+ user_options: ClassVar[
+ # Specifying both because list is invariant. Avoids mypy override assignment issues
+ list[tuple[str, str, str]] | list[tuple[str, str | None, str]]
+ ] = []
+
+ # -- Creation/initialization methods -------------------------------
+
+ def __init__(self, dist: Distribution) -> None:
+ """Create and initialize a new Command object. Most importantly,
+ invokes the 'initialize_options()' method, which is the real
+ initializer and depends on the actual command being
+ instantiated.
+ """
+ # late import because of mutual dependence between these classes
+ from distutils.dist import Distribution
+
+ if not isinstance(dist, Distribution):
+ raise TypeError("dist must be a Distribution instance")
+ if self.__class__ is Command:
+ raise RuntimeError("Command is an abstract class")
+
+ self.distribution = dist
+ self.initialize_options()
+
+ # Per-command versions of the global flags, so that the user can
+ # customize Distutils' behaviour command-by-command and let some
+ # commands fall back on the Distribution's behaviour. None means
+ # "not defined, check self.distribution's copy", while 0 or 1 mean
+ # false and true (duh). Note that this means figuring out the real
+ # value of each flag is a touch complicated -- hence "self._dry_run"
+ # will be handled by __getattr__, below.
+ # XXX This needs to be fixed.
+ self._dry_run = None
+
+ # verbose is largely ignored, but needs to be set for
+ # backwards compatibility (I think)?
+ self.verbose = dist.verbose
+
+ # Some commands define a 'self.force' option to ignore file
+ # timestamps, but methods defined *here* assume that
+ # 'self.force' exists for all commands. So define it here
+ # just to be safe.
+ self.force = None
+
+ # The 'help' flag is just used for command-line parsing, so
+ # none of that complicated bureaucracy is needed.
+ self.help = False
+
+ # 'finalized' records whether or not 'finalize_options()' has been
+ # called. 'finalize_options()' itself should not pay attention to
+ # this flag: it is the business of 'ensure_finalized()', which
+ # always calls 'finalize_options()', to respect/update it.
+ self.finalized = False
+
+ # XXX A more explicit way to customize dry_run would be better.
+ def __getattr__(self, attr):
+ if attr == 'dry_run':
+ myval = getattr(self, "_" + attr)
+ if myval is None:
+ return getattr(self.distribution, attr)
+ else:
+ return myval
+ else:
+ raise AttributeError(attr)
+
+ def ensure_finalized(self) -> None:
+ if not self.finalized:
+ self.finalize_options()
+ self.finalized = True
+
+ # Subclasses must define:
+ # initialize_options()
+ # provide default values for all options; may be customized by
+ # setup script, by options from config file(s), or by command-line
+ # options
+ # finalize_options()
+ # decide on the final values for all options; this is called
+ # after all possible intervention from the outside world
+ # (command-line, option file, etc.) has been processed
+ # run()
+ # run the command: do whatever it is we're here to do,
+ # controlled by the command's various option values
+
+ @abstractmethod
+ def initialize_options(self) -> None:
+ """Set default values for all the options that this command
+ supports. Note that these defaults may be overridden by other
+ commands, by the setup script, by config files, or by the
+ command-line. Thus, this is not the place to code dependencies
+ between options; generally, 'initialize_options()' implementations
+ are just a bunch of "self.foo = None" assignments.
+
+ This method must be implemented by all command classes.
+ """
+ raise RuntimeError(
+ f"abstract method -- subclass {self.__class__} must override"
+ )
+
+ @abstractmethod
+ def finalize_options(self) -> None:
+ """Set final values for all the options that this command supports.
+ This is always called as late as possible, ie. after any option
+ assignments from the command-line or from other commands have been
+ done. Thus, this is the place to code option dependencies: if
+ 'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as
+ long as 'foo' still has the same value it was assigned in
+ 'initialize_options()'.
+
+ This method must be implemented by all command classes.
+ """
+ raise RuntimeError(
+ f"abstract method -- subclass {self.__class__} must override"
+ )
+
+ def dump_options(self, header=None, indent=""):
+ from distutils.fancy_getopt import longopt_xlate
+
+ if header is None:
+ header = f"command options for '{self.get_command_name()}':"
+ self.announce(indent + header, level=logging.INFO)
+ indent = indent + " "
+ for option, _, _ in self.user_options:
+ option = option.translate(longopt_xlate)
+ if option[-1] == "=":
+ option = option[:-1]
+ value = getattr(self, option)
+ self.announce(indent + f"{option} = {value}", level=logging.INFO)
+
+ @abstractmethod
+ def run(self) -> None:
+ """A command's raison d'etre: carry out the action it exists to
+ perform, controlled by the options initialized in
+ 'initialize_options()', customized by other commands, the setup
+ script, the command-line, and config files, and finalized in
+ 'finalize_options()'. All terminal output and filesystem
+ interaction should be done by 'run()'.
+
+ This method must be implemented by all command classes.
+ """
+ raise RuntimeError(
+ f"abstract method -- subclass {self.__class__} must override"
+ )
+
+ def announce(self, msg: object, level: int = logging.DEBUG) -> None:
+ log.log(level, msg)
+
+ def debug_print(self, msg: object) -> None:
+ """Print 'msg' to stdout if the global DEBUG (taken from the
+ DISTUTILS_DEBUG environment variable) flag is true.
+ """
+ from distutils.debug import DEBUG
+
+ if DEBUG:
+ print(msg)
+ sys.stdout.flush()
+
+ # -- Option validation methods -------------------------------------
+ # (these are very handy in writing the 'finalize_options()' method)
+ #
+ # NB. the general philosophy here is to ensure that a particular option
+ # value meets certain type and value constraints. If not, we try to
+ # force it into conformance (eg. if we expect a list but have a string,
+ # split the string on comma and/or whitespace). If we can't force the
+ # option into conformance, raise DistutilsOptionError. Thus, command
+ # classes need do nothing more than (eg.)
+ # self.ensure_string_list('foo')
+ # and they can be guaranteed that thereafter, self.foo will be
+ # a list of strings.
+
+ 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, str):
+ raise DistutilsOptionError(f"'{option}' must be a {what} (got `{val}`)")
+ return val
+
+ def ensure_string(self, option: str, default: str | None = None) -> None:
+ """Ensure that 'option' is a string; if not defined, set it to
+ 'default'.
+ """
+ self._ensure_stringlike(option, "string", default)
+
+ def ensure_string_list(self, option: str) -> None:
+ 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, str):
+ setattr(self, option, re.split(r',\s*|\s+', val))
+ else:
+ if isinstance(val, list):
+ ok = all(isinstance(v, str) for v in val)
+ else:
+ ok = False
+ if not ok:
+ raise DistutilsOptionError(
+ f"'{option}' must be a list of strings (got {val!r})"
+ )
+
+ def _ensure_tested_string(self, option, tester, what, error_fmt, default=None):
+ val = self._ensure_stringlike(option, what, default)
+ if val is not None and not tester(val):
+ raise DistutilsOptionError(
+ ("error in '%s' option: " + error_fmt) % (option, val)
+ )
+
+ def ensure_filename(self, option: str) -> None:
+ """Ensure that 'option' is the name of an existing file."""
+ self._ensure_tested_string(
+ option, os.path.isfile, "filename", "'%s' does not exist or is not a file"
+ )
+
+ def ensure_dirname(self, option: str) -> None:
+ self._ensure_tested_string(
+ option,
+ os.path.isdir,
+ "directory name",
+ "'%s' does not exist or is not a directory",
+ )
+
+ # -- Convenience methods for commands ------------------------------
+
+ def get_command_name(self) -> str:
+ if hasattr(self, 'command_name'):
+ return self.command_name
+ else:
+ return self.__class__.__name__
+
+ def set_undefined_options(
+ self, src_cmd: str, *option_pairs: tuple[str, str]
+ ) -> None:
+ """Set the values of any "undefined" options from corresponding
+ option values in some other command object. "Undefined" here means
+ "is None", which is the convention used to indicate that an option
+ has not been changed between 'initialize_options()' and
+ 'finalize_options()'. Usually called from 'finalize_options()' for
+ options that depend on some other command rather than another
+ option of the same command. 'src_cmd' is the other command from
+ which option values will be taken (a command object will be created
+ for it if necessary); the remaining arguments are
+ '(src_option,dst_option)' tuples which mean "take the value of
+ 'src_option' in the 'src_cmd' command object, and copy it to
+ 'dst_option' in the current command object".
+ """
+ # Option_pairs: list of (src_option, dst_option) tuples
+ src_cmd_obj = self.distribution.get_command_obj(src_cmd)
+ src_cmd_obj.ensure_finalized()
+ for src_option, dst_option in option_pairs:
+ if getattr(self, dst_option) is None:
+ setattr(self, dst_option, getattr(src_cmd_obj, src_option))
+
+ # NOTE: Because distutils is private to Setuptools and not all commands are exposed here,
+ # not every possible command is enumerated in the signature.
+ def get_finalized_command(self, command: str, create: bool = True) -> Command:
+ """Wrapper around Distribution's 'get_command_obj()' method: find
+ (create if necessary and 'create' is true) the command object for
+ 'command', call its 'ensure_finalized()' method, and return the
+ finalized command object.
+ """
+ cmd_obj = self.distribution.get_command_obj(command, create)
+ cmd_obj.ensure_finalized()
+ return cmd_obj
+
+ # XXX rename to 'get_reinitialized_command()'? (should do the
+ # same in dist.py, if so)
+ @overload
+ def reinitialize_command(
+ self, command: str, reinit_subcommands: bool = False
+ ) -> Command: ...
+ @overload
+ def reinitialize_command(
+ self, command: _CommandT, reinit_subcommands: bool = False
+ ) -> _CommandT: ...
+ def reinitialize_command(
+ self, command: str | Command, reinit_subcommands=False
+ ) -> Command:
+ return self.distribution.reinitialize_command(command, reinit_subcommands)
+
+ def run_command(self, command: str) -> None:
+ """Run some other command: uses the 'run_command()' method of
+ Distribution, which creates and finalizes the command object if
+ necessary and then invokes its 'run()' method.
+ """
+ self.distribution.run_command(command)
+
+ def get_sub_commands(self) -> list[str]:
+ """Determine the sub-commands that are relevant in the current
+ distribution (ie., that need to be run). This is based on the
+ 'sub_commands' class attribute: each tuple in that list may include
+ a method that we call to determine if the subcommand needs to be
+ run for the current distribution. Return a list of command names.
+ """
+ commands = []
+ for cmd_name, method in self.sub_commands:
+ if method is None or method(self):
+ commands.append(cmd_name)
+ return commands
+
+ # -- External world manipulation -----------------------------------
+
+ def warn(self, msg: object) -> None:
+ log.warning("warning: %s: %s\n", self.get_command_name(), msg)
+
+ def execute(
+ self,
+ func: Callable[[Unpack[_Ts]], object],
+ args: tuple[Unpack[_Ts]],
+ msg: object = None,
+ level: int = 1,
+ ) -> None:
+ util.execute(func, args, msg, dry_run=self.dry_run)
+
+ def mkpath(self, name: str, mode: int = 0o777) -> None:
+ dir_util.mkpath(name, mode, dry_run=self.dry_run)
+
+ @overload
+ def copy_file(
+ self,
+ infile: str | os.PathLike[str],
+ outfile: _StrPathT,
+ preserve_mode: bool = True,
+ preserve_times: bool = True,
+ link: str | None = None,
+ level: int = 1,
+ ) -> tuple[_StrPathT | str, bool]: ...
+ @overload
+ def copy_file(
+ self,
+ infile: bytes | os.PathLike[bytes],
+ outfile: _BytesPathT,
+ preserve_mode: bool = True,
+ preserve_times: bool = True,
+ link: str | None = None,
+ level: int = 1,
+ ) -> tuple[_BytesPathT | bytes, bool]: ...
+ def copy_file(
+ self,
+ infile: str | os.PathLike[str] | bytes | os.PathLike[bytes],
+ outfile: str | os.PathLike[str] | bytes | os.PathLike[bytes],
+ preserve_mode: bool = True,
+ preserve_times: bool = True,
+ link: str | None = None,
+ level: int = 1,
+ ) -> tuple[str | os.PathLike[str] | bytes | os.PathLike[bytes], bool]:
+ """Copy a file respecting verbose, dry-run and force flags. (The
+ former two default to whatever is in the Distribution object, and
+ the latter defaults to false for commands that don't define it.)"""
+ return file_util.copy_file(
+ infile,
+ outfile,
+ preserve_mode,
+ preserve_times,
+ not self.force,
+ link,
+ dry_run=self.dry_run,
+ )
+
+ def copy_tree(
+ self,
+ infile: str | os.PathLike[str],
+ outfile: str,
+ preserve_mode: bool = True,
+ preserve_times: bool = True,
+ preserve_symlinks: bool = False,
+ level: int = 1,
+ ) -> list[str]:
+ """Copy an entire directory tree respecting verbose, dry-run,
+ and force flags.
+ """
+ return dir_util.copy_tree(
+ infile,
+ outfile,
+ preserve_mode,
+ preserve_times,
+ preserve_symlinks,
+ not self.force,
+ dry_run=self.dry_run,
+ )
+
+ @overload
+ def move_file(
+ self, src: str | os.PathLike[str], dst: _StrPathT, level: int = 1
+ ) -> _StrPathT | str: ...
+ @overload
+ def move_file(
+ self, src: bytes | os.PathLike[bytes], dst: _BytesPathT, level: int = 1
+ ) -> _BytesPathT | bytes: ...
+ def move_file(
+ self,
+ src: str | os.PathLike[str] | bytes | os.PathLike[bytes],
+ dst: str | os.PathLike[str] | bytes | os.PathLike[bytes],
+ level: int = 1,
+ ) -> str | os.PathLike[str] | bytes | os.PathLike[bytes]:
+ """Move a file respecting dry-run flag."""
+ return file_util.move_file(src, dst, dry_run=self.dry_run)
+
+ def spawn(
+ self, cmd: MutableSequence[str], search_path: bool = True, level: int = 1
+ ) -> None:
+ """Spawn an external command respecting dry-run flag."""
+ from distutils.spawn import spawn
+
+ spawn(cmd, search_path, dry_run=self.dry_run)
+
+ @overload
+ def make_archive(
+ self,
+ base_name: str,
+ format: str,
+ root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes] | None = None,
+ base_dir: str | None = None,
+ owner: str | None = None,
+ group: str | None = None,
+ ) -> str: ...
+ @overload
+ def make_archive(
+ self,
+ base_name: str | os.PathLike[str],
+ format: str,
+ root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes],
+ base_dir: str | None = None,
+ owner: str | None = None,
+ group: str | None = None,
+ ) -> str: ...
+ def make_archive(
+ self,
+ base_name: str | os.PathLike[str],
+ format: str,
+ root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes] | None = None,
+ base_dir: str | None = None,
+ owner: str | None = None,
+ group: str | None = None,
+ ) -> str:
+ return archive_util.make_archive(
+ base_name,
+ format,
+ root_dir,
+ base_dir,
+ dry_run=self.dry_run,
+ owner=owner,
+ group=group,
+ )
+
+ def make_file(
+ self,
+ infiles: str | list[str] | tuple[str, ...],
+ outfile: str | os.PathLike[str] | bytes | os.PathLike[bytes],
+ func: Callable[[Unpack[_Ts]], object],
+ args: tuple[Unpack[_Ts]],
+ exec_msg: object = None,
+ skip_msg: object = None,
+ level: int = 1,
+ ) -> None:
+ """Special case of 'execute()' for operations that process one or
+ more input files and generate one output file. Works just like
+ 'execute()', except the operation is skipped and a different
+ message printed if 'outfile' already exists and is newer than all
+ files listed in 'infiles'. If the command defined 'self.force',
+ and it is true, then the command is unconditionally run -- does no
+ timestamp checks.
+ """
+ if skip_msg is None:
+ skip_msg = f"skipping {outfile} (inputs unchanged)"
+
+ # Allow 'infiles' to be a single string
+ if isinstance(infiles, str):
+ infiles = (infiles,)
+ elif not isinstance(infiles, (list, tuple)):
+ raise TypeError("'infiles' must be a string, or a list or tuple of strings")
+
+ if exec_msg is None:
+ exec_msg = "generating {} from {}".format(outfile, ', '.join(infiles))
+
+ # If 'outfile' must be regenerated (either because it doesn't
+ # exist, is out-of-date, or the 'force' flag is true) then
+ # perform the action that presumably regenerates it
+ if self.force or _modified.newer_group(infiles, outfile):
+ self.execute(func, args, exec_msg, level)
+ # Otherwise, print the "skip" message
+ else:
+ log.debug(skip_msg)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__init__.py
new file mode 100644
index 0000000..0f8a169
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__init__.py
@@ -0,0 +1,23 @@
+"""distutils.command
+
+Package containing implementation of all the standard Distutils
+commands."""
+
+__all__ = [
+ 'build',
+ 'build_py',
+ 'build_ext',
+ 'build_clib',
+ 'build_scripts',
+ 'clean',
+ 'install',
+ 'install_lib',
+ 'install_headers',
+ 'install_scripts',
+ 'install_data',
+ 'sdist',
+ 'bdist',
+ 'bdist_dumb',
+ 'bdist_rpm',
+ 'check',
+]
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..3ff648b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/_framework_compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/_framework_compat.cpython-312.pyc
new file mode 100644
index 0000000..825f97e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/_framework_compat.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-312.pyc
new file mode 100644
index 0000000..9624efb
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-312.pyc
new file mode 100644
index 0000000..c50b783
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-312.pyc
new file mode 100644
index 0000000..c99d3f8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-312.pyc
new file mode 100644
index 0000000..6df75ca
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-312.pyc
new file mode 100644
index 0000000..46d8b63
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-312.pyc
new file mode 100644
index 0000000..8f3599a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-312.pyc
new file mode 100644
index 0000000..b3b4f63
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-312.pyc
new file mode 100644
index 0000000..2a2f117
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-312.pyc
new file mode 100644
index 0000000..544932b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-312.pyc
new file mode 100644
index 0000000..fffd0ed
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-312.pyc
new file mode 100644
index 0000000..f7f559b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-312.pyc
new file mode 100644
index 0000000..ca76465
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-312.pyc
new file mode 100644
index 0000000..52d7b16
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-312.pyc
new file mode 100644
index 0000000..77bae66
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-312.pyc
new file mode 100644
index 0000000..03462f3
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_lib.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_lib.cpython-312.pyc
new file mode 100644
index 0000000..f56df47
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_lib.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-312.pyc
new file mode 100644
index 0000000..564a77f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/sdist.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/sdist.cpython-312.pyc
new file mode 100644
index 0000000..4f57b00
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/sdist.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/_framework_compat.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/_framework_compat.py
new file mode 100644
index 0000000..00d34bc
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/_framework_compat.py
@@ -0,0 +1,54 @@
+"""
+Backward compatibility for homebrew builds on macOS.
+"""
+
+import functools
+import os
+import subprocess
+import sys
+import sysconfig
+
+
+@functools.lru_cache
+def enabled():
+ """
+ Only enabled for Python 3.9 framework homebrew builds
+ except ensurepip and venv.
+ """
+ PY39 = (3, 9) < sys.version_info < (3, 10)
+ framework = sys.platform == 'darwin' and sys._framework
+ homebrew = "Cellar" in sysconfig.get_config_var('projectbase')
+ venv = sys.prefix != sys.base_prefix
+ ensurepip = os.environ.get("ENSUREPIP_OPTIONS")
+ return PY39 and framework and homebrew and not venv and not ensurepip
+
+
+schemes = dict(
+ osx_framework_library=dict(
+ stdlib='{installed_base}/{platlibdir}/python{py_version_short}',
+ platstdlib='{platbase}/{platlibdir}/python{py_version_short}',
+ purelib='{homebrew_prefix}/lib/python{py_version_short}/site-packages',
+ platlib='{homebrew_prefix}/{platlibdir}/python{py_version_short}/site-packages',
+ include='{installed_base}/include/python{py_version_short}{abiflags}',
+ platinclude='{installed_platbase}/include/python{py_version_short}{abiflags}',
+ scripts='{homebrew_prefix}/bin',
+ data='{homebrew_prefix}',
+ )
+)
+
+
+@functools.lru_cache
+def vars():
+ if not enabled():
+ return {}
+ homebrew_prefix = subprocess.check_output(['brew', '--prefix'], text=True).strip()
+ return locals()
+
+
+def scheme(name):
+ """
+ Override the selected scheme for posix_prefix.
+ """
+ if not enabled() or not name.endswith('_prefix'):
+ return name
+ return 'osx_framework_library'
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/bdist.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/bdist.py
new file mode 100644
index 0000000..07811aa
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/bdist.py
@@ -0,0 +1,167 @@
+"""distutils.command.bdist
+
+Implements the Distutils 'bdist' command (create a built [binary]
+distribution)."""
+
+from __future__ import annotations
+
+import os
+import warnings
+from collections.abc import Callable
+from typing import TYPE_CHECKING, ClassVar
+
+from ..core import Command
+from ..errors import DistutilsOptionError, DistutilsPlatformError
+from ..util import get_platform
+
+if TYPE_CHECKING:
+ from typing_extensions import deprecated
+else:
+
+ def deprecated(message):
+ return lambda fn: fn
+
+
+def show_formats():
+ """Print list of available formats (arguments to "--format" option)."""
+ from ..fancy_getopt import FancyGetopt
+
+ formats = [
+ ("formats=" + format, None, bdist.format_commands[format][1])
+ for format in bdist.format_commands
+ ]
+ pretty_printer = FancyGetopt(formats)
+ pretty_printer.print_help("List of available distribution formats:")
+
+
+class ListCompat(dict[str, tuple[str, str]]):
+ # adapter to allow for Setuptools compatibility in format_commands
+ @deprecated("format_commands is now a dict. append is deprecated.")
+ def append(self, item: object) -> None:
+ warnings.warn(
+ "format_commands is now a dict. append is deprecated.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+
+
+class bdist(Command):
+ description = "create a built (binary) distribution"
+
+ user_options = [
+ ('bdist-base=', 'b', "temporary directory for creating built distributions"),
+ (
+ 'plat-name=',
+ 'p',
+ "platform name to embed in generated filenames "
+ f"[default: {get_platform()}]",
+ ),
+ ('formats=', None, "formats for distribution (comma-separated list)"),
+ (
+ 'dist-dir=',
+ 'd',
+ "directory to put final built distributions in [default: dist]",
+ ),
+ ('skip-build', None, "skip rebuilding everything (for testing/debugging)"),
+ (
+ 'owner=',
+ 'u',
+ "Owner name used when creating a tar file [default: current user]",
+ ),
+ (
+ 'group=',
+ 'g',
+ "Group name used when creating a tar file [default: current group]",
+ ),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['skip-build']
+
+ help_options: ClassVar[list[tuple[str, str | None, str, Callable[[], object]]]] = [
+ ('help-formats', None, "lists available distribution formats", show_formats),
+ ]
+
+ # The following commands do not take a format option from bdist
+ no_format_option: ClassVar[tuple[str, ...]] = ('bdist_rpm',)
+
+ # This won't do in reality: will need to distinguish RPM-ish Linux,
+ # Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS.
+ default_format: ClassVar[dict[str, str]] = {'posix': 'gztar', 'nt': 'zip'}
+
+ # Define commands in preferred order for the --help-formats option
+ format_commands = ListCompat({
+ 'rpm': ('bdist_rpm', "RPM distribution"),
+ 'gztar': ('bdist_dumb', "gzip'ed tar file"),
+ 'bztar': ('bdist_dumb', "bzip2'ed tar file"),
+ 'xztar': ('bdist_dumb', "xz'ed tar file"),
+ 'ztar': ('bdist_dumb', "compressed tar file"),
+ 'tar': ('bdist_dumb', "tar file"),
+ 'zip': ('bdist_dumb', "ZIP file"),
+ })
+
+ # for compatibility until consumers only reference format_commands
+ format_command = format_commands
+
+ def initialize_options(self):
+ self.bdist_base = None
+ self.plat_name = None
+ self.formats = None
+ self.dist_dir = None
+ self.skip_build = False
+ self.group = None
+ self.owner = None
+
+ def finalize_options(self) -> None:
+ # have to finalize 'plat_name' before 'bdist_base'
+ if self.plat_name is None:
+ if self.skip_build:
+ self.plat_name = get_platform()
+ else:
+ self.plat_name = self.get_finalized_command('build').plat_name
+
+ # 'bdist_base' -- parent of per-built-distribution-format
+ # temporary directories (eg. we'll probably have
+ # "build/bdist./dumb", "build/bdist./rpm", etc.)
+ if self.bdist_base is None:
+ build_base = self.get_finalized_command('build').build_base
+ self.bdist_base = os.path.join(build_base, 'bdist.' + self.plat_name)
+
+ self.ensure_string_list('formats')
+ if self.formats is None:
+ try:
+ self.formats = [self.default_format[os.name]]
+ except KeyError:
+ raise DistutilsPlatformError(
+ "don't know how to create built distributions "
+ f"on platform {os.name}"
+ )
+
+ if self.dist_dir is None:
+ self.dist_dir = "dist"
+
+ def run(self) -> None:
+ # Figure out which sub-commands we need to run.
+ commands = []
+ for format in self.formats:
+ try:
+ commands.append(self.format_commands[format][0])
+ except KeyError:
+ raise DistutilsOptionError(f"invalid format '{format}'")
+
+ # Reinitialize and run each command.
+ for i in range(len(self.formats)):
+ cmd_name = commands[i]
+ sub_cmd = self.reinitialize_command(cmd_name)
+ if cmd_name not in self.no_format_option:
+ sub_cmd.format = self.formats[i]
+
+ # passing the owner and group names for tar archiving
+ if cmd_name == 'bdist_dumb':
+ sub_cmd.owner = self.owner
+ sub_cmd.group = self.group
+
+ # If we're going to need to run this command again, tell it to
+ # keep its temporary files around so subsequent runs go faster.
+ if cmd_name in commands[i + 1 :]:
+ sub_cmd.keep_temp = True
+ self.run_command(cmd_name)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/bdist_dumb.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/bdist_dumb.py
new file mode 100644
index 0000000..ccad66f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/bdist_dumb.py
@@ -0,0 +1,141 @@
+"""distutils.command.bdist_dumb
+
+Implements the Distutils 'bdist_dumb' command (create a "dumb" built
+distribution -- i.e., just an archive to be unpacked under $prefix or
+$exec_prefix)."""
+
+import os
+from distutils._log import log
+from typing import ClassVar
+
+from ..core import Command
+from ..dir_util import ensure_relative, remove_tree
+from ..errors import DistutilsPlatformError
+from ..sysconfig import get_python_version
+from ..util import get_platform
+
+
+class bdist_dumb(Command):
+ description = "create a \"dumb\" built distribution"
+
+ user_options = [
+ ('bdist-dir=', 'd', "temporary directory for creating the distribution"),
+ (
+ 'plat-name=',
+ 'p',
+ "platform name to embed in generated filenames "
+ f"[default: {get_platform()}]",
+ ),
+ (
+ 'format=',
+ 'f',
+ "archive format to create (tar, gztar, bztar, xztar, ztar, zip)",
+ ),
+ (
+ 'keep-temp',
+ 'k',
+ "keep the pseudo-installation tree around after creating the distribution archive",
+ ),
+ ('dist-dir=', 'd', "directory to put final built distributions in"),
+ ('skip-build', None, "skip rebuilding everything (for testing/debugging)"),
+ (
+ 'relative',
+ None,
+ "build the archive using relative paths [default: false]",
+ ),
+ (
+ 'owner=',
+ 'u',
+ "Owner name used when creating a tar file [default: current user]",
+ ),
+ (
+ 'group=',
+ 'g',
+ "Group name used when creating a tar file [default: current group]",
+ ),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['keep-temp', 'skip-build', 'relative']
+
+ default_format = {'posix': 'gztar', 'nt': 'zip'}
+
+ def initialize_options(self):
+ self.bdist_dir = None
+ self.plat_name = None
+ self.format = None
+ self.keep_temp = False
+ self.dist_dir = None
+ self.skip_build = None
+ self.relative = False
+ self.owner = None
+ self.group = None
+
+ def finalize_options(self):
+ if self.bdist_dir is None:
+ bdist_base = self.get_finalized_command('bdist').bdist_base
+ self.bdist_dir = os.path.join(bdist_base, 'dumb')
+
+ if self.format is None:
+ try:
+ self.format = self.default_format[os.name]
+ except KeyError:
+ raise DistutilsPlatformError(
+ "don't know how to create dumb built distributions "
+ f"on platform {os.name}"
+ )
+
+ self.set_undefined_options(
+ 'bdist',
+ ('dist_dir', 'dist_dir'),
+ ('plat_name', 'plat_name'),
+ ('skip_build', 'skip_build'),
+ )
+
+ def run(self):
+ if not self.skip_build:
+ self.run_command('build')
+
+ install = self.reinitialize_command('install', reinit_subcommands=True)
+ install.root = self.bdist_dir
+ install.skip_build = self.skip_build
+ install.warn_dir = False
+
+ log.info("installing to %s", self.bdist_dir)
+ self.run_command('install')
+
+ # And make an archive relative to the root of the
+ # pseudo-installation tree.
+ archive_basename = f"{self.distribution.get_fullname()}.{self.plat_name}"
+
+ pseudoinstall_root = os.path.join(self.dist_dir, archive_basename)
+ if not self.relative:
+ archive_root = self.bdist_dir
+ else:
+ if self.distribution.has_ext_modules() and (
+ install.install_base != install.install_platbase
+ ):
+ raise DistutilsPlatformError(
+ "can't make a dumb built distribution where "
+ f"base and platbase are different ({install.install_base!r}, {install.install_platbase!r})"
+ )
+ else:
+ archive_root = os.path.join(
+ self.bdist_dir, ensure_relative(install.install_base)
+ )
+
+ # Make the archive
+ filename = self.make_archive(
+ pseudoinstall_root,
+ self.format,
+ root_dir=archive_root,
+ owner=self.owner,
+ group=self.group,
+ )
+ if self.distribution.has_ext_modules():
+ pyversion = get_python_version()
+ else:
+ pyversion = 'any'
+ self.distribution.dist_files.append(('bdist_dumb', pyversion, filename))
+
+ if not self.keep_temp:
+ remove_tree(self.bdist_dir, dry_run=self.dry_run)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/bdist_rpm.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/bdist_rpm.py
new file mode 100644
index 0000000..357b4e8
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/bdist_rpm.py
@@ -0,0 +1,598 @@
+"""distutils.command.bdist_rpm
+
+Implements the Distutils 'bdist_rpm' command (create RPM source and binary
+distributions)."""
+
+import os
+import subprocess
+import sys
+from distutils._log import log
+from typing import ClassVar
+
+from ..core import Command
+from ..debug import DEBUG
+from ..errors import (
+ DistutilsExecError,
+ DistutilsFileError,
+ DistutilsOptionError,
+ DistutilsPlatformError,
+)
+from ..file_util import write_file
+from ..sysconfig import get_python_version
+
+
+class bdist_rpm(Command):
+ description = "create an RPM distribution"
+
+ user_options = [
+ ('bdist-base=', None, "base directory for creating built distributions"),
+ (
+ 'rpm-base=',
+ None,
+ "base directory for creating RPMs (defaults to \"rpm\" under "
+ "--bdist-base; must be specified for RPM 2)",
+ ),
+ (
+ 'dist-dir=',
+ 'd',
+ "directory to put final RPM files in (and .spec files if --spec-only)",
+ ),
+ (
+ 'python=',
+ None,
+ "path to Python interpreter to hard-code in the .spec file "
+ "[default: \"python\"]",
+ ),
+ (
+ 'fix-python',
+ None,
+ "hard-code the exact path to the current Python interpreter in "
+ "the .spec file",
+ ),
+ ('spec-only', None, "only regenerate spec file"),
+ ('source-only', None, "only generate source RPM"),
+ ('binary-only', None, "only generate binary RPM"),
+ ('use-bzip2', None, "use bzip2 instead of gzip to create source distribution"),
+ # More meta-data: too RPM-specific to put in the setup script,
+ # but needs to go in the .spec file -- so we make these options
+ # to "bdist_rpm". The idea is that packagers would put this
+ # info in setup.cfg, although they are of course free to
+ # supply it on the command line.
+ (
+ 'distribution-name=',
+ None,
+ "name of the (Linux) distribution to which this "
+ "RPM applies (*not* the name of the module distribution!)",
+ ),
+ ('group=', None, "package classification [default: \"Development/Libraries\"]"),
+ ('release=', None, "RPM release number"),
+ ('serial=', None, "RPM serial number"),
+ (
+ 'vendor=',
+ None,
+ "RPM \"vendor\" (eg. \"Joe Blow \") "
+ "[default: maintainer or author from setup script]",
+ ),
+ (
+ 'packager=',
+ None,
+ "RPM packager (eg. \"Jane Doe \") [default: vendor]",
+ ),
+ ('doc-files=', None, "list of documentation files (space or comma-separated)"),
+ ('changelog=', None, "RPM changelog"),
+ ('icon=', None, "name of icon file"),
+ ('provides=', None, "capabilities provided by this package"),
+ ('requires=', None, "capabilities required by this package"),
+ ('conflicts=', None, "capabilities which conflict with this package"),
+ ('build-requires=', None, "capabilities required to build this package"),
+ ('obsoletes=', None, "capabilities made obsolete by this package"),
+ ('no-autoreq', None, "do not automatically calculate dependencies"),
+ # Actions to take when building RPM
+ ('keep-temp', 'k', "don't clean up RPM build directory"),
+ ('no-keep-temp', None, "clean up RPM build directory [default]"),
+ (
+ 'use-rpm-opt-flags',
+ None,
+ "compile with RPM_OPT_FLAGS when building from source RPM",
+ ),
+ ('no-rpm-opt-flags', None, "do not pass any RPM CFLAGS to compiler"),
+ ('rpm3-mode', None, "RPM 3 compatibility mode (default)"),
+ ('rpm2-mode', None, "RPM 2 compatibility mode"),
+ # Add the hooks necessary for specifying custom scripts
+ ('prep-script=', None, "Specify a script for the PREP phase of RPM building"),
+ ('build-script=', None, "Specify a script for the BUILD phase of RPM building"),
+ (
+ 'pre-install=',
+ None,
+ "Specify a script for the pre-INSTALL phase of RPM building",
+ ),
+ (
+ 'install-script=',
+ None,
+ "Specify a script for the INSTALL phase of RPM building",
+ ),
+ (
+ 'post-install=',
+ None,
+ "Specify a script for the post-INSTALL phase of RPM building",
+ ),
+ (
+ 'pre-uninstall=',
+ None,
+ "Specify a script for the pre-UNINSTALL phase of RPM building",
+ ),
+ (
+ 'post-uninstall=',
+ None,
+ "Specify a script for the post-UNINSTALL phase of RPM building",
+ ),
+ ('clean-script=', None, "Specify a script for the CLEAN phase of RPM building"),
+ (
+ 'verify-script=',
+ None,
+ "Specify a script for the VERIFY phase of the RPM build",
+ ),
+ # Allow a packager to explicitly force an architecture
+ ('force-arch=', None, "Force an architecture onto the RPM build process"),
+ ('quiet', 'q', "Run the INSTALL phase of RPM building in quiet mode"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = [
+ 'keep-temp',
+ 'use-rpm-opt-flags',
+ 'rpm3-mode',
+ 'no-autoreq',
+ 'quiet',
+ ]
+
+ negative_opt: ClassVar[dict[str, str]] = {
+ 'no-keep-temp': 'keep-temp',
+ 'no-rpm-opt-flags': 'use-rpm-opt-flags',
+ 'rpm2-mode': 'rpm3-mode',
+ }
+
+ def initialize_options(self):
+ self.bdist_base = None
+ self.rpm_base = None
+ self.dist_dir = None
+ self.python = None
+ self.fix_python = None
+ self.spec_only = None
+ self.binary_only = None
+ self.source_only = None
+ self.use_bzip2 = None
+
+ self.distribution_name = None
+ self.group = None
+ self.release = None
+ self.serial = None
+ self.vendor = None
+ self.packager = None
+ self.doc_files = None
+ self.changelog = None
+ self.icon = None
+
+ self.prep_script = None
+ self.build_script = None
+ self.install_script = None
+ self.clean_script = None
+ self.verify_script = None
+ self.pre_install = None
+ self.post_install = None
+ self.pre_uninstall = None
+ self.post_uninstall = None
+ self.prep = None
+ self.provides = None
+ self.requires = None
+ self.conflicts = None
+ self.build_requires = None
+ self.obsoletes = None
+
+ self.keep_temp = False
+ self.use_rpm_opt_flags = True
+ self.rpm3_mode = True
+ self.no_autoreq = False
+
+ self.force_arch = None
+ self.quiet = False
+
+ def finalize_options(self) -> None:
+ self.set_undefined_options('bdist', ('bdist_base', 'bdist_base'))
+ if self.rpm_base is None:
+ if not self.rpm3_mode:
+ raise DistutilsOptionError("you must specify --rpm-base in RPM 2 mode")
+ self.rpm_base = os.path.join(self.bdist_base, "rpm")
+
+ if self.python is None:
+ if self.fix_python:
+ self.python = sys.executable
+ else:
+ self.python = "python3"
+ elif self.fix_python:
+ raise DistutilsOptionError(
+ "--python and --fix-python are mutually exclusive options"
+ )
+
+ if os.name != 'posix':
+ raise DistutilsPlatformError(
+ f"don't know how to create RPM distributions on platform {os.name}"
+ )
+ if self.binary_only and self.source_only:
+ raise DistutilsOptionError(
+ "cannot supply both '--source-only' and '--binary-only'"
+ )
+
+ # don't pass CFLAGS to pure python distributions
+ if not self.distribution.has_ext_modules():
+ self.use_rpm_opt_flags = False
+
+ self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
+ self.finalize_package_data()
+
+ def finalize_package_data(self) -> None:
+ self.ensure_string('group', "Development/Libraries")
+ self.ensure_string(
+ 'vendor',
+ f"{self.distribution.get_contact()} <{self.distribution.get_contact_email()}>",
+ )
+ self.ensure_string('packager')
+ self.ensure_string_list('doc_files')
+ if isinstance(self.doc_files, list):
+ for readme in ('README', 'README.txt'):
+ if os.path.exists(readme) and readme not in self.doc_files:
+ self.doc_files.append(readme)
+
+ self.ensure_string('release', "1")
+ self.ensure_string('serial') # should it be an int?
+
+ self.ensure_string('distribution_name')
+
+ self.ensure_string('changelog')
+ # Format changelog correctly
+ self.changelog = self._format_changelog(self.changelog)
+
+ self.ensure_filename('icon')
+
+ self.ensure_filename('prep_script')
+ self.ensure_filename('build_script')
+ self.ensure_filename('install_script')
+ self.ensure_filename('clean_script')
+ self.ensure_filename('verify_script')
+ self.ensure_filename('pre_install')
+ self.ensure_filename('post_install')
+ self.ensure_filename('pre_uninstall')
+ self.ensure_filename('post_uninstall')
+
+ # XXX don't forget we punted on summaries and descriptions -- they
+ # should be handled here eventually!
+
+ # Now *this* is some meta-data that belongs in the setup script...
+ self.ensure_string_list('provides')
+ self.ensure_string_list('requires')
+ self.ensure_string_list('conflicts')
+ self.ensure_string_list('build_requires')
+ self.ensure_string_list('obsoletes')
+
+ self.ensure_string('force_arch')
+
+ def run(self) -> None: # noqa: C901
+ if DEBUG:
+ print("before _get_package_data():")
+ print("vendor =", self.vendor)
+ print("packager =", self.packager)
+ print("doc_files =", self.doc_files)
+ print("changelog =", self.changelog)
+
+ # make directories
+ if self.spec_only:
+ spec_dir = self.dist_dir
+ self.mkpath(spec_dir)
+ else:
+ rpm_dir = {}
+ for d in ('SOURCES', 'SPECS', 'BUILD', 'RPMS', 'SRPMS'):
+ rpm_dir[d] = os.path.join(self.rpm_base, d)
+ self.mkpath(rpm_dir[d])
+ spec_dir = rpm_dir['SPECS']
+
+ # Spec file goes into 'dist_dir' if '--spec-only specified',
+ # build/rpm. otherwise.
+ spec_path = os.path.join(spec_dir, f"{self.distribution.get_name()}.spec")
+ self.execute(
+ write_file, (spec_path, self._make_spec_file()), f"writing '{spec_path}'"
+ )
+
+ if self.spec_only: # stop if requested
+ return
+
+ # Make a source distribution and copy to SOURCES directory with
+ # optional icon.
+ saved_dist_files = self.distribution.dist_files[:]
+ sdist = self.reinitialize_command('sdist')
+ if self.use_bzip2:
+ sdist.formats = ['bztar']
+ else:
+ sdist.formats = ['gztar']
+ self.run_command('sdist')
+ self.distribution.dist_files = saved_dist_files
+
+ source = sdist.get_archive_files()[0]
+ source_dir = rpm_dir['SOURCES']
+ self.copy_file(source, source_dir)
+
+ if self.icon:
+ if os.path.exists(self.icon):
+ self.copy_file(self.icon, source_dir)
+ else:
+ raise DistutilsFileError(f"icon file '{self.icon}' does not exist")
+
+ # build package
+ log.info("building RPMs")
+ rpm_cmd = ['rpmbuild']
+
+ if self.source_only: # what kind of RPMs?
+ rpm_cmd.append('-bs')
+ elif self.binary_only:
+ rpm_cmd.append('-bb')
+ else:
+ rpm_cmd.append('-ba')
+ rpm_cmd.extend(['--define', f'__python {self.python}'])
+ if self.rpm3_mode:
+ rpm_cmd.extend(['--define', f'_topdir {os.path.abspath(self.rpm_base)}'])
+ if not self.keep_temp:
+ rpm_cmd.append('--clean')
+
+ if self.quiet:
+ rpm_cmd.append('--quiet')
+
+ rpm_cmd.append(spec_path)
+ # Determine the binary rpm names that should be built out of this spec
+ # file
+ # Note that some of these may not be really built (if the file
+ # list is empty)
+ nvr_string = "%{name}-%{version}-%{release}"
+ src_rpm = nvr_string + ".src.rpm"
+ non_src_rpm = "%{arch}/" + nvr_string + ".%{arch}.rpm"
+ q_cmd = rf"rpm -q --qf '{src_rpm} {non_src_rpm}\n' --specfile '{spec_path}'"
+
+ out = os.popen(q_cmd)
+ try:
+ binary_rpms = []
+ source_rpm = None
+ while True:
+ line = out.readline()
+ if not line:
+ break
+ ell = line.strip().split()
+ assert len(ell) == 2
+ binary_rpms.append(ell[1])
+ # The source rpm is named after the first entry in the spec file
+ if source_rpm is None:
+ source_rpm = ell[0]
+
+ status = out.close()
+ if status:
+ raise DistutilsExecError(f"Failed to execute: {q_cmd!r}")
+
+ finally:
+ out.close()
+
+ self.spawn(rpm_cmd)
+
+ if not self.dry_run:
+ if self.distribution.has_ext_modules():
+ pyversion = get_python_version()
+ else:
+ pyversion = 'any'
+
+ if not self.binary_only:
+ srpm = os.path.join(rpm_dir['SRPMS'], source_rpm)
+ assert os.path.exists(srpm)
+ self.move_file(srpm, self.dist_dir)
+ filename = os.path.join(self.dist_dir, source_rpm)
+ self.distribution.dist_files.append(('bdist_rpm', pyversion, filename))
+
+ if not self.source_only:
+ for rpm in binary_rpms:
+ rpm = os.path.join(rpm_dir['RPMS'], rpm)
+ if os.path.exists(rpm):
+ self.move_file(rpm, self.dist_dir)
+ filename = os.path.join(self.dist_dir, os.path.basename(rpm))
+ self.distribution.dist_files.append((
+ 'bdist_rpm',
+ pyversion,
+ filename,
+ ))
+
+ def _dist_path(self, path):
+ return os.path.join(self.dist_dir, os.path.basename(path))
+
+ def _make_spec_file(self): # noqa: C901
+ """Generate the text of an RPM spec file and return it as a
+ list of strings (one per line).
+ """
+ # definitions and headers
+ spec_file = [
+ '%define name ' + self.distribution.get_name(),
+ '%define version ' + self.distribution.get_version().replace('-', '_'),
+ '%define unmangled_version ' + self.distribution.get_version(),
+ '%define release ' + self.release.replace('-', '_'),
+ '',
+ 'Summary: ' + (self.distribution.get_description() or "UNKNOWN"),
+ ]
+
+ # Workaround for #14443 which affects some RPM based systems such as
+ # RHEL6 (and probably derivatives)
+ vendor_hook = subprocess.getoutput('rpm --eval %{__os_install_post}')
+ # Generate a potential replacement value for __os_install_post (whilst
+ # normalizing the whitespace to simplify the test for whether the
+ # invocation of brp-python-bytecompile passes in __python):
+ vendor_hook = '\n'.join([
+ f' {line.strip()} \\' for line in vendor_hook.splitlines()
+ ])
+ problem = "brp-python-bytecompile \\\n"
+ fixed = "brp-python-bytecompile %{__python} \\\n"
+ fixed_hook = vendor_hook.replace(problem, fixed)
+ if fixed_hook != vendor_hook:
+ spec_file.append('# Workaround for https://bugs.python.org/issue14443')
+ spec_file.append('%define __os_install_post ' + fixed_hook + '\n')
+
+ # put locale summaries into spec file
+ # XXX not supported for now (hard to put a dictionary
+ # in a config file -- arg!)
+ # for locale in self.summaries.keys():
+ # spec_file.append('Summary(%s): %s' % (locale,
+ # self.summaries[locale]))
+
+ spec_file.extend([
+ 'Name: %{name}',
+ 'Version: %{version}',
+ 'Release: %{release}',
+ ])
+
+ # XXX yuck! this filename is available from the "sdist" command,
+ # but only after it has run: and we create the spec file before
+ # running "sdist", in case of --spec-only.
+ if self.use_bzip2:
+ spec_file.append('Source0: %{name}-%{unmangled_version}.tar.bz2')
+ else:
+ spec_file.append('Source0: %{name}-%{unmangled_version}.tar.gz')
+
+ spec_file.extend([
+ 'License: ' + (self.distribution.get_license() or "UNKNOWN"),
+ 'Group: ' + self.group,
+ 'BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot',
+ 'Prefix: %{_prefix}',
+ ])
+
+ if not self.force_arch:
+ # noarch if no extension modules
+ if not self.distribution.has_ext_modules():
+ spec_file.append('BuildArch: noarch')
+ else:
+ spec_file.append(f'BuildArch: {self.force_arch}')
+
+ for field in (
+ 'Vendor',
+ 'Packager',
+ 'Provides',
+ 'Requires',
+ 'Conflicts',
+ 'Obsoletes',
+ ):
+ val = getattr(self, field.lower())
+ if isinstance(val, list):
+ spec_file.append('{}: {}'.format(field, ' '.join(val)))
+ elif val is not None:
+ spec_file.append(f'{field}: {val}')
+
+ if self.distribution.get_url():
+ spec_file.append('Url: ' + self.distribution.get_url())
+
+ if self.distribution_name:
+ spec_file.append('Distribution: ' + self.distribution_name)
+
+ if self.build_requires:
+ spec_file.append('BuildRequires: ' + ' '.join(self.build_requires))
+
+ if self.icon:
+ spec_file.append('Icon: ' + os.path.basename(self.icon))
+
+ if self.no_autoreq:
+ spec_file.append('AutoReq: 0')
+
+ spec_file.extend([
+ '',
+ '%description',
+ self.distribution.get_long_description() or "",
+ ])
+
+ # put locale descriptions into spec file
+ # XXX again, suppressed because config file syntax doesn't
+ # easily support this ;-(
+ # for locale in self.descriptions.keys():
+ # spec_file.extend([
+ # '',
+ # '%description -l ' + locale,
+ # self.descriptions[locale],
+ # ])
+
+ # rpm scripts
+ # figure out default build script
+ def_setup_call = f"{self.python} {os.path.basename(sys.argv[0])}"
+ def_build = f"{def_setup_call} build"
+ if self.use_rpm_opt_flags:
+ def_build = 'env CFLAGS="$RPM_OPT_FLAGS" ' + def_build
+
+ # insert contents of files
+
+ # XXX this is kind of misleading: user-supplied options are files
+ # that we open and interpolate into the spec file, but the defaults
+ # are just text that we drop in as-is. Hmmm.
+
+ install_cmd = f'{def_setup_call} install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES'
+
+ script_options = [
+ ('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"),
+ ('build', 'build_script', def_build),
+ ('install', 'install_script', install_cmd),
+ ('clean', 'clean_script', "rm -rf $RPM_BUILD_ROOT"),
+ ('verifyscript', 'verify_script', None),
+ ('pre', 'pre_install', None),
+ ('post', 'post_install', None),
+ ('preun', 'pre_uninstall', None),
+ ('postun', 'post_uninstall', None),
+ ]
+
+ for rpm_opt, attr, default in script_options:
+ # Insert contents of file referred to, if no file is referred to
+ # use 'default' as contents of script
+ val = getattr(self, attr)
+ if val or default:
+ spec_file.extend([
+ '',
+ '%' + rpm_opt,
+ ])
+ if val:
+ with open(val) as f:
+ spec_file.extend(f.read().split('\n'))
+ else:
+ spec_file.append(default)
+
+ # files section
+ spec_file.extend([
+ '',
+ '%files -f INSTALLED_FILES',
+ '%defattr(-,root,root)',
+ ])
+
+ if self.doc_files:
+ spec_file.append('%doc ' + ' '.join(self.doc_files))
+
+ if self.changelog:
+ spec_file.extend([
+ '',
+ '%changelog',
+ ])
+ spec_file.extend(self.changelog)
+
+ return spec_file
+
+ def _format_changelog(self, changelog):
+ """Format the changelog correctly and convert it to a list of strings"""
+ if not changelog:
+ return changelog
+ new_changelog = []
+ for line in changelog.strip().split('\n'):
+ line = line.strip()
+ if line[0] == '*':
+ new_changelog.extend(['', line])
+ elif line[0] == '-':
+ new_changelog.append(line)
+ else:
+ new_changelog.append(' ' + line)
+
+ # strip trailing newline inserted by first changelog entry
+ if not new_changelog[0]:
+ del new_changelog[0]
+
+ return new_changelog
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build.py
new file mode 100644
index 0000000..6a8303a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build.py
@@ -0,0 +1,156 @@
+"""distutils.command.build
+
+Implements the Distutils 'build' command."""
+
+from __future__ import annotations
+
+import os
+import sys
+import sysconfig
+from collections.abc import Callable
+from typing import ClassVar
+
+from ..ccompiler import show_compilers
+from ..core import Command
+from ..errors import DistutilsOptionError
+from ..util import get_platform
+
+
+class build(Command):
+ description = "build everything needed to install"
+
+ user_options = [
+ ('build-base=', 'b', "base directory for build library"),
+ ('build-purelib=', None, "build directory for platform-neutral distributions"),
+ ('build-platlib=', None, "build directory for platform-specific distributions"),
+ (
+ 'build-lib=',
+ None,
+ "build directory for all distribution (defaults to either build-purelib or build-platlib",
+ ),
+ ('build-scripts=', None, "build directory for scripts"),
+ ('build-temp=', 't', "temporary build directory"),
+ (
+ 'plat-name=',
+ 'p',
+ f"platform name to build for, if supported [default: {get_platform()}]",
+ ),
+ ('compiler=', 'c', "specify the compiler type"),
+ ('parallel=', 'j', "number of parallel build jobs"),
+ ('debug', 'g', "compile extensions and libraries with debugging information"),
+ ('force', 'f', "forcibly build everything (ignore file timestamps)"),
+ ('executable=', 'e', "specify final destination interpreter path (build.py)"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['debug', 'force']
+
+ help_options: ClassVar[list[tuple[str, str | None, str, Callable[[], object]]]] = [
+ ('help-compiler', None, "list available compilers", show_compilers),
+ ]
+
+ def initialize_options(self):
+ self.build_base = 'build'
+ # these are decided only after 'build_base' has its final value
+ # (unless overridden by the user or client)
+ self.build_purelib = None
+ self.build_platlib = None
+ self.build_lib = None
+ self.build_temp = None
+ self.build_scripts = None
+ self.compiler = None
+ self.plat_name = None
+ self.debug = None
+ self.force = False
+ self.executable = None
+ self.parallel = None
+
+ def finalize_options(self) -> None: # noqa: C901
+ if self.plat_name is None:
+ self.plat_name = get_platform()
+ else:
+ # plat-name only supported for windows (other platforms are
+ # supported via ./configure flags, if at all). Avoid misleading
+ # other platforms.
+ if os.name != 'nt':
+ raise DistutilsOptionError(
+ "--plat-name only supported on Windows (try "
+ "using './configure --help' on your platform)"
+ )
+
+ plat_specifier = f".{self.plat_name}-{sys.implementation.cache_tag}"
+
+ # Python 3.13+ with --disable-gil shouldn't share build directories
+ if sysconfig.get_config_var('Py_GIL_DISABLED'):
+ plat_specifier += 't'
+
+ # Make it so Python 2.x and Python 2.x with --with-pydebug don't
+ # share the same build directories. Doing so confuses the build
+ # process for C modules
+ if hasattr(sys, 'gettotalrefcount'):
+ plat_specifier += '-pydebug'
+
+ # 'build_purelib' and 'build_platlib' just default to 'lib' and
+ # 'lib.' under the base build directory. We only use one of
+ # them for a given distribution, though --
+ if self.build_purelib is None:
+ self.build_purelib = os.path.join(self.build_base, 'lib')
+ if self.build_platlib is None:
+ self.build_platlib = os.path.join(self.build_base, 'lib' + plat_specifier)
+
+ # 'build_lib' is the actual directory that we will use for this
+ # particular module distribution -- if user didn't supply it, pick
+ # one of 'build_purelib' or 'build_platlib'.
+ if self.build_lib is None:
+ if self.distribution.has_ext_modules():
+ self.build_lib = self.build_platlib
+ else:
+ self.build_lib = self.build_purelib
+
+ # 'build_temp' -- temporary directory for compiler turds,
+ # "build/temp."
+ if self.build_temp is None:
+ self.build_temp = os.path.join(self.build_base, 'temp' + plat_specifier)
+ if self.build_scripts is None:
+ self.build_scripts = os.path.join(
+ self.build_base,
+ f'scripts-{sys.version_info.major}.{sys.version_info.minor}',
+ )
+
+ if self.executable is None and sys.executable:
+ self.executable = os.path.normpath(sys.executable)
+
+ if isinstance(self.parallel, str):
+ try:
+ self.parallel = int(self.parallel)
+ except ValueError:
+ raise DistutilsOptionError("parallel should be an integer")
+
+ def run(self) -> None:
+ # Run all relevant sub-commands. This will be some subset of:
+ # - build_py - pure Python modules
+ # - build_clib - standalone C libraries
+ # - build_ext - Python extensions
+ # - build_scripts - (Python) scripts
+ for cmd_name in self.get_sub_commands():
+ self.run_command(cmd_name)
+
+ # -- Predicates for the sub-command list ---------------------------
+
+ def has_pure_modules(self):
+ return self.distribution.has_pure_modules()
+
+ def has_c_libraries(self):
+ return self.distribution.has_c_libraries()
+
+ def has_ext_modules(self):
+ return self.distribution.has_ext_modules()
+
+ def has_scripts(self):
+ return self.distribution.has_scripts()
+
+ sub_commands = [
+ ('build_py', has_pure_modules),
+ ('build_clib', has_c_libraries),
+ ('build_ext', has_ext_modules),
+ ('build_scripts', has_scripts),
+ ]
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_clib.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_clib.py
new file mode 100644
index 0000000..8b65b3d
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_clib.py
@@ -0,0 +1,201 @@
+"""distutils.command.build_clib
+
+Implements the Distutils 'build_clib' command, to build a C/C++ library
+that is included in the module distribution and needed by an extension
+module."""
+
+# XXX this module has *lots* of code ripped-off quite transparently from
+# build_ext.py -- not surprisingly really, as the work required to build
+# a static library from a collection of C source files is not really all
+# that different from what's required to build a shared object file from
+# a collection of C source files. Nevertheless, I haven't done the
+# necessary refactoring to account for the overlap in code between the
+# two modules, mainly because a number of subtle details changed in the
+# cut 'n paste. Sigh.
+from __future__ import annotations
+
+import os
+from collections.abc import Callable
+from distutils._log import log
+from typing import ClassVar
+
+from ..ccompiler import new_compiler, show_compilers
+from ..core import Command
+from ..errors import DistutilsSetupError
+from ..sysconfig import customize_compiler
+
+
+class build_clib(Command):
+ description = "build C/C++ libraries used by Python extensions"
+
+ user_options: ClassVar[list[tuple[str, str, str]]] = [
+ ('build-clib=', 'b', "directory to build C/C++ libraries to"),
+ ('build-temp=', 't', "directory to put temporary build by-products"),
+ ('debug', 'g', "compile with debugging information"),
+ ('force', 'f', "forcibly build everything (ignore file timestamps)"),
+ ('compiler=', 'c', "specify the compiler type"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['debug', 'force']
+
+ help_options: ClassVar[list[tuple[str, str | None, str, Callable[[], object]]]] = [
+ ('help-compiler', None, "list available compilers", show_compilers),
+ ]
+
+ def initialize_options(self):
+ self.build_clib = None
+ self.build_temp = None
+
+ # List of libraries to build
+ self.libraries = None
+
+ # Compilation options for all libraries
+ self.include_dirs = None
+ self.define = None
+ self.undef = None
+ self.debug = None
+ self.force = False
+ self.compiler = None
+
+ def finalize_options(self) -> None:
+ # This might be confusing: both build-clib and build-temp default
+ # to build-temp as defined by the "build" command. This is because
+ # I think that C libraries are really just temporary build
+ # by-products, at least from the point of view of building Python
+ # extensions -- but I want to keep my options open.
+ self.set_undefined_options(
+ 'build',
+ ('build_temp', 'build_clib'),
+ ('build_temp', 'build_temp'),
+ ('compiler', 'compiler'),
+ ('debug', 'debug'),
+ ('force', 'force'),
+ )
+
+ self.libraries = self.distribution.libraries
+ if self.libraries:
+ self.check_library_list(self.libraries)
+
+ if self.include_dirs is None:
+ self.include_dirs = self.distribution.include_dirs or []
+ if isinstance(self.include_dirs, str):
+ self.include_dirs = self.include_dirs.split(os.pathsep)
+
+ # XXX same as for build_ext -- what about 'self.define' and
+ # 'self.undef' ?
+
+ def run(self) -> None:
+ if not self.libraries:
+ return
+
+ self.compiler = new_compiler(
+ compiler=self.compiler, dry_run=self.dry_run, force=self.force
+ )
+ customize_compiler(self.compiler)
+
+ if self.include_dirs is not None:
+ self.compiler.set_include_dirs(self.include_dirs)
+ if self.define is not None:
+ # 'define' option is a list of (name,value) tuples
+ for name, value in self.define:
+ self.compiler.define_macro(name, value)
+ if self.undef is not None:
+ for macro in self.undef:
+ self.compiler.undefine_macro(macro)
+
+ self.build_libraries(self.libraries)
+
+ def check_library_list(self, libraries) -> None:
+ """Ensure that the list of libraries is valid.
+
+ `library` is presumably provided as a command option 'libraries'.
+ This method checks that it is a list of 2-tuples, where the tuples
+ are (library_name, build_info_dict).
+
+ Raise DistutilsSetupError if the structure is invalid anywhere;
+ just returns otherwise.
+ """
+ if not isinstance(libraries, list):
+ raise DistutilsSetupError("'libraries' option must be a list of tuples")
+
+ for lib in libraries:
+ if not isinstance(lib, tuple) and len(lib) != 2:
+ raise DistutilsSetupError("each element of 'libraries' must a 2-tuple")
+
+ name, build_info = lib
+
+ if not isinstance(name, str):
+ raise DistutilsSetupError(
+ "first element of each tuple in 'libraries' "
+ "must be a string (the library name)"
+ )
+
+ if '/' in name or (os.sep != '/' and os.sep in name):
+ raise DistutilsSetupError(
+ f"bad library name '{lib[0]}': may not contain directory separators"
+ )
+
+ if not isinstance(build_info, dict):
+ raise DistutilsSetupError(
+ "second element of each tuple in 'libraries' "
+ "must be a dictionary (build info)"
+ )
+
+ def get_library_names(self):
+ # Assume the library list is valid -- 'check_library_list()' is
+ # called from 'finalize_options()', so it should be!
+ if not self.libraries:
+ return None
+
+ lib_names = []
+ for lib_name, _build_info in self.libraries:
+ lib_names.append(lib_name)
+ return lib_names
+
+ def get_source_files(self):
+ self.check_library_list(self.libraries)
+ filenames = []
+ for lib_name, build_info in self.libraries:
+ sources = build_info.get('sources')
+ if sources is None or not isinstance(sources, (list, tuple)):
+ raise DistutilsSetupError(
+ f"in 'libraries' option (library '{lib_name}'), "
+ "'sources' must be present and must be "
+ "a list of source filenames"
+ )
+
+ filenames.extend(sources)
+ return filenames
+
+ def build_libraries(self, libraries) -> None:
+ for lib_name, build_info in libraries:
+ sources = build_info.get('sources')
+ if sources is None or not isinstance(sources, (list, tuple)):
+ raise DistutilsSetupError(
+ f"in 'libraries' option (library '{lib_name}'), "
+ "'sources' must be present and must be "
+ "a list of source filenames"
+ )
+ sources = list(sources)
+
+ log.info("building '%s' library", lib_name)
+
+ # First, compile the source code to object files in the library
+ # directory. (This should probably change to putting object
+ # files in a temporary build directory.)
+ macros = build_info.get('macros')
+ include_dirs = build_info.get('include_dirs')
+ objects = self.compiler.compile(
+ sources,
+ output_dir=self.build_temp,
+ macros=macros,
+ include_dirs=include_dirs,
+ debug=self.debug,
+ )
+
+ # Now "link" the object files together into a static library.
+ # (On Unix at least, this isn't really linking -- it just
+ # builds an archive. Whatever.)
+ self.compiler.create_static_lib(
+ objects, lib_name, output_dir=self.build_clib, debug=self.debug
+ )
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_ext.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_ext.py
new file mode 100644
index 0000000..ec45b44
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_ext.py
@@ -0,0 +1,812 @@
+"""distutils.command.build_ext
+
+Implements the Distutils 'build_ext' command, for building extension
+modules (currently limited to C extensions, should accommodate C++
+extensions ASAP)."""
+
+from __future__ import annotations
+
+import contextlib
+import os
+import re
+import sys
+from collections.abc import Callable
+from distutils._log import log
+from site import USER_BASE
+from typing import ClassVar
+
+from .._modified import newer_group
+from ..ccompiler import new_compiler, show_compilers
+from ..core import Command
+from ..errors import (
+ CCompilerError,
+ CompileError,
+ DistutilsError,
+ DistutilsOptionError,
+ DistutilsPlatformError,
+ DistutilsSetupError,
+)
+from ..extension import Extension
+from ..sysconfig import customize_compiler, get_config_h_filename, get_python_version
+from ..util import get_platform, is_freethreaded, is_mingw
+
+# An extension name is just a dot-separated list of Python NAMEs (ie.
+# the same as a fully-qualified module name).
+extension_name_re = re.compile(r'^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$')
+
+
+class build_ext(Command):
+ description = "build C/C++ extensions (compile/link to build directory)"
+
+ # XXX thoughts on how to deal with complex command-line options like
+ # these, i.e. how to make it so fancy_getopt can suck them off the
+ # command line and make it look like setup.py defined the appropriate
+ # lists of tuples of what-have-you.
+ # - each command needs a callback to process its command-line options
+ # - Command.__init__() needs access to its share of the whole
+ # command line (must ultimately come from
+ # Distribution.parse_command_line())
+ # - it then calls the current command class' option-parsing
+ # callback to deal with weird options like -D, which have to
+ # parse the option text and churn out some custom data
+ # structure
+ # - that data structure (in this case, a list of 2-tuples)
+ # will then be present in the command object by the time
+ # we get to finalize_options() (i.e. the constructor
+ # takes care of both command-line and client options
+ # in between initialize_options() and finalize_options())
+
+ sep_by = f" (separated by '{os.pathsep}')"
+ user_options = [
+ ('build-lib=', 'b', "directory for compiled extension modules"),
+ ('build-temp=', 't', "directory for temporary files (build by-products)"),
+ (
+ 'plat-name=',
+ 'p',
+ "platform name to cross-compile for, if supported "
+ f"[default: {get_platform()}]",
+ ),
+ (
+ 'inplace',
+ 'i',
+ "ignore build-lib and put compiled extensions into the source "
+ "directory alongside your pure Python modules",
+ ),
+ (
+ 'include-dirs=',
+ 'I',
+ "list of directories to search for header files" + sep_by,
+ ),
+ ('define=', 'D', "C preprocessor macros to define"),
+ ('undef=', 'U', "C preprocessor macros to undefine"),
+ ('libraries=', 'l', "external C libraries to link with"),
+ (
+ 'library-dirs=',
+ 'L',
+ "directories to search for external C libraries" + sep_by,
+ ),
+ ('rpath=', 'R', "directories to search for shared C libraries at runtime"),
+ ('link-objects=', 'O', "extra explicit link objects to include in the link"),
+ ('debug', 'g', "compile/link with debugging information"),
+ ('force', 'f', "forcibly build everything (ignore file timestamps)"),
+ ('compiler=', 'c', "specify the compiler type"),
+ ('parallel=', 'j', "number of parallel build jobs"),
+ ('swig-cpp', None, "make SWIG create C++ files (default is C)"),
+ ('swig-opts=', None, "list of SWIG command line options"),
+ ('swig=', None, "path to the SWIG executable"),
+ ('user', None, "add user include, library and rpath"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = [
+ 'inplace',
+ 'debug',
+ 'force',
+ 'swig-cpp',
+ 'user',
+ ]
+
+ help_options: ClassVar[list[tuple[str, str | None, str, Callable[[], object]]]] = [
+ ('help-compiler', None, "list available compilers", show_compilers),
+ ]
+
+ def initialize_options(self):
+ self.extensions = None
+ self.build_lib = None
+ self.plat_name = None
+ self.build_temp = None
+ self.inplace = False
+ self.package = None
+
+ self.include_dirs = None
+ self.define = None
+ self.undef = None
+ self.libraries = None
+ self.library_dirs = None
+ self.rpath = None
+ self.link_objects = None
+ self.debug = None
+ self.force = None
+ self.compiler = None
+ self.swig = None
+ self.swig_cpp = None
+ self.swig_opts = None
+ self.user = None
+ self.parallel = None
+
+ @staticmethod
+ def _python_lib_dir(sysconfig):
+ """
+ Resolve Python's library directory for building extensions
+ that rely on a shared Python library.
+
+ See python/cpython#44264 and python/cpython#48686
+ """
+ if not sysconfig.get_config_var('Py_ENABLE_SHARED'):
+ return
+
+ if sysconfig.python_build:
+ yield '.'
+ return
+
+ if sys.platform == 'zos':
+ # On z/OS, a user is not required to install Python to
+ # a predetermined path, but can use Python portably
+ installed_dir = sysconfig.get_config_var('base')
+ lib_dir = sysconfig.get_config_var('platlibdir')
+ yield os.path.join(installed_dir, lib_dir)
+ else:
+ # building third party extensions
+ yield sysconfig.get_config_var('LIBDIR')
+
+ def finalize_options(self) -> None: # noqa: C901
+ from distutils import sysconfig
+
+ self.set_undefined_options(
+ 'build',
+ ('build_lib', 'build_lib'),
+ ('build_temp', 'build_temp'),
+ ('compiler', 'compiler'),
+ ('debug', 'debug'),
+ ('force', 'force'),
+ ('parallel', 'parallel'),
+ ('plat_name', 'plat_name'),
+ )
+
+ if self.package is None:
+ self.package = self.distribution.ext_package
+
+ self.extensions = self.distribution.ext_modules
+
+ # Make sure Python's include directories (for Python.h, pyconfig.h,
+ # etc.) are in the include search path.
+ py_include = sysconfig.get_python_inc()
+ plat_py_include = sysconfig.get_python_inc(plat_specific=True)
+ if self.include_dirs is None:
+ self.include_dirs = self.distribution.include_dirs or []
+ if isinstance(self.include_dirs, str):
+ self.include_dirs = self.include_dirs.split(os.pathsep)
+
+ # If in a virtualenv, add its include directory
+ # Issue 16116
+ if sys.exec_prefix != sys.base_exec_prefix:
+ self.include_dirs.append(os.path.join(sys.exec_prefix, 'include'))
+
+ # Put the Python "system" include dir at the end, so that
+ # any local include dirs take precedence.
+ self.include_dirs.extend(py_include.split(os.path.pathsep))
+ if plat_py_include != py_include:
+ self.include_dirs.extend(plat_py_include.split(os.path.pathsep))
+
+ self.ensure_string_list('libraries')
+ self.ensure_string_list('link_objects')
+
+ # Life is easier if we're not forever checking for None, so
+ # simplify these options to empty lists if unset
+ if self.libraries is None:
+ self.libraries = []
+ if self.library_dirs is None:
+ self.library_dirs = []
+ elif isinstance(self.library_dirs, str):
+ self.library_dirs = self.library_dirs.split(os.pathsep)
+
+ if self.rpath is None:
+ self.rpath = []
+ elif isinstance(self.rpath, str):
+ self.rpath = self.rpath.split(os.pathsep)
+
+ # for extensions under windows use different directories
+ # for Release and Debug builds.
+ # also Python's library directory must be appended to library_dirs
+ if os.name == 'nt' and not is_mingw():
+ # the 'libs' directory is for binary installs - we assume that
+ # must be the *native* platform. But we don't really support
+ # cross-compiling via a binary install anyway, so we let it go.
+ self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
+ if sys.base_exec_prefix != sys.prefix: # Issue 16116
+ self.library_dirs.append(os.path.join(sys.base_exec_prefix, 'libs'))
+ if self.debug:
+ self.build_temp = os.path.join(self.build_temp, "Debug")
+ else:
+ self.build_temp = os.path.join(self.build_temp, "Release")
+
+ # Append the source distribution include and library directories,
+ # this allows distutils on windows to work in the source tree
+ self.include_dirs.append(os.path.dirname(get_config_h_filename()))
+ self.library_dirs.append(sys.base_exec_prefix)
+
+ # Use the .lib files for the correct architecture
+ if self.plat_name == 'win32':
+ suffix = 'win32'
+ else:
+ # win-amd64
+ suffix = self.plat_name[4:]
+ new_lib = os.path.join(sys.exec_prefix, 'PCbuild')
+ if suffix:
+ new_lib = os.path.join(new_lib, suffix)
+ self.library_dirs.append(new_lib)
+
+ # For extensions under Cygwin, Python's library directory must be
+ # appended to library_dirs
+ if sys.platform[:6] == 'cygwin':
+ if not sysconfig.python_build:
+ # building third party extensions
+ self.library_dirs.append(
+ os.path.join(
+ sys.prefix, "lib", "python" + get_python_version(), "config"
+ )
+ )
+ else:
+ # building python standard extensions
+ self.library_dirs.append('.')
+
+ self.library_dirs.extend(self._python_lib_dir(sysconfig))
+
+ # The argument parsing will result in self.define being a string, but
+ # it has to be a list of 2-tuples. All the preprocessor symbols
+ # specified by the 'define' option will be set to '1'. Multiple
+ # symbols can be separated with commas.
+
+ if self.define:
+ defines = self.define.split(',')
+ self.define = [(symbol, '1') for symbol in defines]
+
+ # The option for macros to undefine is also a string from the
+ # option parsing, but has to be a list. Multiple symbols can also
+ # be separated with commas here.
+ if self.undef:
+ self.undef = self.undef.split(',')
+
+ if self.swig_opts is None:
+ self.swig_opts = []
+ else:
+ self.swig_opts = self.swig_opts.split(' ')
+
+ # Finally add the user include and library directories if requested
+ if self.user:
+ user_include = os.path.join(USER_BASE, "include")
+ user_lib = os.path.join(USER_BASE, "lib")
+ if os.path.isdir(user_include):
+ self.include_dirs.append(user_include)
+ if os.path.isdir(user_lib):
+ self.library_dirs.append(user_lib)
+ self.rpath.append(user_lib)
+
+ if isinstance(self.parallel, str):
+ try:
+ self.parallel = int(self.parallel)
+ except ValueError:
+ raise DistutilsOptionError("parallel should be an integer")
+
+ def run(self) -> None: # noqa: C901
+ # 'self.extensions', as supplied by setup.py, is a list of
+ # Extension instances. See the documentation for Extension (in
+ # distutils.extension) for details.
+ #
+ # For backwards compatibility with Distutils 0.8.2 and earlier, we
+ # also allow the 'extensions' list to be a list of tuples:
+ # (ext_name, build_info)
+ # where build_info is a dictionary containing everything that
+ # Extension instances do except the name, with a few things being
+ # differently named. We convert these 2-tuples to Extension
+ # instances as needed.
+
+ if not self.extensions:
+ return
+
+ # If we were asked to build any C/C++ libraries, make sure that the
+ # directory where we put them is in the library search path for
+ # linking extensions.
+ if self.distribution.has_c_libraries():
+ build_clib = self.get_finalized_command('build_clib')
+ self.libraries.extend(build_clib.get_library_names() or [])
+ self.library_dirs.append(build_clib.build_clib)
+
+ # Setup the CCompiler object that we'll use to do all the
+ # compiling and linking
+ self.compiler = new_compiler(
+ compiler=self.compiler,
+ verbose=self.verbose,
+ dry_run=self.dry_run,
+ force=self.force,
+ )
+ customize_compiler(self.compiler)
+ # If we are cross-compiling, init the compiler now (if we are not
+ # cross-compiling, init would not hurt, but people may rely on
+ # late initialization of compiler even if they shouldn't...)
+ if os.name == 'nt' and self.plat_name != get_platform():
+ self.compiler.initialize(self.plat_name)
+
+ # The official Windows free threaded Python installer doesn't set
+ # Py_GIL_DISABLED because its pyconfig.h is shared with the
+ # default build, so define it here (pypa/setuptools#4662).
+ if os.name == 'nt' and is_freethreaded():
+ self.compiler.define_macro('Py_GIL_DISABLED', '1')
+
+ # And make sure that any compile/link-related options (which might
+ # come from the command-line or from the setup script) are set in
+ # that CCompiler object -- that way, they automatically apply to
+ # all compiling and linking done here.
+ if self.include_dirs is not None:
+ self.compiler.set_include_dirs(self.include_dirs)
+ if self.define is not None:
+ # 'define' option is a list of (name,value) tuples
+ for name, value in self.define:
+ self.compiler.define_macro(name, value)
+ if self.undef is not None:
+ for macro in self.undef:
+ self.compiler.undefine_macro(macro)
+ if self.libraries is not None:
+ self.compiler.set_libraries(self.libraries)
+ if self.library_dirs is not None:
+ self.compiler.set_library_dirs(self.library_dirs)
+ if self.rpath is not None:
+ self.compiler.set_runtime_library_dirs(self.rpath)
+ if self.link_objects is not None:
+ self.compiler.set_link_objects(self.link_objects)
+
+ # Now actually compile and link everything.
+ self.build_extensions()
+
+ def check_extensions_list(self, extensions) -> None: # noqa: C901
+ """Ensure that the list of extensions (presumably provided as a
+ command option 'extensions') is valid, i.e. it is a list of
+ Extension objects. We also support the old-style list of 2-tuples,
+ where the tuples are (ext_name, build_info), which are converted to
+ Extension instances here.
+
+ Raise DistutilsSetupError if the structure is invalid anywhere;
+ just returns otherwise.
+ """
+ if not isinstance(extensions, list):
+ raise DistutilsSetupError(
+ "'ext_modules' option must be a list of Extension instances"
+ )
+
+ for i, ext in enumerate(extensions):
+ if isinstance(ext, Extension):
+ continue # OK! (assume type-checking done
+ # by Extension constructor)
+
+ if not isinstance(ext, tuple) or len(ext) != 2:
+ raise DistutilsSetupError(
+ "each element of 'ext_modules' option must be an "
+ "Extension instance or 2-tuple"
+ )
+
+ ext_name, build_info = ext
+
+ log.warning(
+ "old-style (ext_name, build_info) tuple found in "
+ "ext_modules for extension '%s' "
+ "-- please convert to Extension instance",
+ ext_name,
+ )
+
+ if not (isinstance(ext_name, str) and extension_name_re.match(ext_name)):
+ raise DistutilsSetupError(
+ "first element of each tuple in 'ext_modules' "
+ "must be the extension name (a string)"
+ )
+
+ if not isinstance(build_info, dict):
+ raise DistutilsSetupError(
+ "second element of each tuple in 'ext_modules' "
+ "must be a dictionary (build info)"
+ )
+
+ # OK, the (ext_name, build_info) dict is type-safe: convert it
+ # to an Extension instance.
+ ext = Extension(ext_name, build_info['sources'])
+
+ # Easy stuff: one-to-one mapping from dict elements to
+ # instance attributes.
+ for key in (
+ 'include_dirs',
+ 'library_dirs',
+ 'libraries',
+ 'extra_objects',
+ 'extra_compile_args',
+ 'extra_link_args',
+ ):
+ val = build_info.get(key)
+ if val is not None:
+ setattr(ext, key, val)
+
+ # Medium-easy stuff: same syntax/semantics, different names.
+ ext.runtime_library_dirs = build_info.get('rpath')
+ if 'def_file' in build_info:
+ log.warning("'def_file' element of build info dict no longer supported")
+
+ # Non-trivial stuff: 'macros' split into 'define_macros'
+ # and 'undef_macros'.
+ macros = build_info.get('macros')
+ if macros:
+ ext.define_macros = []
+ ext.undef_macros = []
+ for macro in macros:
+ if not (isinstance(macro, tuple) and len(macro) in (1, 2)):
+ raise DistutilsSetupError(
+ "'macros' element of build info dict must be 1- or 2-tuple"
+ )
+ if len(macro) == 1:
+ ext.undef_macros.append(macro[0])
+ elif len(macro) == 2:
+ ext.define_macros.append(macro)
+
+ extensions[i] = ext
+
+ def get_source_files(self):
+ self.check_extensions_list(self.extensions)
+ filenames = []
+
+ # Wouldn't it be neat if we knew the names of header files too...
+ for ext in self.extensions:
+ filenames.extend(ext.sources)
+ return filenames
+
+ def get_outputs(self):
+ # Sanity check the 'extensions' list -- can't assume this is being
+ # done in the same run as a 'build_extensions()' call (in fact, we
+ # can probably assume that it *isn't*!).
+ self.check_extensions_list(self.extensions)
+
+ # And build the list of output (built) filenames. Note that this
+ # ignores the 'inplace' flag, and assumes everything goes in the
+ # "build" tree.
+ return [self.get_ext_fullpath(ext.name) for ext in self.extensions]
+
+ def build_extensions(self) -> None:
+ # First, sanity-check the 'extensions' list
+ self.check_extensions_list(self.extensions)
+ if self.parallel:
+ self._build_extensions_parallel()
+ else:
+ self._build_extensions_serial()
+
+ def _build_extensions_parallel(self):
+ workers = self.parallel
+ if self.parallel is True:
+ workers = os.cpu_count() # may return None
+ try:
+ from concurrent.futures import ThreadPoolExecutor
+ except ImportError:
+ workers = None
+
+ if workers is None:
+ self._build_extensions_serial()
+ return
+
+ with ThreadPoolExecutor(max_workers=workers) as executor:
+ futures = [
+ executor.submit(self.build_extension, ext) for ext in self.extensions
+ ]
+ for ext, fut in zip(self.extensions, futures):
+ with self._filter_build_errors(ext):
+ fut.result()
+
+ def _build_extensions_serial(self):
+ for ext in self.extensions:
+ with self._filter_build_errors(ext):
+ self.build_extension(ext)
+
+ @contextlib.contextmanager
+ def _filter_build_errors(self, ext):
+ try:
+ yield
+ except (CCompilerError, DistutilsError, CompileError) as e:
+ if not ext.optional:
+ raise
+ self.warn(f'building extension "{ext.name}" failed: {e}')
+
+ def build_extension(self, ext) -> None:
+ sources = ext.sources
+ if sources is None or not isinstance(sources, (list, tuple)):
+ raise DistutilsSetupError(
+ f"in 'ext_modules' option (extension '{ext.name}'), "
+ "'sources' must be present and must be "
+ "a list of source filenames"
+ )
+ # sort to make the resulting .so file build reproducible
+ sources = sorted(sources)
+
+ ext_path = self.get_ext_fullpath(ext.name)
+ depends = sources + ext.depends
+ if not (self.force or newer_group(depends, ext_path, 'newer')):
+ log.debug("skipping '%s' extension (up-to-date)", ext.name)
+ return
+ else:
+ log.info("building '%s' extension", ext.name)
+
+ # First, scan the sources for SWIG definition files (.i), run
+ # SWIG on 'em to create .c files, and modify the sources list
+ # accordingly.
+ sources = self.swig_sources(sources, ext)
+
+ # Next, compile the source code to object files.
+
+ # XXX not honouring 'define_macros' or 'undef_macros' -- the
+ # CCompiler API needs to change to accommodate this, and I
+ # want to do one thing at a time!
+
+ # Two possible sources for extra compiler arguments:
+ # - 'extra_compile_args' in Extension object
+ # - CFLAGS environment variable (not particularly
+ # elegant, but people seem to expect it and I
+ # guess it's useful)
+ # The environment variable should take precedence, and
+ # any sensible compiler will give precedence to later
+ # command line args. Hence we combine them in order:
+ extra_args = ext.extra_compile_args or []
+
+ macros = ext.define_macros[:]
+ for undef in ext.undef_macros:
+ macros.append((undef,))
+
+ objects = self.compiler.compile(
+ sources,
+ output_dir=self.build_temp,
+ macros=macros,
+ include_dirs=ext.include_dirs,
+ debug=self.debug,
+ extra_postargs=extra_args,
+ depends=ext.depends,
+ )
+
+ # XXX outdated variable, kept here in case third-part code
+ # needs it.
+ self._built_objects = objects[:]
+
+ # Now link the object files together into a "shared object" --
+ # of course, first we have to figure out all the other things
+ # that go into the mix.
+ if ext.extra_objects:
+ objects.extend(ext.extra_objects)
+ extra_args = ext.extra_link_args or []
+
+ # Detect target language, if not provided
+ language = ext.language or self.compiler.detect_language(sources)
+
+ self.compiler.link_shared_object(
+ objects,
+ ext_path,
+ libraries=self.get_libraries(ext),
+ library_dirs=ext.library_dirs,
+ runtime_library_dirs=ext.runtime_library_dirs,
+ extra_postargs=extra_args,
+ export_symbols=self.get_export_symbols(ext),
+ debug=self.debug,
+ build_temp=self.build_temp,
+ target_lang=language,
+ )
+
+ def swig_sources(self, sources, extension):
+ """Walk the list of source files in 'sources', looking for SWIG
+ interface (.i) files. Run SWIG on all that are found, and
+ return a modified 'sources' list with SWIG source files replaced
+ by the generated C (or C++) files.
+ """
+ new_sources = []
+ swig_sources = []
+ swig_targets = {}
+
+ # XXX this drops generated C/C++ files into the source tree, which
+ # is fine for developers who want to distribute the generated
+ # source -- but there should be an option to put SWIG output in
+ # the temp dir.
+
+ if self.swig_cpp:
+ log.warning("--swig-cpp is deprecated - use --swig-opts=-c++")
+
+ if (
+ self.swig_cpp
+ or ('-c++' in self.swig_opts)
+ or ('-c++' in extension.swig_opts)
+ ):
+ target_ext = '.cpp'
+ else:
+ target_ext = '.c'
+
+ for source in sources:
+ (base, ext) = os.path.splitext(source)
+ if ext == ".i": # SWIG interface file
+ new_sources.append(base + '_wrap' + target_ext)
+ swig_sources.append(source)
+ swig_targets[source] = new_sources[-1]
+ else:
+ new_sources.append(source)
+
+ if not swig_sources:
+ return new_sources
+
+ swig = self.swig or self.find_swig()
+ swig_cmd = [swig, "-python"]
+ swig_cmd.extend(self.swig_opts)
+ if self.swig_cpp:
+ swig_cmd.append("-c++")
+
+ # Do not override commandline arguments
+ if not self.swig_opts:
+ swig_cmd.extend(extension.swig_opts)
+
+ for source in swig_sources:
+ target = swig_targets[source]
+ log.info("swigging %s to %s", source, target)
+ self.spawn(swig_cmd + ["-o", target, source])
+
+ return new_sources
+
+ def find_swig(self):
+ """Return the name of the SWIG executable. On Unix, this is
+ just "swig" -- it should be in the PATH. Tries a bit harder on
+ Windows.
+ """
+ if os.name == "posix":
+ return "swig"
+ elif os.name == "nt":
+ # Look for SWIG in its standard installation directory on
+ # Windows (or so I presume!). If we find it there, great;
+ # if not, act like Unix and assume it's in the PATH.
+ for vers in ("1.3", "1.2", "1.1"):
+ fn = os.path.join(f"c:\\swig{vers}", "swig.exe")
+ if os.path.isfile(fn):
+ return fn
+ else:
+ return "swig.exe"
+ else:
+ raise DistutilsPlatformError(
+ f"I don't know how to find (much less run) SWIG on platform '{os.name}'"
+ )
+
+ # -- Name generators -----------------------------------------------
+ # (extension names, filenames, whatever)
+ def get_ext_fullpath(self, ext_name: str) -> str:
+ """Returns the path of the filename for a given extension.
+
+ The file is located in `build_lib` or directly in the package
+ (inplace option).
+ """
+ fullname = self.get_ext_fullname(ext_name)
+ modpath = fullname.split('.')
+ filename = self.get_ext_filename(modpath[-1])
+
+ if not self.inplace:
+ # no further work needed
+ # returning :
+ # build_dir/package/path/filename
+ filename = os.path.join(*modpath[:-1] + [filename])
+ return os.path.join(self.build_lib, filename)
+
+ # the inplace option requires to find the package directory
+ # using the build_py command for that
+ package = '.'.join(modpath[0:-1])
+ build_py = self.get_finalized_command('build_py')
+ package_dir = os.path.abspath(build_py.get_package_dir(package))
+
+ # returning
+ # package_dir/filename
+ return os.path.join(package_dir, filename)
+
+ def get_ext_fullname(self, ext_name: str) -> str:
+ """Returns the fullname of a given extension name.
+
+ Adds the `package.` prefix"""
+ if self.package is None:
+ return ext_name
+ else:
+ return self.package + '.' + ext_name
+
+ def get_ext_filename(self, ext_name: str) -> str:
+ r"""Convert the name of an extension (eg. "foo.bar") into the name
+ of the file from which it will be loaded (eg. "foo/bar.so", or
+ "foo\bar.pyd").
+ """
+ from ..sysconfig import get_config_var
+
+ ext_path = ext_name.split('.')
+ ext_suffix = get_config_var('EXT_SUFFIX')
+ return os.path.join(*ext_path) + ext_suffix
+
+ def get_export_symbols(self, ext: Extension) -> list[str]:
+ """Return the list of symbols that a shared extension has to
+ export. This either uses 'ext.export_symbols' or, if it's not
+ provided, "PyInit_" + module_name. Only relevant on Windows, where
+ the .pyd file (DLL) must export the module "PyInit_" function.
+ """
+ name = self._get_module_name_for_symbol(ext)
+ try:
+ # Unicode module name support as defined in PEP-489
+ # https://peps.python.org/pep-0489/#export-hook-name
+ name.encode('ascii')
+ except UnicodeEncodeError:
+ suffix = 'U_' + name.encode('punycode').replace(b'-', b'_').decode('ascii')
+ else:
+ suffix = "_" + name
+
+ initfunc_name = "PyInit" + suffix
+ if initfunc_name not in ext.export_symbols:
+ ext.export_symbols.append(initfunc_name)
+ return ext.export_symbols
+
+ def _get_module_name_for_symbol(self, ext):
+ # Package name should be used for `__init__` modules
+ # https://github.com/python/cpython/issues/80074
+ # https://github.com/pypa/setuptools/issues/4826
+ parts = ext.name.split(".")
+ if parts[-1] == "__init__" and len(parts) >= 2:
+ return parts[-2]
+ return parts[-1]
+
+ def get_libraries(self, ext: Extension) -> list[str]: # noqa: C901
+ """Return the list of libraries to link against when building a
+ shared extension. On most platforms, this is just 'ext.libraries';
+ on Windows, we add the Python library (eg. python20.dll).
+ """
+ # The python library is always needed on Windows. For MSVC, this
+ # is redundant, since the library is mentioned in a pragma in
+ # pyconfig.h that MSVC groks. The other Windows compilers all seem
+ # to need it mentioned explicitly, though, so that's what we do.
+ # Append '_d' to the python import library on debug builds.
+ if sys.platform == "win32" and not is_mingw():
+ from .._msvccompiler import MSVCCompiler
+
+ if not isinstance(self.compiler, MSVCCompiler):
+ template = "python%d%d"
+ if self.debug:
+ template = template + '_d'
+ pythonlib = template % (
+ sys.hexversion >> 24,
+ (sys.hexversion >> 16) & 0xFF,
+ )
+ # don't extend ext.libraries, it may be shared with other
+ # extensions, it is a reference to the original list
+ return ext.libraries + [pythonlib]
+ else:
+ # On Android only the main executable and LD_PRELOADs are considered
+ # to be RTLD_GLOBAL, all the dependencies of the main executable
+ # remain RTLD_LOCAL and so the shared libraries must be linked with
+ # libpython when python is built with a shared python library (issue
+ # bpo-21536).
+ # On Cygwin (and if required, other POSIX-like platforms based on
+ # Windows like MinGW) it is simply necessary that all symbols in
+ # shared libraries are resolved at link time.
+ from ..sysconfig import get_config_var
+
+ link_libpython = False
+ if get_config_var('Py_ENABLE_SHARED'):
+ # A native build on an Android device or on Cygwin
+ if hasattr(sys, 'getandroidapilevel'):
+ link_libpython = True
+ elif sys.platform == 'cygwin' or is_mingw():
+ link_libpython = True
+ elif '_PYTHON_HOST_PLATFORM' in os.environ:
+ # We are cross-compiling for one of the relevant platforms
+ if get_config_var('ANDROID_API_LEVEL') != 0:
+ link_libpython = True
+ elif get_config_var('MACHDEP') == 'cygwin':
+ link_libpython = True
+
+ if link_libpython:
+ ldversion = get_config_var('LDVERSION')
+ return ext.libraries + ['python' + ldversion]
+
+ return ext.libraries
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_py.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_py.py
new file mode 100644
index 0000000..a20b076
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_py.py
@@ -0,0 +1,407 @@
+"""distutils.command.build_py
+
+Implements the Distutils 'build_py' command."""
+
+import glob
+import importlib.util
+import os
+import sys
+from distutils._log import log
+from typing import ClassVar
+
+from ..core import Command
+from ..errors import DistutilsFileError, DistutilsOptionError
+from ..util import convert_path
+
+
+class build_py(Command):
+ description = "\"build\" pure Python modules (copy to build directory)"
+
+ user_options = [
+ ('build-lib=', 'd', "directory to \"build\" (copy) to"),
+ ('compile', 'c', "compile .py to .pyc"),
+ ('no-compile', None, "don't compile .py files [default]"),
+ (
+ 'optimize=',
+ 'O',
+ "also compile with optimization: -O1 for \"python -O\", "
+ "-O2 for \"python -OO\", and -O0 to disable [default: -O0]",
+ ),
+ ('force', 'f', "forcibly build everything (ignore file timestamps)"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['compile', 'force']
+ negative_opt: ClassVar[dict[str, str]] = {'no-compile': 'compile'}
+
+ def initialize_options(self):
+ self.build_lib = None
+ self.py_modules = None
+ self.package = None
+ self.package_data = None
+ self.package_dir = None
+ self.compile = False
+ self.optimize = 0
+ self.force = None
+
+ def finalize_options(self) -> None:
+ self.set_undefined_options(
+ 'build', ('build_lib', 'build_lib'), ('force', 'force')
+ )
+
+ # Get the distribution options that are aliases for build_py
+ # options -- list of packages and list of modules.
+ self.packages = self.distribution.packages
+ self.py_modules = self.distribution.py_modules
+ self.package_data = self.distribution.package_data
+ self.package_dir = {}
+ if self.distribution.package_dir:
+ for name, path in self.distribution.package_dir.items():
+ self.package_dir[name] = convert_path(path)
+ self.data_files = self.get_data_files()
+
+ # Ick, copied straight from install_lib.py (fancy_getopt needs a
+ # type system! Hell, *everything* needs a type system!!!)
+ if not isinstance(self.optimize, int):
+ try:
+ self.optimize = int(self.optimize)
+ assert 0 <= self.optimize <= 2
+ except (ValueError, AssertionError):
+ raise DistutilsOptionError("optimize must be 0, 1, or 2")
+
+ def run(self) -> None:
+ # XXX copy_file by default preserves atime and mtime. IMHO this is
+ # the right thing to do, but perhaps it should be an option -- in
+ # particular, a site administrator might want installed files to
+ # reflect the time of installation rather than the last
+ # modification time before the installed release.
+
+ # XXX copy_file by default preserves mode, which appears to be the
+ # wrong thing to do: if a file is read-only in the working
+ # directory, we want it to be installed read/write so that the next
+ # installation of the same module distribution can overwrite it
+ # without problems. (This might be a Unix-specific issue.) Thus
+ # we turn off 'preserve_mode' when copying to the build directory,
+ # since the build directory is supposed to be exactly what the
+ # installation will look like (ie. we preserve mode when
+ # installing).
+
+ # Two options control which modules will be installed: 'packages'
+ # and 'py_modules'. The former lets us work with whole packages, not
+ # specifying individual modules at all; the latter is for
+ # specifying modules one-at-a-time.
+
+ if self.py_modules:
+ self.build_modules()
+ if self.packages:
+ self.build_packages()
+ self.build_package_data()
+
+ self.byte_compile(self.get_outputs(include_bytecode=False))
+
+ def get_data_files(self):
+ """Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
+ data = []
+ if not self.packages:
+ return data
+ for package in self.packages:
+ # Locate package source directory
+ src_dir = self.get_package_dir(package)
+
+ # Compute package build directory
+ build_dir = os.path.join(*([self.build_lib] + package.split('.')))
+
+ # Length of path to strip from found files
+ plen = 0
+ if src_dir:
+ plen = len(src_dir) + 1
+
+ # Strip directory from globbed filenames
+ filenames = [file[plen:] for file in self.find_data_files(package, src_dir)]
+ data.append((package, src_dir, build_dir, filenames))
+ return data
+
+ def find_data_files(self, package, src_dir):
+ """Return filenames for package's data files in 'src_dir'"""
+ globs = self.package_data.get('', []) + self.package_data.get(package, [])
+ files = []
+ for pattern in globs:
+ # Each pattern has to be converted to a platform-specific path
+ filelist = glob.glob(
+ os.path.join(glob.escape(src_dir), convert_path(pattern))
+ )
+ # Files that match more than one pattern are only added once
+ files.extend([
+ fn for fn in filelist if fn not in files and os.path.isfile(fn)
+ ])
+ return files
+
+ def build_package_data(self) -> None:
+ """Copy data files into build directory"""
+ for _package, src_dir, build_dir, filenames in self.data_files:
+ for filename in filenames:
+ target = os.path.join(build_dir, filename)
+ self.mkpath(os.path.dirname(target))
+ self.copy_file(
+ os.path.join(src_dir, filename), target, preserve_mode=False
+ )
+
+ def get_package_dir(self, package):
+ """Return the directory, relative to the top of the source
+ distribution, where package 'package' should be found
+ (at least according to the 'package_dir' option, if any)."""
+ path = package.split('.')
+
+ if not self.package_dir:
+ if path:
+ return os.path.join(*path)
+ else:
+ return ''
+ else:
+ tail = []
+ while path:
+ try:
+ pdir = self.package_dir['.'.join(path)]
+ except KeyError:
+ tail.insert(0, path[-1])
+ del path[-1]
+ else:
+ tail.insert(0, pdir)
+ return os.path.join(*tail)
+ else:
+ # Oops, got all the way through 'path' without finding a
+ # match in package_dir. If package_dir defines a directory
+ # for the root (nameless) package, then fallback on it;
+ # otherwise, we might as well have not consulted
+ # package_dir at all, as we just use the directory implied
+ # by 'tail' (which should be the same as the original value
+ # of 'path' at this point).
+ pdir = self.package_dir.get('')
+ if pdir is not None:
+ tail.insert(0, pdir)
+
+ if tail:
+ return os.path.join(*tail)
+ else:
+ return ''
+
+ def check_package(self, package, package_dir):
+ # Empty dir name means current directory, which we can probably
+ # assume exists. Also, os.path.exists and isdir don't know about
+ # my "empty string means current dir" convention, so we have to
+ # circumvent them.
+ if package_dir != "":
+ if not os.path.exists(package_dir):
+ raise DistutilsFileError(
+ f"package directory '{package_dir}' does not exist"
+ )
+ if not os.path.isdir(package_dir):
+ raise DistutilsFileError(
+ f"supposed package directory '{package_dir}' exists, "
+ "but is not a directory"
+ )
+
+ # Directories without __init__.py are namespace packages (PEP 420).
+ if package:
+ init_py = os.path.join(package_dir, "__init__.py")
+ if os.path.isfile(init_py):
+ return init_py
+
+ # Either not in a package at all (__init__.py not expected), or
+ # __init__.py doesn't exist -- so don't return the filename.
+ return None
+
+ def check_module(self, module, module_file):
+ if not os.path.isfile(module_file):
+ log.warning("file %s (for module %s) not found", module_file, module)
+ return False
+ else:
+ return True
+
+ def find_package_modules(self, package, package_dir):
+ self.check_package(package, package_dir)
+ module_files = glob.glob(os.path.join(glob.escape(package_dir), "*.py"))
+ modules = []
+ setup_script = os.path.abspath(self.distribution.script_name)
+
+ for f in module_files:
+ abs_f = os.path.abspath(f)
+ if abs_f != setup_script:
+ module = os.path.splitext(os.path.basename(f))[0]
+ modules.append((package, module, f))
+ else:
+ self.debug_print(f"excluding {setup_script}")
+ return modules
+
+ def find_modules(self):
+ """Finds individually-specified Python modules, ie. those listed by
+ module name in 'self.py_modules'. Returns a list of tuples (package,
+ module_base, filename): 'package' is a tuple of the path through
+ package-space to the module; 'module_base' is the bare (no
+ packages, no dots) module name, and 'filename' is the path to the
+ ".py" file (relative to the distribution root) that implements the
+ module.
+ """
+ # Map package names to tuples of useful info about the package:
+ # (package_dir, checked)
+ # package_dir - the directory where we'll find source files for
+ # this package
+ # checked - true if we have checked that the package directory
+ # is valid (exists, contains __init__.py, ... ?)
+ packages = {}
+
+ # List of (package, module, filename) tuples to return
+ modules = []
+
+ # We treat modules-in-packages almost the same as toplevel modules,
+ # just the "package" for a toplevel is empty (either an empty
+ # string or empty list, depending on context). Differences:
+ # - don't check for __init__.py in directory for empty package
+ for module in self.py_modules:
+ path = module.split('.')
+ package = '.'.join(path[0:-1])
+ module_base = path[-1]
+
+ try:
+ (package_dir, checked) = packages[package]
+ except KeyError:
+ package_dir = self.get_package_dir(package)
+ checked = False
+
+ if not checked:
+ init_py = self.check_package(package, package_dir)
+ packages[package] = (package_dir, 1)
+ if init_py:
+ modules.append((package, "__init__", init_py))
+
+ # XXX perhaps we should also check for just .pyc files
+ # (so greedy closed-source bastards can distribute Python
+ # modules too)
+ module_file = os.path.join(package_dir, module_base + ".py")
+ if not self.check_module(module, module_file):
+ continue
+
+ modules.append((package, module_base, module_file))
+
+ return modules
+
+ def find_all_modules(self):
+ """Compute the list of all modules that will be built, whether
+ they are specified one-module-at-a-time ('self.py_modules') or
+ by whole packages ('self.packages'). Return a list of tuples
+ (package, module, module_file), just like 'find_modules()' and
+ 'find_package_modules()' do."""
+ modules = []
+ if self.py_modules:
+ modules.extend(self.find_modules())
+ if self.packages:
+ for package in self.packages:
+ package_dir = self.get_package_dir(package)
+ m = self.find_package_modules(package, package_dir)
+ modules.extend(m)
+ return modules
+
+ def get_source_files(self):
+ return [module[-1] for module in self.find_all_modules()]
+
+ def get_module_outfile(self, build_dir, package, module):
+ outfile_path = [build_dir] + list(package) + [module + ".py"]
+ return os.path.join(*outfile_path)
+
+ def get_outputs(self, include_bytecode: bool = True) -> list[str]:
+ modules = self.find_all_modules()
+ outputs = []
+ for package, module, _module_file in modules:
+ package = package.split('.')
+ filename = self.get_module_outfile(self.build_lib, package, module)
+ outputs.append(filename)
+ if include_bytecode:
+ if self.compile:
+ outputs.append(
+ importlib.util.cache_from_source(filename, optimization='')
+ )
+ if self.optimize > 0:
+ outputs.append(
+ importlib.util.cache_from_source(
+ filename, optimization=self.optimize
+ )
+ )
+
+ outputs += [
+ os.path.join(build_dir, filename)
+ for package, src_dir, build_dir, filenames in self.data_files
+ for filename in filenames
+ ]
+
+ return outputs
+
+ def build_module(self, module, module_file, package):
+ if isinstance(package, str):
+ package = package.split('.')
+ elif not isinstance(package, (list, tuple)):
+ raise TypeError(
+ "'package' must be a string (dot-separated), list, or tuple"
+ )
+
+ # Now put the module source file into the "build" area -- this is
+ # easy, we just copy it somewhere under self.build_lib (the build
+ # directory for Python source).
+ outfile = self.get_module_outfile(self.build_lib, package, module)
+ dir = os.path.dirname(outfile)
+ self.mkpath(dir)
+ return self.copy_file(module_file, outfile, preserve_mode=False)
+
+ def build_modules(self) -> None:
+ modules = self.find_modules()
+ for package, module, module_file in modules:
+ # Now "build" the module -- ie. copy the source file to
+ # self.build_lib (the build directory for Python source).
+ # (Actually, it gets copied to the directory for this package
+ # under self.build_lib.)
+ self.build_module(module, module_file, package)
+
+ def build_packages(self) -> None:
+ for package in self.packages:
+ # Get list of (package, module, module_file) tuples based on
+ # scanning the package directory. 'package' is only included
+ # in the tuple so that 'find_modules()' and
+ # 'find_package_tuples()' have a consistent interface; it's
+ # ignored here (apart from a sanity check). Also, 'module' is
+ # the *unqualified* module name (ie. no dots, no package -- we
+ # already know its package!), and 'module_file' is the path to
+ # the .py file, relative to the current directory
+ # (ie. including 'package_dir').
+ package_dir = self.get_package_dir(package)
+ modules = self.find_package_modules(package, package_dir)
+
+ # Now loop over the modules we found, "building" each one (just
+ # copy it to self.build_lib).
+ for package_, module, module_file in modules:
+ assert package == package_
+ self.build_module(module, module_file, package)
+
+ def byte_compile(self, files) -> None:
+ if sys.dont_write_bytecode:
+ self.warn('byte-compiling is disabled, skipping.')
+ return
+
+ from ..util import byte_compile
+
+ prefix = self.build_lib
+ if prefix[-1] != os.sep:
+ prefix = prefix + os.sep
+
+ # XXX this code is essentially the same as the 'byte_compile()
+ # method of the "install_lib" command, except for the determination
+ # of the 'prefix' string. Hmmm.
+ if self.compile:
+ byte_compile(
+ files, optimize=0, force=self.force, prefix=prefix, dry_run=self.dry_run
+ )
+ if self.optimize > 0:
+ byte_compile(
+ files,
+ optimize=self.optimize,
+ force=self.force,
+ prefix=prefix,
+ dry_run=self.dry_run,
+ )
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_scripts.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_scripts.py
new file mode 100644
index 0000000..127c51d
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/build_scripts.py
@@ -0,0 +1,160 @@
+"""distutils.command.build_scripts
+
+Implements the Distutils 'build_scripts' command."""
+
+import os
+import re
+import tokenize
+from distutils._log import log
+from stat import ST_MODE
+from typing import ClassVar
+
+from .._modified import newer
+from ..core import Command
+from ..util import convert_path
+
+shebang_pattern = re.compile('^#!.*python[0-9.]*([ \t].*)?$')
+"""
+Pattern matching a Python interpreter indicated in first line of a script.
+"""
+
+# for Setuptools compatibility
+first_line_re = shebang_pattern
+
+
+class build_scripts(Command):
+ description = "\"build\" scripts (copy and fixup #! line)"
+
+ user_options: ClassVar[list[tuple[str, str, str]]] = [
+ ('build-dir=', 'd', "directory to \"build\" (copy) to"),
+ ('force', 'f', "forcibly build everything (ignore file timestamps"),
+ ('executable=', 'e', "specify final destination interpreter path"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['force']
+
+ def initialize_options(self):
+ self.build_dir = None
+ self.scripts = None
+ self.force = None
+ self.executable = None
+
+ def finalize_options(self):
+ self.set_undefined_options(
+ 'build',
+ ('build_scripts', 'build_dir'),
+ ('force', 'force'),
+ ('executable', 'executable'),
+ )
+ self.scripts = self.distribution.scripts
+
+ def get_source_files(self):
+ return self.scripts
+
+ def run(self):
+ if not self.scripts:
+ return
+ self.copy_scripts()
+
+ def copy_scripts(self):
+ """
+ Copy each script listed in ``self.scripts``.
+
+ If a script is marked as a Python script (first line matches
+ 'shebang_pattern', i.e. starts with ``#!`` and contains
+ "python"), then adjust in the copy the first line to refer to
+ the current Python interpreter.
+ """
+ self.mkpath(self.build_dir)
+ outfiles = []
+ updated_files = []
+ for script in self.scripts:
+ self._copy_script(script, outfiles, updated_files)
+
+ self._change_modes(outfiles)
+
+ return outfiles, updated_files
+
+ def _copy_script(self, script, outfiles, updated_files):
+ shebang_match = None
+ script = convert_path(script)
+ outfile = os.path.join(self.build_dir, os.path.basename(script))
+ outfiles.append(outfile)
+
+ if not self.force and not newer(script, outfile):
+ log.debug("not copying %s (up-to-date)", script)
+ return
+
+ # Always open the file, but ignore failures in dry-run mode
+ # in order to attempt to copy directly.
+ try:
+ f = tokenize.open(script)
+ except OSError:
+ if not self.dry_run:
+ raise
+ f = None
+ else:
+ first_line = f.readline()
+ if not first_line:
+ self.warn(f"{script} is an empty file (skipping)")
+ return
+
+ shebang_match = shebang_pattern.match(first_line)
+
+ updated_files.append(outfile)
+ if shebang_match:
+ log.info("copying and adjusting %s -> %s", script, self.build_dir)
+ if not self.dry_run:
+ post_interp = shebang_match.group(1) or ''
+ shebang = f"#!python{post_interp}\n"
+ self._validate_shebang(shebang, f.encoding)
+ with open(outfile, "w", encoding=f.encoding) as outf:
+ outf.write(shebang)
+ outf.writelines(f.readlines())
+ if f:
+ f.close()
+ else:
+ if f:
+ f.close()
+ self.copy_file(script, outfile)
+
+ def _change_modes(self, outfiles):
+ if os.name != 'posix':
+ return
+
+ for file in outfiles:
+ self._change_mode(file)
+
+ def _change_mode(self, file):
+ if self.dry_run:
+ log.info("changing mode of %s", file)
+ return
+
+ oldmode = os.stat(file)[ST_MODE] & 0o7777
+ newmode = (oldmode | 0o555) & 0o7777
+ if newmode != oldmode:
+ log.info("changing mode of %s from %o to %o", file, oldmode, newmode)
+ os.chmod(file, newmode)
+
+ @staticmethod
+ def _validate_shebang(shebang, encoding):
+ # Python parser starts to read a script using UTF-8 until
+ # it gets a #coding:xxx cookie. The shebang has to be the
+ # first line of a file, the #coding:xxx cookie cannot be
+ # written before. So the shebang has to be encodable to
+ # UTF-8.
+ try:
+ shebang.encode('utf-8')
+ except UnicodeEncodeError:
+ raise ValueError(f"The shebang ({shebang!r}) is not encodable to utf-8")
+
+ # If the script is encoded to a custom encoding (use a
+ # #coding:xxx cookie), the shebang has to be encodable to
+ # the script encoding too.
+ try:
+ shebang.encode(encoding)
+ except UnicodeEncodeError:
+ raise ValueError(
+ f"The shebang ({shebang!r}) is not encodable "
+ f"to the script encoding ({encoding})"
+ )
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/check.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/check.py
new file mode 100644
index 0000000..58a823d
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/check.py
@@ -0,0 +1,152 @@
+"""distutils.command.check
+
+Implements the Distutils 'check' command.
+"""
+
+import contextlib
+from typing import ClassVar
+
+from ..core import Command
+from ..errors import DistutilsSetupError
+
+with contextlib.suppress(ImportError):
+ import docutils.frontend
+ import docutils.nodes
+ import docutils.parsers.rst
+ import docutils.utils
+
+ class SilentReporter(docutils.utils.Reporter):
+ def __init__(
+ self,
+ source,
+ report_level,
+ halt_level,
+ stream=None,
+ debug=False,
+ encoding='ascii',
+ error_handler='replace',
+ ):
+ self.messages = []
+ super().__init__(
+ source, report_level, halt_level, stream, debug, encoding, error_handler
+ )
+
+ def system_message(self, level, message, *children, **kwargs):
+ self.messages.append((level, message, children, kwargs))
+ return docutils.nodes.system_message(
+ message, *children, level=level, type=self.levels[level], **kwargs
+ )
+
+
+class check(Command):
+ """This command checks the meta-data of the package."""
+
+ description = "perform some checks on the package"
+ user_options: ClassVar[list[tuple[str, str, str]]] = [
+ ('metadata', 'm', 'Verify meta-data'),
+ (
+ 'restructuredtext',
+ 'r',
+ 'Checks if long string meta-data syntax are reStructuredText-compliant',
+ ),
+ ('strict', 's', 'Will exit with an error if a check fails'),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['metadata', 'restructuredtext', 'strict']
+
+ def initialize_options(self):
+ """Sets default values for options."""
+ self.restructuredtext = False
+ self.metadata = 1
+ self.strict = False
+ self._warnings = 0
+
+ def finalize_options(self):
+ pass
+
+ def warn(self, msg):
+ """Counts the number of warnings that occurs."""
+ self._warnings += 1
+ return Command.warn(self, msg)
+
+ def run(self):
+ """Runs the command."""
+ # perform the various tests
+ if self.metadata:
+ self.check_metadata()
+ if self.restructuredtext:
+ if 'docutils' in globals():
+ try:
+ self.check_restructuredtext()
+ except TypeError as exc:
+ raise DistutilsSetupError(str(exc))
+ elif self.strict:
+ raise DistutilsSetupError('The docutils package is needed.')
+
+ # let's raise an error in strict mode, if we have at least
+ # one warning
+ if self.strict and self._warnings > 0:
+ raise DistutilsSetupError('Please correct your package.')
+
+ def check_metadata(self):
+ """Ensures that all required elements of meta-data are supplied.
+
+ Required fields:
+ name, version
+
+ Warns if any are missing.
+ """
+ metadata = self.distribution.metadata
+
+ missing = [
+ attr for attr in ('name', 'version') if not getattr(metadata, attr, None)
+ ]
+
+ if missing:
+ self.warn("missing required meta-data: {}".format(', '.join(missing)))
+
+ def check_restructuredtext(self):
+ """Checks if the long string fields are reST-compliant."""
+ data = self.distribution.get_long_description()
+ for warning in self._check_rst_data(data):
+ line = warning[-1].get('line')
+ if line is None:
+ warning = warning[1]
+ else:
+ warning = f'{warning[1]} (line {line})'
+ self.warn(warning)
+
+ def _check_rst_data(self, data):
+ """Returns warnings when the provided data doesn't compile."""
+ # the include and csv_table directives need this to be a path
+ source_path = self.distribution.script_name or 'setup.py'
+ parser = docutils.parsers.rst.Parser()
+ settings = docutils.frontend.OptionParser(
+ components=(docutils.parsers.rst.Parser,)
+ ).get_default_values()
+ settings.tab_width = 4
+ settings.pep_references = None
+ settings.rfc_references = None
+ reporter = SilentReporter(
+ source_path,
+ settings.report_level,
+ settings.halt_level,
+ stream=settings.warning_stream,
+ debug=settings.debug,
+ encoding=settings.error_encoding,
+ error_handler=settings.error_encoding_error_handler,
+ )
+
+ document = docutils.nodes.document(settings, reporter, source=source_path)
+ document.note_source(source_path, -1)
+ try:
+ parser.parse(data, document)
+ except (AttributeError, TypeError) as e:
+ reporter.messages.append((
+ -1,
+ f'Could not finish the parsing: {e}.',
+ '',
+ {},
+ ))
+
+ return reporter.messages
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/clean.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/clean.py
new file mode 100644
index 0000000..23427ab
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/clean.py
@@ -0,0 +1,77 @@
+"""distutils.command.clean
+
+Implements the Distutils 'clean' command."""
+
+# contributed by Bastian Kleineidam , added 2000-03-18
+
+import os
+from distutils._log import log
+from typing import ClassVar
+
+from ..core import Command
+from ..dir_util import remove_tree
+
+
+class clean(Command):
+ description = "clean up temporary files from 'build' command"
+ user_options = [
+ ('build-base=', 'b', "base build directory [default: 'build.build-base']"),
+ (
+ 'build-lib=',
+ None,
+ "build directory for all modules [default: 'build.build-lib']",
+ ),
+ ('build-temp=', 't', "temporary build directory [default: 'build.build-temp']"),
+ (
+ 'build-scripts=',
+ None,
+ "build directory for scripts [default: 'build.build-scripts']",
+ ),
+ ('bdist-base=', None, "temporary directory for built distributions"),
+ ('all', 'a', "remove all build output, not just temporary by-products"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['all']
+
+ def initialize_options(self):
+ self.build_base = None
+ self.build_lib = None
+ self.build_temp = None
+ self.build_scripts = None
+ self.bdist_base = None
+ self.all = None
+
+ def finalize_options(self):
+ self.set_undefined_options(
+ 'build',
+ ('build_base', 'build_base'),
+ ('build_lib', 'build_lib'),
+ ('build_scripts', 'build_scripts'),
+ ('build_temp', 'build_temp'),
+ )
+ self.set_undefined_options('bdist', ('bdist_base', 'bdist_base'))
+
+ def run(self):
+ # remove the build/temp. directory (unless it's already
+ # gone)
+ if os.path.exists(self.build_temp):
+ remove_tree(self.build_temp, dry_run=self.dry_run)
+ else:
+ log.debug("'%s' does not exist -- can't clean it", self.build_temp)
+
+ if self.all:
+ # remove build directories
+ for directory in (self.build_lib, self.bdist_base, self.build_scripts):
+ if os.path.exists(directory):
+ remove_tree(directory, dry_run=self.dry_run)
+ else:
+ log.warning("'%s' does not exist -- can't clean it", directory)
+
+ # just for the heck of it, try to remove the base build directory:
+ # we might have emptied it right now, but if not we don't care
+ if not self.dry_run:
+ try:
+ os.rmdir(self.build_base)
+ log.info("removing '%s'", self.build_base)
+ except OSError:
+ pass
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/config.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/config.py
new file mode 100644
index 0000000..44df823
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/config.py
@@ -0,0 +1,360 @@
+"""distutils.command.config
+
+Implements the Distutils 'config' command, a (mostly) empty command class
+that exists mainly to be sub-classed by specific module distributions and
+applications. The idea is that while every "config" command is different,
+at least they're all named the same, and users always see "config" in the
+list of standard commands. Also, this is a good place to put common
+configure-like tasks: "try to compile this C code", or "figure out where
+this header file lives".
+"""
+
+from __future__ import annotations
+
+import os
+import pathlib
+import re
+from collections.abc import Sequence
+from distutils._log import log
+
+from ..ccompiler import CCompiler, CompileError, LinkError, new_compiler
+from ..core import Command
+from ..errors import DistutilsExecError
+from ..sysconfig import customize_compiler
+
+LANG_EXT = {"c": ".c", "c++": ".cxx"}
+
+
+class config(Command):
+ description = "prepare to build"
+
+ user_options = [
+ ('compiler=', None, "specify the compiler type"),
+ ('cc=', None, "specify the compiler executable"),
+ ('include-dirs=', 'I', "list of directories to search for header files"),
+ ('define=', 'D', "C preprocessor macros to define"),
+ ('undef=', 'U', "C preprocessor macros to undefine"),
+ ('libraries=', 'l', "external C libraries to link with"),
+ ('library-dirs=', 'L', "directories to search for external C libraries"),
+ ('noisy', None, "show every action (compile, link, run, ...) taken"),
+ (
+ 'dump-source',
+ None,
+ "dump generated source files before attempting to compile them",
+ ),
+ ]
+
+ # The three standard command methods: since the "config" command
+ # does nothing by default, these are empty.
+
+ def initialize_options(self):
+ self.compiler = None
+ self.cc = None
+ self.include_dirs = None
+ self.libraries = None
+ self.library_dirs = None
+
+ # maximal output for now
+ self.noisy = 1
+ self.dump_source = 1
+
+ # list of temporary files generated along-the-way that we have
+ # to clean at some point
+ self.temp_files = []
+
+ def finalize_options(self):
+ if self.include_dirs is None:
+ self.include_dirs = self.distribution.include_dirs or []
+ elif isinstance(self.include_dirs, str):
+ self.include_dirs = self.include_dirs.split(os.pathsep)
+
+ if self.libraries is None:
+ self.libraries = []
+ elif isinstance(self.libraries, str):
+ self.libraries = [self.libraries]
+
+ if self.library_dirs is None:
+ self.library_dirs = []
+ elif isinstance(self.library_dirs, str):
+ self.library_dirs = self.library_dirs.split(os.pathsep)
+
+ def run(self):
+ pass
+
+ # Utility methods for actual "config" commands. The interfaces are
+ # loosely based on Autoconf macros of similar names. Sub-classes
+ # may use these freely.
+
+ def _check_compiler(self):
+ """Check that 'self.compiler' really is a CCompiler object;
+ if not, make it one.
+ """
+ # We do this late, and only on-demand, because this is an expensive
+ # import.
+ if not isinstance(self.compiler, CCompiler):
+ self.compiler = new_compiler(
+ compiler=self.compiler, dry_run=self.dry_run, force=True
+ )
+ customize_compiler(self.compiler)
+ if self.include_dirs:
+ self.compiler.set_include_dirs(self.include_dirs)
+ if self.libraries:
+ self.compiler.set_libraries(self.libraries)
+ if self.library_dirs:
+ self.compiler.set_library_dirs(self.library_dirs)
+
+ def _gen_temp_sourcefile(self, body, headers, lang):
+ filename = "_configtest" + LANG_EXT[lang]
+ with open(filename, "w", encoding='utf-8') as file:
+ if headers:
+ for header in headers:
+ file.write(f"#include <{header}>\n")
+ file.write("\n")
+ file.write(body)
+ if body[-1] != "\n":
+ file.write("\n")
+ return filename
+
+ def _preprocess(self, body, headers, include_dirs, lang):
+ src = self._gen_temp_sourcefile(body, headers, lang)
+ out = "_configtest.i"
+ self.temp_files.extend([src, out])
+ self.compiler.preprocess(src, out, include_dirs=include_dirs)
+ return (src, out)
+
+ def _compile(self, body, headers, include_dirs, lang):
+ src = self._gen_temp_sourcefile(body, headers, lang)
+ if self.dump_source:
+ dump_file(src, f"compiling '{src}':")
+ (obj,) = self.compiler.object_filenames([src])
+ self.temp_files.extend([src, obj])
+ self.compiler.compile([src], include_dirs=include_dirs)
+ return (src, obj)
+
+ def _link(self, body, headers, include_dirs, libraries, library_dirs, lang):
+ (src, obj) = self._compile(body, headers, include_dirs, lang)
+ prog = os.path.splitext(os.path.basename(src))[0]
+ self.compiler.link_executable(
+ [obj],
+ prog,
+ libraries=libraries,
+ library_dirs=library_dirs,
+ target_lang=lang,
+ )
+
+ if self.compiler.exe_extension is not None:
+ prog = prog + self.compiler.exe_extension
+ self.temp_files.append(prog)
+
+ return (src, obj, prog)
+
+ def _clean(self, *filenames):
+ if not filenames:
+ filenames = self.temp_files
+ self.temp_files = []
+ log.info("removing: %s", ' '.join(filenames))
+ for filename in filenames:
+ try:
+ os.remove(filename)
+ except OSError:
+ pass
+
+ # XXX these ignore the dry-run flag: what to do, what to do? even if
+ # you want a dry-run build, you still need some sort of configuration
+ # info. My inclination is to make it up to the real config command to
+ # consult 'dry_run', and assume a default (minimal) configuration if
+ # true. The problem with trying to do it here is that you'd have to
+ # return either true or false from all the 'try' methods, neither of
+ # which is correct.
+
+ # XXX need access to the header search path and maybe default macros.
+
+ def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"):
+ """Construct a source file from 'body' (a string containing lines
+ of C/C++ code) and 'headers' (a list of header files to include)
+ and run it through the preprocessor. Return true if the
+ preprocessor succeeded, false if there were any errors.
+ ('body' probably isn't of much use, but what the heck.)
+ """
+ self._check_compiler()
+ ok = True
+ try:
+ self._preprocess(body, headers, include_dirs, lang)
+ except CompileError:
+ ok = False
+
+ self._clean()
+ return ok
+
+ def search_cpp(self, pattern, body=None, headers=None, include_dirs=None, lang="c"):
+ """Construct a source file (just like 'try_cpp()'), run it through
+ the preprocessor, and return true if any line of the output matches
+ 'pattern'. 'pattern' should either be a compiled regex object or a
+ string containing a regex. If both 'body' and 'headers' are None,
+ preprocesses an empty file -- which can be useful to determine the
+ symbols the preprocessor and compiler set by default.
+ """
+ self._check_compiler()
+ src, out = self._preprocess(body, headers, include_dirs, lang)
+
+ if isinstance(pattern, str):
+ pattern = re.compile(pattern)
+
+ with open(out, encoding='utf-8') as file:
+ match = any(pattern.search(line) for line in file)
+
+ self._clean()
+ return match
+
+ def try_compile(self, body, headers=None, include_dirs=None, lang="c"):
+ """Try to compile a source file built from 'body' and 'headers'.
+ Return true on success, false otherwise.
+ """
+ self._check_compiler()
+ try:
+ self._compile(body, headers, include_dirs, lang)
+ ok = True
+ except CompileError:
+ ok = False
+
+ log.info(ok and "success!" or "failure.")
+ self._clean()
+ return ok
+
+ def try_link(
+ self,
+ body,
+ headers=None,
+ include_dirs=None,
+ libraries=None,
+ library_dirs=None,
+ lang="c",
+ ):
+ """Try to compile and link a source file, built from 'body' and
+ 'headers', to executable form. Return true on success, false
+ otherwise.
+ """
+ self._check_compiler()
+ try:
+ self._link(body, headers, include_dirs, libraries, library_dirs, lang)
+ ok = True
+ except (CompileError, LinkError):
+ ok = False
+
+ log.info(ok and "success!" or "failure.")
+ self._clean()
+ return ok
+
+ def try_run(
+ self,
+ body,
+ headers=None,
+ include_dirs=None,
+ libraries=None,
+ library_dirs=None,
+ lang="c",
+ ):
+ """Try to compile, link to an executable, and run a program
+ built from 'body' and 'headers'. Return true on success, false
+ otherwise.
+ """
+ self._check_compiler()
+ try:
+ src, obj, exe = self._link(
+ body, headers, include_dirs, libraries, library_dirs, lang
+ )
+ self.spawn([exe])
+ ok = True
+ except (CompileError, LinkError, DistutilsExecError):
+ ok = False
+
+ log.info(ok and "success!" or "failure.")
+ self._clean()
+ return ok
+
+ # -- High-level methods --------------------------------------------
+ # (these are the ones that are actually likely to be useful
+ # when implementing a real-world config command!)
+
+ def check_func(
+ self,
+ func,
+ headers=None,
+ include_dirs=None,
+ libraries=None,
+ library_dirs=None,
+ decl=False,
+ call=False,
+ ):
+ """Determine if function 'func' is available by constructing a
+ source file that refers to 'func', and compiles and links it.
+ If everything succeeds, returns true; otherwise returns false.
+
+ The constructed source file starts out by including the header
+ files listed in 'headers'. If 'decl' is true, it then declares
+ 'func' (as "int func()"); you probably shouldn't supply 'headers'
+ and set 'decl' true in the same call, or you might get errors about
+ a conflicting declarations for 'func'. Finally, the constructed
+ 'main()' function either references 'func' or (if 'call' is true)
+ calls it. 'libraries' and 'library_dirs' are used when
+ linking.
+ """
+ self._check_compiler()
+ body = []
+ if decl:
+ body.append(f"int {func} ();")
+ body.append("int main () {")
+ if call:
+ body.append(f" {func}();")
+ else:
+ body.append(f" {func};")
+ body.append("}")
+ body = "\n".join(body) + "\n"
+
+ return self.try_link(body, headers, include_dirs, libraries, library_dirs)
+
+ def check_lib(
+ self,
+ library,
+ library_dirs=None,
+ headers=None,
+ include_dirs=None,
+ other_libraries: Sequence[str] = [],
+ ):
+ """Determine if 'library' is available to be linked against,
+ without actually checking that any particular symbols are provided
+ by it. 'headers' will be used in constructing the source file to
+ be compiled, but the only effect of this is to check if all the
+ header files listed are available. Any libraries listed in
+ 'other_libraries' will be included in the link, in case 'library'
+ has symbols that depend on other libraries.
+ """
+ self._check_compiler()
+ return self.try_link(
+ "int main (void) { }",
+ headers,
+ include_dirs,
+ [library] + list(other_libraries),
+ library_dirs,
+ )
+
+ def check_header(self, header, include_dirs=None, library_dirs=None, lang="c"):
+ """Determine if the system header file named by 'header_file'
+ exists and can be found by the preprocessor; return true if so,
+ false otherwise.
+ """
+ return self.try_cpp(
+ body="/* No body */", headers=[header], include_dirs=include_dirs
+ )
+
+
+def dump_file(filename, head=None):
+ """Dumps a file content into log.info.
+
+ If head is not None, will be dumped before the file content.
+ """
+ if head is None:
+ log.info('%s', filename)
+ else:
+ log.info(head)
+ log.info(pathlib.Path(filename).read_text(encoding='utf-8'))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install.py
new file mode 100644
index 0000000..dc17e56
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install.py
@@ -0,0 +1,805 @@
+"""distutils.command.install
+
+Implements the Distutils 'install' command."""
+
+from __future__ import annotations
+
+import collections
+import contextlib
+import itertools
+import os
+import sys
+import sysconfig
+from distutils._log import log
+from site import USER_BASE, USER_SITE
+from typing import ClassVar
+
+from ..core import Command
+from ..debug import DEBUG
+from ..errors import DistutilsOptionError, DistutilsPlatformError
+from ..file_util import write_file
+from ..sysconfig import get_config_vars
+from ..util import change_root, convert_path, get_platform, subst_vars
+from . import _framework_compat as fw
+
+HAS_USER_SITE = True
+
+WINDOWS_SCHEME = {
+ 'purelib': '{base}/Lib/site-packages',
+ 'platlib': '{base}/Lib/site-packages',
+ 'headers': '{base}/Include/{dist_name}',
+ 'scripts': '{base}/Scripts',
+ 'data': '{base}',
+}
+
+INSTALL_SCHEMES = {
+ 'posix_prefix': {
+ 'purelib': '{base}/lib/{implementation_lower}{py_version_short}/site-packages',
+ 'platlib': '{platbase}/{platlibdir}/{implementation_lower}'
+ '{py_version_short}/site-packages',
+ 'headers': '{base}/include/{implementation_lower}'
+ '{py_version_short}{abiflags}/{dist_name}',
+ 'scripts': '{base}/bin',
+ 'data': '{base}',
+ },
+ 'posix_home': {
+ 'purelib': '{base}/lib/{implementation_lower}',
+ 'platlib': '{base}/{platlibdir}/{implementation_lower}',
+ 'headers': '{base}/include/{implementation_lower}/{dist_name}',
+ 'scripts': '{base}/bin',
+ 'data': '{base}',
+ },
+ 'nt': WINDOWS_SCHEME,
+ 'pypy': {
+ 'purelib': '{base}/site-packages',
+ 'platlib': '{base}/site-packages',
+ 'headers': '{base}/include/{dist_name}',
+ 'scripts': '{base}/bin',
+ 'data': '{base}',
+ },
+ 'pypy_nt': {
+ 'purelib': '{base}/site-packages',
+ 'platlib': '{base}/site-packages',
+ 'headers': '{base}/include/{dist_name}',
+ 'scripts': '{base}/Scripts',
+ 'data': '{base}',
+ },
+}
+
+# user site schemes
+if HAS_USER_SITE:
+ INSTALL_SCHEMES['nt_user'] = {
+ 'purelib': '{usersite}',
+ 'platlib': '{usersite}',
+ 'headers': '{userbase}/{implementation}{py_version_nodot_plat}'
+ '/Include/{dist_name}',
+ 'scripts': '{userbase}/{implementation}{py_version_nodot_plat}/Scripts',
+ 'data': '{userbase}',
+ }
+
+ INSTALL_SCHEMES['posix_user'] = {
+ 'purelib': '{usersite}',
+ 'platlib': '{usersite}',
+ 'headers': '{userbase}/include/{implementation_lower}'
+ '{py_version_short}{abiflags}/{dist_name}',
+ 'scripts': '{userbase}/bin',
+ 'data': '{userbase}',
+ }
+
+
+INSTALL_SCHEMES.update(fw.schemes)
+
+
+# The keys to an installation scheme; if any new types of files are to be
+# installed, be sure to add an entry to every installation scheme above,
+# and to SCHEME_KEYS here.
+SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data')
+
+
+def _load_sysconfig_schemes():
+ with contextlib.suppress(AttributeError):
+ return {
+ scheme: sysconfig.get_paths(scheme, expand=False)
+ for scheme in sysconfig.get_scheme_names()
+ }
+
+
+def _load_schemes():
+ """
+ Extend default schemes with schemes from sysconfig.
+ """
+
+ sysconfig_schemes = _load_sysconfig_schemes() or {}
+
+ return {
+ scheme: {
+ **INSTALL_SCHEMES.get(scheme, {}),
+ **sysconfig_schemes.get(scheme, {}),
+ }
+ for scheme in set(itertools.chain(INSTALL_SCHEMES, sysconfig_schemes))
+ }
+
+
+def _get_implementation():
+ if hasattr(sys, 'pypy_version_info'):
+ return 'PyPy'
+ else:
+ return 'Python'
+
+
+def _select_scheme(ob, name):
+ scheme = _inject_headers(name, _load_scheme(_resolve_scheme(name)))
+ vars(ob).update(_remove_set(ob, _scheme_attrs(scheme)))
+
+
+def _remove_set(ob, attrs):
+ """
+ Include only attrs that are None in ob.
+ """
+ return {key: value for key, value in attrs.items() if getattr(ob, key) is None}
+
+
+def _resolve_scheme(name):
+ os_name, sep, key = name.partition('_')
+ try:
+ resolved = sysconfig.get_preferred_scheme(key)
+ except Exception:
+ resolved = fw.scheme(name)
+ return resolved
+
+
+def _load_scheme(name):
+ return _load_schemes()[name]
+
+
+def _inject_headers(name, scheme):
+ """
+ Given a scheme name and the resolved scheme,
+ if the scheme does not include headers, resolve
+ the fallback scheme for the name and use headers
+ from it. pypa/distutils#88
+ """
+ # Bypass the preferred scheme, which may not
+ # have defined headers.
+ fallback = _load_scheme(name)
+ scheme.setdefault('headers', fallback['headers'])
+ return scheme
+
+
+def _scheme_attrs(scheme):
+ """Resolve install directories by applying the install schemes."""
+ return {f'install_{key}': scheme[key] for key in SCHEME_KEYS}
+
+
+class install(Command):
+ description = "install everything from build directory"
+
+ user_options = [
+ # Select installation scheme and set base director(y|ies)
+ ('prefix=', None, "installation prefix"),
+ ('exec-prefix=', None, "(Unix only) prefix for platform-specific files"),
+ ('home=', None, "(Unix only) home directory to install under"),
+ # Or, just set the base director(y|ies)
+ (
+ 'install-base=',
+ None,
+ "base installation directory (instead of --prefix or --home)",
+ ),
+ (
+ 'install-platbase=',
+ None,
+ "base installation directory for platform-specific files (instead of --exec-prefix or --home)",
+ ),
+ ('root=', None, "install everything relative to this alternate root directory"),
+ # Or, explicitly set the installation scheme
+ (
+ 'install-purelib=',
+ None,
+ "installation directory for pure Python module distributions",
+ ),
+ (
+ 'install-platlib=',
+ None,
+ "installation directory for non-pure module distributions",
+ ),
+ (
+ 'install-lib=',
+ None,
+ "installation directory for all module distributions (overrides --install-purelib and --install-platlib)",
+ ),
+ ('install-headers=', None, "installation directory for C/C++ headers"),
+ ('install-scripts=', None, "installation directory for Python scripts"),
+ ('install-data=', None, "installation directory for data files"),
+ # Byte-compilation options -- see install_lib.py for details, as
+ # these are duplicated from there (but only install_lib does
+ # anything with them).
+ ('compile', 'c', "compile .py to .pyc [default]"),
+ ('no-compile', None, "don't compile .py files"),
+ (
+ 'optimize=',
+ 'O',
+ "also compile with optimization: -O1 for \"python -O\", "
+ "-O2 for \"python -OO\", and -O0 to disable [default: -O0]",
+ ),
+ # Miscellaneous control options
+ ('force', 'f', "force installation (overwrite any existing files)"),
+ ('skip-build', None, "skip rebuilding everything (for testing/debugging)"),
+ # Where to install documentation (eventually!)
+ # ('doc-format=', None, "format of documentation to generate"),
+ # ('install-man=', None, "directory for Unix man pages"),
+ # ('install-html=', None, "directory for HTML documentation"),
+ # ('install-info=', None, "directory for GNU info files"),
+ ('record=', None, "filename in which to record list of installed files"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['compile', 'force', 'skip-build']
+
+ if HAS_USER_SITE:
+ user_options.append((
+ 'user',
+ None,
+ f"install in user site-package '{USER_SITE}'",
+ ))
+ boolean_options.append('user')
+
+ negative_opt: ClassVar[dict[str, str]] = {'no-compile': 'compile'}
+
+ def initialize_options(self) -> None:
+ """Initializes options."""
+ # High-level options: these select both an installation base
+ # and scheme.
+ self.prefix: str | None = None
+ self.exec_prefix: str | None = None
+ self.home: str | None = None
+ self.user = False
+
+ # These select only the installation base; it's up to the user to
+ # specify the installation scheme (currently, that means supplying
+ # the --install-{platlib,purelib,scripts,data} options).
+ self.install_base = None
+ self.install_platbase = None
+ self.root: str | None = None
+
+ # These options are the actual installation directories; if not
+ # supplied by the user, they are filled in using the installation
+ # scheme implied by prefix/exec-prefix/home and the contents of
+ # that installation scheme.
+ self.install_purelib = None # for pure module distributions
+ self.install_platlib = None # non-pure (dists w/ extensions)
+ self.install_headers = None # for C/C++ headers
+ self.install_lib: str | None = None # set to either purelib or platlib
+ self.install_scripts = None
+ self.install_data = None
+ self.install_userbase = USER_BASE
+ self.install_usersite = USER_SITE
+
+ self.compile = None
+ self.optimize = None
+
+ # Deprecated
+ # These two are for putting non-packagized distributions into their
+ # own directory and creating a .pth file if it makes sense.
+ # 'extra_path' comes from the setup file; 'install_path_file' can
+ # be turned off if it makes no sense to install a .pth file. (But
+ # better to install it uselessly than to guess wrong and not
+ # install it when it's necessary and would be used!) Currently,
+ # 'install_path_file' is always true unless some outsider meddles
+ # with it.
+ self.extra_path = None
+ self.install_path_file = True
+
+ # 'force' forces installation, even if target files are not
+ # out-of-date. 'skip_build' skips running the "build" command,
+ # handy if you know it's not necessary. 'warn_dir' (which is *not*
+ # a user option, it's just there so the bdist_* commands can turn
+ # it off) determines whether we warn about installing to a
+ # directory not in sys.path.
+ self.force = False
+ self.skip_build = False
+ self.warn_dir = True
+
+ # These are only here as a conduit from the 'build' command to the
+ # 'install_*' commands that do the real work. ('build_base' isn't
+ # actually used anywhere, but it might be useful in future.) They
+ # are not user options, because if the user told the install
+ # command where the build directory is, that wouldn't affect the
+ # build command.
+ self.build_base = None
+ self.build_lib = None
+
+ # Not defined yet because we don't know anything about
+ # documentation yet.
+ # self.install_man = None
+ # self.install_html = None
+ # self.install_info = None
+
+ self.record = None
+
+ # -- Option finalizing methods -------------------------------------
+ # (This is rather more involved than for most commands,
+ # because this is where the policy for installing third-
+ # party Python modules on various platforms given a wide
+ # array of user input is decided. Yes, it's quite complex!)
+
+ def finalize_options(self) -> None: # noqa: C901
+ """Finalizes options."""
+ # This method (and its helpers, like 'finalize_unix()',
+ # 'finalize_other()', and 'select_scheme()') is where the default
+ # installation directories for modules, extension modules, and
+ # anything else we care to install from a Python module
+ # distribution. Thus, this code makes a pretty important policy
+ # statement about how third-party stuff is added to a Python
+ # installation! Note that the actual work of installation is done
+ # by the relatively simple 'install_*' commands; they just take
+ # their orders from the installation directory options determined
+ # here.
+
+ # Check for errors/inconsistencies in the options; first, stuff
+ # that's wrong on any platform.
+
+ if (self.prefix or self.exec_prefix or self.home) and (
+ self.install_base or self.install_platbase
+ ):
+ raise DistutilsOptionError(
+ "must supply either prefix/exec-prefix/home or install-base/install-platbase -- not both"
+ )
+
+ if self.home and (self.prefix or self.exec_prefix):
+ raise DistutilsOptionError(
+ "must supply either home or prefix/exec-prefix -- not both"
+ )
+
+ if self.user and (
+ self.prefix
+ or self.exec_prefix
+ or self.home
+ or self.install_base
+ or self.install_platbase
+ ):
+ raise DistutilsOptionError(
+ "can't combine user with prefix, "
+ "exec_prefix/home, or install_(plat)base"
+ )
+
+ # Next, stuff that's wrong (or dubious) only on certain platforms.
+ if os.name != "posix":
+ if self.exec_prefix:
+ self.warn("exec-prefix option ignored on this platform")
+ self.exec_prefix = None
+
+ # Now the interesting logic -- so interesting that we farm it out
+ # to other methods. The goal of these methods is to set the final
+ # values for the install_{lib,scripts,data,...} options, using as
+ # input a heady brew of prefix, exec_prefix, home, install_base,
+ # install_platbase, user-supplied versions of
+ # install_{purelib,platlib,lib,scripts,data,...}, and the
+ # install schemes. Phew!
+
+ self.dump_dirs("pre-finalize_{unix,other}")
+
+ if os.name == 'posix':
+ self.finalize_unix()
+ else:
+ self.finalize_other()
+
+ self.dump_dirs("post-finalize_{unix,other}()")
+
+ # Expand configuration variables, tilde, etc. in self.install_base
+ # and self.install_platbase -- that way, we can use $base or
+ # $platbase in the other installation directories and not worry
+ # about needing recursive variable expansion (shudder).
+
+ py_version = sys.version.split()[0]
+ (prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix')
+ try:
+ abiflags = sys.abiflags
+ except AttributeError:
+ # sys.abiflags may not be defined on all platforms.
+ abiflags = ''
+ local_vars = {
+ 'dist_name': self.distribution.get_name(),
+ 'dist_version': self.distribution.get_version(),
+ 'dist_fullname': self.distribution.get_fullname(),
+ 'py_version': py_version,
+ 'py_version_short': f'{sys.version_info.major}.{sys.version_info.minor}',
+ 'py_version_nodot': f'{sys.version_info.major}{sys.version_info.minor}',
+ 'sys_prefix': prefix,
+ 'prefix': prefix,
+ 'sys_exec_prefix': exec_prefix,
+ 'exec_prefix': exec_prefix,
+ 'abiflags': abiflags,
+ 'platlibdir': getattr(sys, 'platlibdir', 'lib'),
+ 'implementation_lower': _get_implementation().lower(),
+ 'implementation': _get_implementation(),
+ }
+
+ # vars for compatibility on older Pythons
+ compat_vars = dict(
+ # Python 3.9 and earlier
+ py_version_nodot_plat=getattr(sys, 'winver', '').replace('.', ''),
+ )
+
+ if HAS_USER_SITE:
+ local_vars['userbase'] = self.install_userbase
+ local_vars['usersite'] = self.install_usersite
+
+ self.config_vars = collections.ChainMap(
+ local_vars,
+ sysconfig.get_config_vars(),
+ compat_vars,
+ fw.vars(),
+ )
+
+ self.expand_basedirs()
+
+ self.dump_dirs("post-expand_basedirs()")
+
+ # Now define config vars for the base directories so we can expand
+ # everything else.
+ local_vars['base'] = self.install_base
+ local_vars['platbase'] = self.install_platbase
+
+ if DEBUG:
+ from pprint import pprint
+
+ print("config vars:")
+ pprint(dict(self.config_vars))
+
+ # Expand "~" and configuration variables in the installation
+ # directories.
+ self.expand_dirs()
+
+ self.dump_dirs("post-expand_dirs()")
+
+ # Create directories in the home dir:
+ if self.user:
+ self.create_home_path()
+
+ # Pick the actual directory to install all modules to: either
+ # install_purelib or install_platlib, depending on whether this
+ # module distribution is pure or not. Of course, if the user
+ # already specified install_lib, use their selection.
+ if self.install_lib is None:
+ if self.distribution.has_ext_modules(): # has extensions: non-pure
+ self.install_lib = self.install_platlib
+ else:
+ self.install_lib = self.install_purelib
+
+ # Convert directories from Unix /-separated syntax to the local
+ # convention.
+ self.convert_paths(
+ 'lib',
+ 'purelib',
+ 'platlib',
+ 'scripts',
+ 'data',
+ 'headers',
+ 'userbase',
+ 'usersite',
+ )
+
+ # Deprecated
+ # Well, we're not actually fully completely finalized yet: we still
+ # have to deal with 'extra_path', which is the hack for allowing
+ # non-packagized module distributions (hello, Numerical Python!) to
+ # get their own directories.
+ self.handle_extra_path()
+ self.install_libbase = self.install_lib # needed for .pth file
+ self.install_lib = os.path.join(self.install_lib, self.extra_dirs)
+
+ # If a new root directory was supplied, make all the installation
+ # dirs relative to it.
+ if self.root is not None:
+ self.change_roots(
+ 'libbase', 'lib', 'purelib', 'platlib', 'scripts', 'data', 'headers'
+ )
+
+ self.dump_dirs("after prepending root")
+
+ # Find out the build directories, ie. where to install from.
+ self.set_undefined_options(
+ 'build', ('build_base', 'build_base'), ('build_lib', 'build_lib')
+ )
+
+ # Punt on doc directories for now -- after all, we're punting on
+ # documentation completely!
+
+ def dump_dirs(self, msg) -> None:
+ """Dumps the list of user options."""
+ if not DEBUG:
+ return
+ from ..fancy_getopt import longopt_xlate
+
+ log.debug(msg + ":")
+ for opt in self.user_options:
+ opt_name = opt[0]
+ if opt_name[-1] == "=":
+ opt_name = opt_name[0:-1]
+ if opt_name in self.negative_opt:
+ opt_name = self.negative_opt[opt_name]
+ opt_name = opt_name.translate(longopt_xlate)
+ val = not getattr(self, opt_name)
+ else:
+ opt_name = opt_name.translate(longopt_xlate)
+ val = getattr(self, opt_name)
+ log.debug(" %s: %s", opt_name, val)
+
+ def finalize_unix(self) -> None:
+ """Finalizes options for posix platforms."""
+ if self.install_base is not None or self.install_platbase is not None:
+ incomplete_scheme = (
+ (
+ self.install_lib is None
+ and self.install_purelib is None
+ and self.install_platlib is None
+ )
+ or self.install_headers is None
+ or self.install_scripts is None
+ or self.install_data is None
+ )
+ if incomplete_scheme:
+ raise DistutilsOptionError(
+ "install-base or install-platbase supplied, but "
+ "installation scheme is incomplete"
+ )
+ return
+
+ if self.user:
+ if self.install_userbase is None:
+ raise DistutilsPlatformError("User base directory is not specified")
+ self.install_base = self.install_platbase = self.install_userbase
+ self.select_scheme("posix_user")
+ elif self.home is not None:
+ self.install_base = self.install_platbase = self.home
+ self.select_scheme("posix_home")
+ else:
+ if self.prefix is None:
+ if self.exec_prefix is not None:
+ raise DistutilsOptionError(
+ "must not supply exec-prefix without prefix"
+ )
+
+ # Allow Fedora to add components to the prefix
+ _prefix_addition = getattr(sysconfig, '_prefix_addition', "")
+
+ self.prefix = os.path.normpath(sys.prefix) + _prefix_addition
+ self.exec_prefix = os.path.normpath(sys.exec_prefix) + _prefix_addition
+
+ else:
+ if self.exec_prefix is None:
+ self.exec_prefix = self.prefix
+
+ self.install_base = self.prefix
+ self.install_platbase = self.exec_prefix
+ self.select_scheme("posix_prefix")
+
+ def finalize_other(self) -> None:
+ """Finalizes options for non-posix platforms"""
+ if self.user:
+ if self.install_userbase is None:
+ raise DistutilsPlatformError("User base directory is not specified")
+ self.install_base = self.install_platbase = self.install_userbase
+ self.select_scheme(os.name + "_user")
+ elif self.home is not None:
+ self.install_base = self.install_platbase = self.home
+ self.select_scheme("posix_home")
+ else:
+ if self.prefix is None:
+ self.prefix = os.path.normpath(sys.prefix)
+
+ self.install_base = self.install_platbase = self.prefix
+ try:
+ self.select_scheme(os.name)
+ except KeyError:
+ raise DistutilsPlatformError(
+ f"I don't know how to install stuff on '{os.name}'"
+ )
+
+ def select_scheme(self, name) -> None:
+ _select_scheme(self, name)
+
+ def _expand_attrs(self, attrs):
+ for attr in attrs:
+ val = getattr(self, attr)
+ if val is not None:
+ if os.name in ('posix', 'nt'):
+ val = os.path.expanduser(val)
+ val = subst_vars(val, self.config_vars)
+ setattr(self, attr, val)
+
+ def expand_basedirs(self) -> None:
+ """Calls `os.path.expanduser` on install_base, install_platbase and
+ root."""
+ self._expand_attrs(['install_base', 'install_platbase', 'root'])
+
+ def expand_dirs(self) -> None:
+ """Calls `os.path.expanduser` on install dirs."""
+ self._expand_attrs([
+ 'install_purelib',
+ 'install_platlib',
+ 'install_lib',
+ 'install_headers',
+ 'install_scripts',
+ 'install_data',
+ ])
+
+ def convert_paths(self, *names) -> None:
+ """Call `convert_path` over `names`."""
+ for name in names:
+ attr = "install_" + name
+ setattr(self, attr, convert_path(getattr(self, attr)))
+
+ def handle_extra_path(self) -> None:
+ """Set `path_file` and `extra_dirs` using `extra_path`."""
+ if self.extra_path is None:
+ self.extra_path = self.distribution.extra_path
+
+ if self.extra_path is not None:
+ log.warning(
+ "Distribution option extra_path is deprecated. "
+ "See issue27919 for details."
+ )
+ if isinstance(self.extra_path, str):
+ self.extra_path = self.extra_path.split(',')
+
+ if len(self.extra_path) == 1:
+ path_file = extra_dirs = self.extra_path[0]
+ elif len(self.extra_path) == 2:
+ path_file, extra_dirs = self.extra_path
+ else:
+ raise DistutilsOptionError(
+ "'extra_path' option must be a list, tuple, or "
+ "comma-separated string with 1 or 2 elements"
+ )
+
+ # convert to local form in case Unix notation used (as it
+ # should be in setup scripts)
+ extra_dirs = convert_path(extra_dirs)
+ else:
+ path_file = None
+ extra_dirs = ''
+
+ # XXX should we warn if path_file and not extra_dirs? (in which
+ # case the path file would be harmless but pointless)
+ self.path_file = path_file
+ self.extra_dirs = extra_dirs
+
+ def change_roots(self, *names) -> None:
+ """Change the install directories pointed by name using root."""
+ for name in names:
+ attr = "install_" + name
+ setattr(self, attr, change_root(self.root, getattr(self, attr)))
+
+ def create_home_path(self) -> None:
+ """Create directories under ~."""
+ if not self.user:
+ return
+ home = convert_path(os.path.expanduser("~"))
+ for path in self.config_vars.values():
+ if str(path).startswith(home) and not os.path.isdir(path):
+ self.debug_print(f"os.makedirs('{path}', 0o700)")
+ os.makedirs(path, 0o700)
+
+ # -- Command execution methods -------------------------------------
+
+ def run(self):
+ """Runs the command."""
+ # Obviously have to build before we can install
+ if not self.skip_build:
+ self.run_command('build')
+ # If we built for any other platform, we can't install.
+ build_plat = self.distribution.get_command_obj('build').plat_name
+ # check warn_dir - it is a clue that the 'install' is happening
+ # internally, and not to sys.path, so we don't check the platform
+ # matches what we are running.
+ if self.warn_dir and build_plat != get_platform():
+ raise DistutilsPlatformError("Can't install when cross-compiling")
+
+ # Run all sub-commands (at least those that need to be run)
+ for cmd_name in self.get_sub_commands():
+ self.run_command(cmd_name)
+
+ if self.path_file:
+ self.create_path_file()
+
+ # write list of installed files, if requested.
+ if self.record:
+ outputs = self.get_outputs()
+ if self.root: # strip any package prefix
+ root_len = len(self.root)
+ for counter in range(len(outputs)):
+ outputs[counter] = outputs[counter][root_len:]
+ self.execute(
+ write_file,
+ (self.record, outputs),
+ f"writing list of installed files to '{self.record}'",
+ )
+
+ sys_path = map(os.path.normpath, sys.path)
+ sys_path = map(os.path.normcase, sys_path)
+ install_lib = os.path.normcase(os.path.normpath(self.install_lib))
+ if (
+ self.warn_dir
+ and not (self.path_file and self.install_path_file)
+ and install_lib not in sys_path
+ ):
+ log.debug(
+ (
+ "modules installed to '%s', which is not in "
+ "Python's module search path (sys.path) -- "
+ "you'll have to change the search path yourself"
+ ),
+ self.install_lib,
+ )
+
+ def create_path_file(self):
+ """Creates the .pth file"""
+ filename = os.path.join(self.install_libbase, self.path_file + ".pth")
+ if self.install_path_file:
+ self.execute(
+ write_file, (filename, [self.extra_dirs]), f"creating {filename}"
+ )
+ else:
+ self.warn(f"path file '{filename}' not created")
+
+ # -- Reporting methods ---------------------------------------------
+
+ def get_outputs(self):
+ """Assembles the outputs of all the sub-commands."""
+ outputs = []
+ for cmd_name in self.get_sub_commands():
+ cmd = self.get_finalized_command(cmd_name)
+ # Add the contents of cmd.get_outputs(), ensuring
+ # that outputs doesn't contain duplicate entries
+ for filename in cmd.get_outputs():
+ if filename not in outputs:
+ outputs.append(filename)
+
+ if self.path_file and self.install_path_file:
+ outputs.append(os.path.join(self.install_libbase, self.path_file + ".pth"))
+
+ return outputs
+
+ def get_inputs(self):
+ """Returns the inputs of all the sub-commands"""
+ # XXX gee, this looks familiar ;-(
+ inputs = []
+ for cmd_name in self.get_sub_commands():
+ cmd = self.get_finalized_command(cmd_name)
+ inputs.extend(cmd.get_inputs())
+
+ return inputs
+
+ # -- Predicates for sub-command list -------------------------------
+
+ def has_lib(self):
+ """Returns true if the current distribution has any Python
+ modules to install."""
+ return (
+ self.distribution.has_pure_modules() or self.distribution.has_ext_modules()
+ )
+
+ def has_headers(self):
+ """Returns true if the current distribution has any headers to
+ install."""
+ return self.distribution.has_headers()
+
+ def has_scripts(self):
+ """Returns true if the current distribution has any scripts to.
+ install."""
+ return self.distribution.has_scripts()
+
+ def has_data(self):
+ """Returns true if the current distribution has any data to.
+ install."""
+ return self.distribution.has_data_files()
+
+ # 'sub_commands': a list of commands this command might have to run to
+ # get its work done. See cmd.py for more info.
+ sub_commands = [
+ ('install_lib', has_lib),
+ ('install_headers', has_headers),
+ ('install_scripts', has_scripts),
+ ('install_data', has_data),
+ ('install_egg_info', lambda self: True),
+ ]
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_data.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_data.py
new file mode 100644
index 0000000..4ad186e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_data.py
@@ -0,0 +1,94 @@
+"""distutils.command.install_data
+
+Implements the Distutils 'install_data' command, for installing
+platform-independent data files."""
+
+# contributed by Bastian Kleineidam
+
+from __future__ import annotations
+
+import functools
+import os
+from collections.abc import Iterable
+from typing import ClassVar
+
+from ..core import Command
+from ..util import change_root, convert_path
+
+
+class install_data(Command):
+ description = "install data files"
+
+ user_options = [
+ (
+ 'install-dir=',
+ 'd',
+ "base directory for installing data files [default: installation base dir]",
+ ),
+ ('root=', None, "install everything relative to this alternate root directory"),
+ ('force', 'f', "force installation (overwrite existing files)"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['force']
+
+ def initialize_options(self):
+ self.install_dir = None
+ self.outfiles = []
+ self.root = None
+ self.force = False
+ self.data_files = self.distribution.data_files
+ self.warn_dir = True
+
+ def finalize_options(self) -> None:
+ self.set_undefined_options(
+ 'install',
+ ('install_data', 'install_dir'),
+ ('root', 'root'),
+ ('force', 'force'),
+ )
+
+ def run(self) -> None:
+ self.mkpath(self.install_dir)
+ for f in self.data_files:
+ self._copy(f)
+
+ @functools.singledispatchmethod
+ def _copy(self, f: tuple[str | os.PathLike, Iterable[str | os.PathLike]]):
+ # it's a tuple with path to install to and a list of files
+ dir = convert_path(f[0])
+ if not os.path.isabs(dir):
+ dir = os.path.join(self.install_dir, dir)
+ elif self.root:
+ dir = change_root(self.root, dir)
+ self.mkpath(dir)
+
+ if f[1] == []:
+ # If there are no files listed, the user must be
+ # trying to create an empty directory, so add the
+ # directory to the list of output files.
+ self.outfiles.append(dir)
+ else:
+ # Copy files, adding them to the list of output files.
+ for data in f[1]:
+ data = convert_path(data)
+ (out, _) = self.copy_file(data, dir)
+ self.outfiles.append(out)
+
+ @_copy.register(str)
+ @_copy.register(os.PathLike)
+ def _(self, f: str | os.PathLike):
+ # it's a simple file, so copy it
+ f = convert_path(f)
+ if self.warn_dir:
+ self.warn(
+ "setup script did not provide a directory for "
+ f"'{f}' -- installing right in '{self.install_dir}'"
+ )
+ (out, _) = self.copy_file(f, self.install_dir)
+ self.outfiles.append(out)
+
+ def get_inputs(self):
+ return self.data_files or []
+
+ def get_outputs(self):
+ return self.outfiles
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_egg_info.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_egg_info.py
new file mode 100644
index 0000000..230e94a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_egg_info.py
@@ -0,0 +1,91 @@
+"""
+distutils.command.install_egg_info
+
+Implements the Distutils 'install_egg_info' command, for installing
+a package's PKG-INFO metadata.
+"""
+
+import os
+import re
+import sys
+from typing import ClassVar
+
+from .. import dir_util
+from .._log import log
+from ..cmd import Command
+
+
+class install_egg_info(Command):
+ """Install an .egg-info file for the package"""
+
+ description = "Install package's PKG-INFO metadata as an .egg-info file"
+ user_options: ClassVar[list[tuple[str, str, str]]] = [
+ ('install-dir=', 'd', "directory to install to"),
+ ]
+
+ def initialize_options(self):
+ self.install_dir = None
+
+ @property
+ def basename(self):
+ """
+ Allow basename to be overridden by child class.
+ Ref pypa/distutils#2.
+ """
+ name = to_filename(safe_name(self.distribution.get_name()))
+ version = to_filename(safe_version(self.distribution.get_version()))
+ return f"{name}-{version}-py{sys.version_info.major}.{sys.version_info.minor}.egg-info"
+
+ def finalize_options(self):
+ self.set_undefined_options('install_lib', ('install_dir', 'install_dir'))
+ self.target = os.path.join(self.install_dir, self.basename)
+ self.outputs = [self.target]
+
+ def run(self):
+ target = self.target
+ if os.path.isdir(target) and not os.path.islink(target):
+ dir_util.remove_tree(target, dry_run=self.dry_run)
+ elif os.path.exists(target):
+ self.execute(os.unlink, (self.target,), "Removing " + target)
+ elif not os.path.isdir(self.install_dir):
+ self.execute(
+ os.makedirs, (self.install_dir,), "Creating " + self.install_dir
+ )
+ log.info("Writing %s", target)
+ if not self.dry_run:
+ with open(target, 'w', encoding='UTF-8') as f:
+ self.distribution.metadata.write_pkg_file(f)
+
+ def get_outputs(self):
+ return self.outputs
+
+
+# The following routines are taken from setuptools' pkg_resources module and
+# can be replaced by importing them from pkg_resources once it is included
+# in the stdlib.
+
+
+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
+
+ Spaces become dots, and all other non-alphanumeric characters become
+ dashes, with runs of multiple dashes condensed to a single dash.
+ """
+ version = version.replace(' ', '.')
+ return re.sub('[^A-Za-z0-9.]+', '-', version)
+
+
+def to_filename(name):
+ """Convert a project or version name to its filename-escaped form
+
+ Any '-' characters are currently replaced with '_'.
+ """
+ return name.replace('-', '_')
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_headers.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_headers.py
new file mode 100644
index 0000000..97af137
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_headers.py
@@ -0,0 +1,46 @@
+"""distutils.command.install_headers
+
+Implements the Distutils 'install_headers' command, to install C/C++ header
+files to the Python include directory."""
+
+from typing import ClassVar
+
+from ..core import Command
+
+
+# XXX force is never used
+class install_headers(Command):
+ description = "install C/C++ header files"
+
+ user_options: ClassVar[list[tuple[str, str, str]]] = [
+ ('install-dir=', 'd', "directory to install header files to"),
+ ('force', 'f', "force installation (overwrite existing files)"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['force']
+
+ def initialize_options(self):
+ self.install_dir = None
+ self.force = False
+ self.outfiles = []
+
+ def finalize_options(self):
+ self.set_undefined_options(
+ 'install', ('install_headers', 'install_dir'), ('force', 'force')
+ )
+
+ def run(self):
+ headers = self.distribution.headers
+ if not headers:
+ return
+
+ self.mkpath(self.install_dir)
+ for header in headers:
+ (out, _) = self.copy_file(header, self.install_dir)
+ self.outfiles.append(out)
+
+ def get_inputs(self):
+ return self.distribution.headers or []
+
+ def get_outputs(self):
+ return self.outfiles
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_lib.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_lib.py
new file mode 100644
index 0000000..2aababf
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_lib.py
@@ -0,0 +1,238 @@
+"""distutils.command.install_lib
+
+Implements the Distutils 'install_lib' command
+(install all Python modules)."""
+
+from __future__ import annotations
+
+import importlib.util
+import os
+import sys
+from typing import Any, ClassVar
+
+from ..core import Command
+from ..errors import DistutilsOptionError
+
+# Extension for Python source files.
+PYTHON_SOURCE_EXTENSION = ".py"
+
+
+class install_lib(Command):
+ description = "install all Python modules (extensions and pure Python)"
+
+ # The byte-compilation options are a tad confusing. Here are the
+ # possible scenarios:
+ # 1) no compilation at all (--no-compile --no-optimize)
+ # 2) compile .pyc only (--compile --no-optimize; default)
+ # 3) compile .pyc and "opt-1" .pyc (--compile --optimize)
+ # 4) compile "opt-1" .pyc only (--no-compile --optimize)
+ # 5) compile .pyc and "opt-2" .pyc (--compile --optimize-more)
+ # 6) compile "opt-2" .pyc only (--no-compile --optimize-more)
+ #
+ # The UI for this is two options, 'compile' and 'optimize'.
+ # 'compile' is strictly boolean, and only decides whether to
+ # generate .pyc files. 'optimize' is three-way (0, 1, or 2), and
+ # decides both whether to generate .pyc files and what level of
+ # optimization to use.
+
+ user_options = [
+ ('install-dir=', 'd', "directory to install to"),
+ ('build-dir=', 'b', "build directory (where to install from)"),
+ ('force', 'f', "force installation (overwrite existing files)"),
+ ('compile', 'c', "compile .py to .pyc [default]"),
+ ('no-compile', None, "don't compile .py files"),
+ (
+ 'optimize=',
+ 'O',
+ "also compile with optimization: -O1 for \"python -O\", "
+ "-O2 for \"python -OO\", and -O0 to disable [default: -O0]",
+ ),
+ ('skip-build', None, "skip the build steps"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['force', 'compile', 'skip-build']
+ negative_opt: ClassVar[dict[str, str]] = {'no-compile': 'compile'}
+
+ def initialize_options(self):
+ # let the 'install' command dictate our installation directory
+ self.install_dir = None
+ self.build_dir = None
+ self.force = False
+ self.compile = None
+ self.optimize = None
+ self.skip_build = None
+
+ def finalize_options(self) -> None:
+ # Get all the information we need to install pure Python modules
+ # from the umbrella 'install' command -- build (source) directory,
+ # install (target) directory, and whether to compile .py files.
+ self.set_undefined_options(
+ 'install',
+ ('build_lib', 'build_dir'),
+ ('install_lib', 'install_dir'),
+ ('force', 'force'),
+ ('compile', 'compile'),
+ ('optimize', 'optimize'),
+ ('skip_build', 'skip_build'),
+ )
+
+ if self.compile is None:
+ self.compile = True
+ if self.optimize is None:
+ self.optimize = False
+
+ if not isinstance(self.optimize, int):
+ try:
+ self.optimize = int(self.optimize)
+ except ValueError:
+ pass
+ if self.optimize not in (0, 1, 2):
+ raise DistutilsOptionError("optimize must be 0, 1, or 2")
+
+ def run(self) -> None:
+ # Make sure we have built everything we need first
+ self.build()
+
+ # Install everything: simply dump the entire contents of the build
+ # directory to the installation directory (that's the beauty of
+ # having a build directory!)
+ outfiles = self.install()
+
+ # (Optionally) compile .py to .pyc
+ if outfiles is not None and self.distribution.has_pure_modules():
+ self.byte_compile(outfiles)
+
+ # -- Top-level worker functions ------------------------------------
+ # (called from 'run()')
+
+ def build(self) -> None:
+ if not self.skip_build:
+ if self.distribution.has_pure_modules():
+ self.run_command('build_py')
+ if self.distribution.has_ext_modules():
+ self.run_command('build_ext')
+
+ # Any: https://typing.readthedocs.io/en/latest/guides/writing_stubs.html#the-any-trick
+ def install(self) -> list[str] | Any:
+ if os.path.isdir(self.build_dir):
+ outfiles = self.copy_tree(self.build_dir, self.install_dir)
+ else:
+ self.warn(
+ f"'{self.build_dir}' does not exist -- no Python modules to install"
+ )
+ return
+ return outfiles
+
+ def byte_compile(self, files) -> None:
+ if sys.dont_write_bytecode:
+ self.warn('byte-compiling is disabled, skipping.')
+ return
+
+ from ..util import byte_compile
+
+ # Get the "--root" directory supplied to the "install" command,
+ # and use it as a prefix to strip off the purported filename
+ # encoded in bytecode files. This is far from complete, but it
+ # should at least generate usable bytecode in RPM distributions.
+ install_root = self.get_finalized_command('install').root
+
+ if self.compile:
+ byte_compile(
+ files,
+ optimize=0,
+ force=self.force,
+ prefix=install_root,
+ dry_run=self.dry_run,
+ )
+ if self.optimize > 0:
+ byte_compile(
+ files,
+ optimize=self.optimize,
+ force=self.force,
+ prefix=install_root,
+ verbose=self.verbose,
+ dry_run=self.dry_run,
+ )
+
+ # -- Utility methods -----------------------------------------------
+
+ def _mutate_outputs(self, has_any, build_cmd, cmd_option, output_dir):
+ if not has_any:
+ return []
+
+ build_cmd = self.get_finalized_command(build_cmd)
+ build_files = build_cmd.get_outputs()
+ build_dir = getattr(build_cmd, cmd_option)
+
+ prefix_len = len(build_dir) + len(os.sep)
+ outputs = [os.path.join(output_dir, file[prefix_len:]) for file in build_files]
+
+ return outputs
+
+ def _bytecode_filenames(self, py_filenames):
+ bytecode_files = []
+ for py_file in py_filenames:
+ # Since build_py handles package data installation, the
+ # list of outputs can contain more than just .py files.
+ # Make sure we only report bytecode for the .py files.
+ ext = os.path.splitext(os.path.normcase(py_file))[1]
+ if ext != PYTHON_SOURCE_EXTENSION:
+ continue
+ if self.compile:
+ bytecode_files.append(
+ importlib.util.cache_from_source(py_file, optimization='')
+ )
+ if self.optimize > 0:
+ bytecode_files.append(
+ importlib.util.cache_from_source(
+ py_file, optimization=self.optimize
+ )
+ )
+
+ return bytecode_files
+
+ # -- External interface --------------------------------------------
+ # (called by outsiders)
+
+ def get_outputs(self):
+ """Return the list of files that would be installed if this command
+ were actually run. Not affected by the "dry-run" flag or whether
+ modules have actually been built yet.
+ """
+ pure_outputs = self._mutate_outputs(
+ self.distribution.has_pure_modules(),
+ 'build_py',
+ 'build_lib',
+ self.install_dir,
+ )
+ if self.compile:
+ bytecode_outputs = self._bytecode_filenames(pure_outputs)
+ else:
+ bytecode_outputs = []
+
+ ext_outputs = self._mutate_outputs(
+ self.distribution.has_ext_modules(),
+ 'build_ext',
+ 'build_lib',
+ self.install_dir,
+ )
+
+ return pure_outputs + bytecode_outputs + ext_outputs
+
+ def get_inputs(self):
+ """Get the list of files that are input to this command, ie. the
+ files that get installed as they are named in the build tree.
+ The files in this list correspond one-to-one to the output
+ filenames returned by 'get_outputs()'.
+ """
+ inputs = []
+
+ if self.distribution.has_pure_modules():
+ build_py = self.get_finalized_command('build_py')
+ inputs.extend(build_py.get_outputs())
+
+ if self.distribution.has_ext_modules():
+ build_ext = self.get_finalized_command('build_ext')
+ inputs.extend(build_ext.get_outputs())
+
+ return inputs
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_scripts.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_scripts.py
new file mode 100644
index 0000000..92e8694
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/install_scripts.py
@@ -0,0 +1,62 @@
+"""distutils.command.install_scripts
+
+Implements the Distutils 'install_scripts' command, for installing
+Python scripts."""
+
+# contributed by Bastian Kleineidam
+
+import os
+from distutils._log import log
+from stat import ST_MODE
+from typing import ClassVar
+
+from ..core import Command
+
+
+class install_scripts(Command):
+ description = "install scripts (Python or otherwise)"
+
+ user_options = [
+ ('install-dir=', 'd', "directory to install scripts to"),
+ ('build-dir=', 'b', "build directory (where to install from)"),
+ ('force', 'f', "force installation (overwrite existing files)"),
+ ('skip-build', None, "skip the build steps"),
+ ]
+
+ boolean_options: ClassVar[list[str]] = ['force', 'skip-build']
+
+ def initialize_options(self):
+ self.install_dir = None
+ self.force = False
+ self.build_dir = None
+ self.skip_build = None
+
+ def finalize_options(self) -> None:
+ self.set_undefined_options('build', ('build_scripts', 'build_dir'))
+ self.set_undefined_options(
+ 'install',
+ ('install_scripts', 'install_dir'),
+ ('force', 'force'),
+ ('skip_build', 'skip_build'),
+ )
+
+ def run(self) -> None:
+ if not self.skip_build:
+ self.run_command('build_scripts')
+ self.outfiles = self.copy_tree(self.build_dir, self.install_dir)
+ if os.name == 'posix':
+ # Set the executable bits (owner, group, and world) on
+ # all the scripts we just installed.
+ for file in self.get_outputs():
+ if self.dry_run:
+ log.info("changing mode of %s", file)
+ else:
+ mode = ((os.stat(file)[ST_MODE]) | 0o555) & 0o7777
+ log.info("changing mode of %s to %o", file, mode)
+ os.chmod(file, mode)
+
+ def get_inputs(self):
+ return self.distribution.scripts or []
+
+ def get_outputs(self):
+ return self.outfiles or []
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/sdist.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/sdist.py
new file mode 100644
index 0000000..b3bf0c3
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/command/sdist.py
@@ -0,0 +1,521 @@
+"""distutils.command.sdist
+
+Implements the Distutils 'sdist' command (create a source distribution)."""
+
+from __future__ import annotations
+
+import os
+import sys
+from collections.abc import Callable
+from distutils import archive_util, dir_util, file_util
+from distutils._log import log
+from glob import glob
+from itertools import filterfalse
+from typing import ClassVar
+
+from ..core import Command
+from ..errors import DistutilsOptionError, DistutilsTemplateError
+from ..filelist import FileList
+from ..text_file import TextFile
+from ..util import convert_path
+
+
+def show_formats():
+ """Print all possible values for the 'formats' option (used by
+ the "--help-formats" command-line option).
+ """
+ from ..archive_util import ARCHIVE_FORMATS
+ from ..fancy_getopt import FancyGetopt
+
+ formats = sorted(
+ ("formats=" + format, None, ARCHIVE_FORMATS[format][2])
+ for format in ARCHIVE_FORMATS.keys()
+ )
+ FancyGetopt(formats).print_help("List of available source distribution formats:")
+
+
+class sdist(Command):
+ description = "create a source distribution (tarball, zip file, etc.)"
+
+ def checking_metadata(self) -> bool:
+ """Callable used for the check sub-command.
+
+ Placed here so user_options can view it"""
+ return self.metadata_check
+
+ user_options = [
+ ('template=', 't', "name of manifest template file [default: MANIFEST.in]"),
+ ('manifest=', 'm', "name of manifest file [default: MANIFEST]"),
+ (
+ 'use-defaults',
+ None,
+ "include the default file set in the manifest "
+ "[default; disable with --no-defaults]",
+ ),
+ ('no-defaults', None, "don't include the default file set"),
+ (
+ 'prune',
+ None,
+ "specifically exclude files/directories that should not be "
+ "distributed (build tree, RCS/CVS dirs, etc.) "
+ "[default; disable with --no-prune]",
+ ),
+ ('no-prune', None, "don't automatically exclude anything"),
+ (
+ 'manifest-only',
+ 'o',
+ "just regenerate the manifest and then stop (implies --force-manifest)",
+ ),
+ (
+ 'force-manifest',
+ 'f',
+ "forcibly regenerate the manifest and carry on as usual. "
+ "Deprecated: now the manifest is always regenerated.",
+ ),
+ ('formats=', None, "formats for source distribution (comma-separated list)"),
+ (
+ 'keep-temp',
+ 'k',
+ "keep the distribution tree around after creating " + "archive file(s)",
+ ),
+ (
+ 'dist-dir=',
+ 'd',
+ "directory to put the source distribution archive(s) in [default: dist]",
+ ),
+ (
+ 'metadata-check',
+ None,
+ "Ensure that all required elements of meta-data "
+ "are supplied. Warn if any missing. [default]",
+ ),
+ (
+ 'owner=',
+ 'u',
+ "Owner name used when creating a tar file [default: current user]",
+ ),
+ (
+ 'group=',
+ 'g',
+ "Group name used when creating a tar file [default: current group]",
+ ),
+ ]
+
+ boolean_options: ClassVar[list[str]] = [
+ 'use-defaults',
+ 'prune',
+ 'manifest-only',
+ 'force-manifest',
+ 'keep-temp',
+ 'metadata-check',
+ ]
+
+ help_options: ClassVar[list[tuple[str, str | None, str, Callable[[], object]]]] = [
+ ('help-formats', None, "list available distribution formats", show_formats),
+ ]
+
+ negative_opt: ClassVar[dict[str, str]] = {
+ 'no-defaults': 'use-defaults',
+ 'no-prune': 'prune',
+ }
+
+ sub_commands = [('check', checking_metadata)]
+
+ READMES: ClassVar[tuple[str, ...]] = ('README', 'README.txt', 'README.rst')
+
+ def initialize_options(self):
+ # 'template' and 'manifest' are, respectively, the names of
+ # the manifest template and manifest file.
+ self.template = None
+ self.manifest = None
+
+ # 'use_defaults': if true, we will include the default file set
+ # in the manifest
+ self.use_defaults = True
+ self.prune = True
+
+ self.manifest_only = False
+ self.force_manifest = False
+
+ self.formats = ['gztar']
+ self.keep_temp = False
+ self.dist_dir = None
+
+ self.archive_files = None
+ self.metadata_check = True
+ self.owner = None
+ self.group = None
+
+ def finalize_options(self) -> None:
+ if self.manifest is None:
+ self.manifest = "MANIFEST"
+ if self.template is None:
+ self.template = "MANIFEST.in"
+
+ self.ensure_string_list('formats')
+
+ bad_format = archive_util.check_archive_formats(self.formats)
+ if bad_format:
+ raise DistutilsOptionError(f"unknown archive format '{bad_format}'")
+
+ if self.dist_dir is None:
+ self.dist_dir = "dist"
+
+ def run(self) -> None:
+ # 'filelist' contains the list of files that will make up the
+ # manifest
+ self.filelist = FileList()
+
+ # Run sub commands
+ for cmd_name in self.get_sub_commands():
+ self.run_command(cmd_name)
+
+ # Do whatever it takes to get the list of files to process
+ # (process the manifest template, read an existing manifest,
+ # whatever). File list is accumulated in 'self.filelist'.
+ self.get_file_list()
+
+ # If user just wanted us to regenerate the manifest, stop now.
+ if self.manifest_only:
+ return
+
+ # Otherwise, go ahead and create the source distribution tarball,
+ # or zipfile, or whatever.
+ self.make_distribution()
+
+ def get_file_list(self) -> None:
+ """Figure out the list of files to include in the source
+ distribution, and put it in 'self.filelist'. This might involve
+ reading the manifest template (and writing the manifest), or just
+ reading the manifest, or just using the default file set -- it all
+ depends on the user's options.
+ """
+ # new behavior when using a template:
+ # the file list is recalculated every time because
+ # even if MANIFEST.in or setup.py are not changed
+ # the user might have added some files in the tree that
+ # need to be included.
+ #
+ # This makes --force the default and only behavior with templates.
+ template_exists = os.path.isfile(self.template)
+ if not template_exists and self._manifest_is_not_generated():
+ self.read_manifest()
+ self.filelist.sort()
+ self.filelist.remove_duplicates()
+ return
+
+ if not template_exists:
+ self.warn(
+ ("manifest template '%s' does not exist " + "(using default file list)")
+ % self.template
+ )
+ self.filelist.findall()
+
+ if self.use_defaults:
+ self.add_defaults()
+
+ if template_exists:
+ self.read_template()
+
+ if self.prune:
+ self.prune_file_list()
+
+ self.filelist.sort()
+ self.filelist.remove_duplicates()
+ self.write_manifest()
+
+ def add_defaults(self) -> None:
+ """Add all the default files to self.filelist:
+ - README or README.txt
+ - setup.py
+ - tests/test*.py and test/test*.py
+ - all pure Python modules mentioned in setup script
+ - all files pointed by package_data (build_py)
+ - all files defined in data_files.
+ - all files defined as scripts.
+ - all C sources listed as part of extensions or C libraries
+ in the setup script (doesn't catch C headers!)
+ Warns if (README or README.txt) or setup.py are missing; everything
+ else is optional.
+ """
+ self._add_defaults_standards()
+ self._add_defaults_optional()
+ self._add_defaults_python()
+ self._add_defaults_data_files()
+ self._add_defaults_ext()
+ self._add_defaults_c_libs()
+ self._add_defaults_scripts()
+
+ @staticmethod
+ def _cs_path_exists(fspath):
+ """
+ Case-sensitive path existence check
+
+ >>> sdist._cs_path_exists(__file__)
+ True
+ >>> sdist._cs_path_exists(__file__.upper())
+ False
+ """
+ if not os.path.exists(fspath):
+ return False
+ # make absolute so we always have a directory
+ abspath = os.path.abspath(fspath)
+ directory, filename = os.path.split(abspath)
+ return filename in os.listdir(directory)
+
+ def _add_defaults_standards(self):
+ standards = [self.READMES, self.distribution.script_name]
+ for fn in standards:
+ if isinstance(fn, tuple):
+ alts = fn
+ got_it = False
+ for fn in alts:
+ if self._cs_path_exists(fn):
+ got_it = True
+ self.filelist.append(fn)
+ break
+
+ if not got_it:
+ self.warn(
+ "standard file not found: should have one of " + ', '.join(alts)
+ )
+ else:
+ if self._cs_path_exists(fn):
+ self.filelist.append(fn)
+ else:
+ self.warn(f"standard file '{fn}' not found")
+
+ def _add_defaults_optional(self):
+ optional = ['tests/test*.py', 'test/test*.py', 'setup.cfg']
+ for pattern in optional:
+ files = filter(os.path.isfile, glob(pattern))
+ self.filelist.extend(files)
+
+ def _add_defaults_python(self):
+ # build_py is used to get:
+ # - python modules
+ # - files defined in package_data
+ build_py = self.get_finalized_command('build_py')
+
+ # getting python files
+ if self.distribution.has_pure_modules():
+ self.filelist.extend(build_py.get_source_files())
+
+ # getting package_data files
+ # (computed in build_py.data_files by build_py.finalize_options)
+ for _pkg, src_dir, _build_dir, filenames in build_py.data_files:
+ for filename in filenames:
+ self.filelist.append(os.path.join(src_dir, filename))
+
+ def _add_defaults_data_files(self):
+ # getting distribution.data_files
+ if self.distribution.has_data_files():
+ for item in self.distribution.data_files:
+ if isinstance(item, str):
+ # plain file
+ item = convert_path(item)
+ if os.path.isfile(item):
+ self.filelist.append(item)
+ else:
+ # a (dirname, filenames) tuple
+ dirname, filenames = item
+ for f in filenames:
+ f = convert_path(f)
+ if os.path.isfile(f):
+ self.filelist.append(f)
+
+ def _add_defaults_ext(self):
+ if self.distribution.has_ext_modules():
+ build_ext = self.get_finalized_command('build_ext')
+ self.filelist.extend(build_ext.get_source_files())
+
+ def _add_defaults_c_libs(self):
+ if self.distribution.has_c_libraries():
+ build_clib = self.get_finalized_command('build_clib')
+ self.filelist.extend(build_clib.get_source_files())
+
+ def _add_defaults_scripts(self):
+ if self.distribution.has_scripts():
+ build_scripts = self.get_finalized_command('build_scripts')
+ self.filelist.extend(build_scripts.get_source_files())
+
+ def read_template(self) -> None:
+ """Read and parse manifest template file named by self.template.
+
+ (usually "MANIFEST.in") The parsing and processing is done by
+ 'self.filelist', which updates itself accordingly.
+ """
+ log.info("reading manifest template '%s'", self.template)
+ template = TextFile(
+ self.template,
+ strip_comments=True,
+ skip_blanks=True,
+ join_lines=True,
+ lstrip_ws=True,
+ rstrip_ws=True,
+ collapse_join=True,
+ )
+
+ try:
+ while True:
+ line = template.readline()
+ if line is None: # end of file
+ break
+
+ try:
+ self.filelist.process_template_line(line)
+ # the call above can raise a DistutilsTemplateError for
+ # malformed lines, or a ValueError from the lower-level
+ # convert_path function
+ except (DistutilsTemplateError, ValueError) as msg:
+ self.warn(
+ f"{template.filename}, line {int(template.current_line)}: {msg}"
+ )
+ finally:
+ template.close()
+
+ def prune_file_list(self) -> None:
+ """Prune off branches that might slip into the file list as created
+ by 'read_template()', but really don't belong there:
+ * the build tree (typically "build")
+ * the release tree itself (only an issue if we ran "sdist"
+ previously with --keep-temp, or it aborted)
+ * any RCS, CVS, .svn, .hg, .git, .bzr, _darcs directories
+ """
+ build = self.get_finalized_command('build')
+ base_dir = self.distribution.get_fullname()
+
+ self.filelist.exclude_pattern(None, prefix=os.fspath(build.build_base))
+ self.filelist.exclude_pattern(None, prefix=base_dir)
+
+ if sys.platform == 'win32':
+ seps = r'/|\\'
+ else:
+ seps = '/'
+
+ vcs_dirs = ['RCS', 'CVS', r'\.svn', r'\.hg', r'\.git', r'\.bzr', '_darcs']
+ vcs_ptrn = r'(^|{})({})({}).*'.format(seps, '|'.join(vcs_dirs), seps)
+ self.filelist.exclude_pattern(vcs_ptrn, is_regex=True)
+
+ def write_manifest(self) -> None:
+ """Write the file list in 'self.filelist' (presumably as filled in
+ by 'add_defaults()' and 'read_template()') to the manifest file
+ named by 'self.manifest'.
+ """
+ if self._manifest_is_not_generated():
+ log.info(
+ f"not writing to manually maintained manifest file '{self.manifest}'"
+ )
+ return
+
+ content = self.filelist.files[:]
+ content.insert(0, '# file GENERATED by distutils, do NOT edit')
+ self.execute(
+ file_util.write_file,
+ (self.manifest, content),
+ f"writing manifest file '{self.manifest}'",
+ )
+
+ def _manifest_is_not_generated(self):
+ # check for special comment used in 3.1.3 and higher
+ if not os.path.isfile(self.manifest):
+ return False
+
+ with open(self.manifest, encoding='utf-8') as fp:
+ first_line = next(fp)
+ return first_line != '# file GENERATED by distutils, do NOT edit\n'
+
+ def read_manifest(self) -> None:
+ """Read the manifest file (named by 'self.manifest') and use it to
+ fill in 'self.filelist', the list of files to include in the source
+ distribution.
+ """
+ log.info("reading manifest file '%s'", self.manifest)
+ with open(self.manifest, encoding='utf-8') as lines:
+ self.filelist.extend(
+ # ignore comments and blank lines
+ filter(None, filterfalse(is_comment, map(str.strip, lines)))
+ )
+
+ def make_release_tree(self, base_dir, files) -> None:
+ """Create the directory tree that will become the source
+ distribution archive. All directories implied by the filenames in
+ 'files' are created under 'base_dir', and then we hard link or copy
+ (if hard linking is unavailable) those files into place.
+ Essentially, this duplicates the developer's source tree, but in a
+ directory named after the distribution, containing only the files
+ to be distributed.
+ """
+ # Create all the directories under 'base_dir' necessary to
+ # put 'files' there; the 'mkpath()' is just so we don't die
+ # if the manifest happens to be empty.
+ self.mkpath(base_dir)
+ dir_util.create_tree(base_dir, files, dry_run=self.dry_run)
+
+ # And walk over the list of files, either making a hard link (if
+ # os.link exists) to each one that doesn't already exist in its
+ # corresponding location under 'base_dir', or copying each file
+ # that's out-of-date in 'base_dir'. (Usually, all files will be
+ # out-of-date, because by default we blow away 'base_dir' when
+ # we're done making the distribution archives.)
+
+ if hasattr(os, 'link'): # can make hard links on this system
+ link = 'hard'
+ msg = f"making hard links in {base_dir}..."
+ else: # nope, have to copy
+ link = None
+ msg = f"copying files to {base_dir}..."
+
+ if not files:
+ log.warning("no files to distribute -- empty manifest?")
+ else:
+ log.info(msg)
+ for file in files:
+ if not os.path.isfile(file):
+ log.warning("'%s' not a regular file -- skipping", file)
+ else:
+ dest = os.path.join(base_dir, file)
+ self.copy_file(file, dest, link=link)
+
+ self.distribution.metadata.write_pkg_info(base_dir)
+
+ def make_distribution(self) -> None:
+ """Create the source distribution(s). First, we create the release
+ tree with 'make_release_tree()'; then, we create all required
+ archive files (according to 'self.formats') from the release tree.
+ Finally, we clean up by blowing away the release tree (unless
+ 'self.keep_temp' is true). The list of archive files created is
+ stored so it can be retrieved later by 'get_archive_files()'.
+ """
+ # Don't warn about missing meta-data here -- should be (and is!)
+ # done elsewhere.
+ base_dir = self.distribution.get_fullname()
+ base_name = os.path.join(self.dist_dir, base_dir)
+
+ self.make_release_tree(base_dir, self.filelist.files)
+ archive_files = [] # remember names of files we create
+ # tar archive must be created last to avoid overwrite and remove
+ if 'tar' in self.formats:
+ self.formats.append(self.formats.pop(self.formats.index('tar')))
+
+ for fmt in self.formats:
+ file = self.make_archive(
+ base_name, fmt, base_dir=base_dir, owner=self.owner, group=self.group
+ )
+ archive_files.append(file)
+ self.distribution.dist_files.append(('sdist', '', file))
+
+ self.archive_files = archive_files
+
+ if not self.keep_temp:
+ dir_util.remove_tree(base_dir, dry_run=self.dry_run)
+
+ def get_archive_files(self):
+ """Return the list of archive files created when the command
+ was run, or None if the command hasn't run yet.
+ """
+ return self.archive_files
+
+
+def is_comment(line: str) -> bool:
+ return line.startswith('#')
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__init__.py
new file mode 100644
index 0000000..2c43729
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__init__.py
@@ -0,0 +1,18 @@
+from __future__ import annotations
+
+from collections.abc import Iterable
+from typing import TypeVar
+
+_IterableT = TypeVar("_IterableT", bound="Iterable[str]")
+
+
+def consolidate_linker_args(args: _IterableT) -> _IterableT | str:
+ """
+ Ensure the return value is a string for backward compatibility.
+
+ Retain until at least 2025-04-31. See pypa/distutils#246
+ """
+
+ if not all(arg.startswith('-Wl,') for arg in args):
+ return args
+ return '-Wl,' + ','.join(arg.removeprefix('-Wl,') for arg in args)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..0799d18
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__pycache__/numpy.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__pycache__/numpy.cpython-312.pyc
new file mode 100644
index 0000000..4dcd355
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__pycache__/numpy.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__pycache__/py39.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__pycache__/py39.cpython-312.pyc
new file mode 100644
index 0000000..94f4ef2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/__pycache__/py39.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/numpy.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/numpy.py
new file mode 100644
index 0000000..73eca7a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/numpy.py
@@ -0,0 +1,2 @@
+# required for older numpy versions on Pythons prior to 3.12; see pypa/setuptools#4876
+from ..compilers.C.base import _default_compilers, compiler_class # noqa: F401
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/py39.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/py39.py
new file mode 100644
index 0000000..1b436d7
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compat/py39.py
@@ -0,0 +1,66 @@
+import functools
+import itertools
+import platform
+import sys
+
+
+def add_ext_suffix_39(vars):
+ """
+ Ensure vars contains 'EXT_SUFFIX'. pypa/distutils#130
+ """
+ import _imp
+
+ ext_suffix = _imp.extension_suffixes()[0]
+ vars.update(
+ EXT_SUFFIX=ext_suffix,
+ # sysconfig sets SO to match EXT_SUFFIX, so maintain
+ # that expectation.
+ # https://github.com/python/cpython/blob/785cc6770588de087d09e89a69110af2542be208/Lib/sysconfig.py#L671-L673
+ SO=ext_suffix,
+ )
+
+
+needs_ext_suffix = sys.version_info < (3, 10) and platform.system() == 'Windows'
+add_ext_suffix = add_ext_suffix_39 if needs_ext_suffix else lambda vars: None
+
+
+# from more_itertools
+class UnequalIterablesError(ValueError):
+ def __init__(self, details=None):
+ msg = 'Iterables have different lengths'
+ if details is not None:
+ msg += (': index 0 has length {}; index {} has length {}').format(*details)
+
+ super().__init__(msg)
+
+
+# from more_itertools
+def _zip_equal_generator(iterables):
+ _marker = object()
+ for combo in itertools.zip_longest(*iterables, fillvalue=_marker):
+ for val in combo:
+ if val is _marker:
+ raise UnequalIterablesError()
+ yield combo
+
+
+# from more_itertools
+def _zip_equal(*iterables):
+ # Check whether the iterables are all the same size.
+ try:
+ first_size = len(iterables[0])
+ for i, it in enumerate(iterables[1:], 1):
+ size = len(it)
+ if size != first_size:
+ raise UnequalIterablesError(details=(first_size, i, size))
+ # All sizes are equal, we can use the built-in zip.
+ return zip(*iterables)
+ # If any one of the iterables didn't have a length, start reading
+ # them until one runs out.
+ except TypeError:
+ return _zip_equal_generator(iterables)
+
+
+zip_strict = (
+ _zip_equal if sys.version_info < (3, 10) else functools.partial(zip, strict=True)
+)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/base.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/base.cpython-312.pyc
new file mode 100644
index 0000000..31c7e14
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/base.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/cygwin.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/cygwin.cpython-312.pyc
new file mode 100644
index 0000000..8bdd95a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/cygwin.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/errors.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/errors.cpython-312.pyc
new file mode 100644
index 0000000..70175f5
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/errors.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/msvc.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/msvc.cpython-312.pyc
new file mode 100644
index 0000000..924d1db
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/msvc.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/unix.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/unix.cpython-312.pyc
new file mode 100644
index 0000000..489eaac
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/unix.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/zos.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/zos.cpython-312.pyc
new file mode 100644
index 0000000..3d96fee
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/__pycache__/zos.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/base.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/base.py
new file mode 100644
index 0000000..5efd2a3
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/base.py
@@ -0,0 +1,1394 @@
+"""distutils.ccompiler
+
+Contains Compiler, an abstract base class that defines the interface
+for the Distutils compiler abstraction model."""
+
+from __future__ import annotations
+
+import os
+import pathlib
+import re
+import sys
+import warnings
+from collections.abc import Callable, Iterable, MutableSequence, Sequence
+from typing import (
+ TYPE_CHECKING,
+ ClassVar,
+ Literal,
+ TypeVar,
+ Union,
+ overload,
+)
+
+from more_itertools import always_iterable
+
+from ..._log import log
+from ..._modified import newer_group
+from ...dir_util import mkpath
+from ...errors import (
+ DistutilsModuleError,
+ DistutilsPlatformError,
+)
+from ...file_util import move_file
+from ...spawn import spawn
+from ...util import execute, is_mingw, split_quoted
+from .errors import (
+ CompileError,
+ LinkError,
+ UnknownFileType,
+)
+
+if TYPE_CHECKING:
+ from typing_extensions import TypeAlias, TypeVarTuple, Unpack
+
+ _Ts = TypeVarTuple("_Ts")
+
+_Macro: TypeAlias = Union[tuple[str], tuple[str, Union[str, None]]]
+_StrPathT = TypeVar("_StrPathT", bound="str | os.PathLike[str]")
+_BytesPathT = TypeVar("_BytesPathT", bound="bytes | os.PathLike[bytes]")
+
+
+class Compiler:
+ """Abstract base class to define the interface that must be implemented
+ by real compiler classes. Also has some utility methods used by
+ several compiler classes.
+
+ The basic idea behind a compiler abstraction class is that each
+ instance can be used for all the compile/link steps in building a
+ single project. Thus, attributes common to all of those compile and
+ link steps -- include directories, macros to define, libraries to link
+ against, etc. -- are attributes of the compiler instance. To allow for
+ variability in how individual files are treated, most of those
+ attributes may be varied on a per-compilation or per-link basis.
+ """
+
+ # 'compiler_type' is a class attribute that identifies this class. It
+ # keeps code that wants to know what kind of compiler it's dealing with
+ # from having to import all possible compiler classes just to do an
+ # 'isinstance'. In concrete CCompiler subclasses, 'compiler_type'
+ # should really, really be one of the keys of the 'compiler_class'
+ # dictionary (see below -- used by the 'new_compiler()' factory
+ # function) -- authors of new compiler interface classes are
+ # responsible for updating 'compiler_class'!
+ compiler_type: ClassVar[str] = None # type: ignore[assignment]
+
+ # XXX things not handled by this compiler abstraction model:
+ # * client can't provide additional options for a compiler,
+ # e.g. warning, optimization, debugging flags. Perhaps this
+ # should be the domain of concrete compiler abstraction classes
+ # (UnixCCompiler, MSVCCompiler, etc.) -- or perhaps the base
+ # class should have methods for the common ones.
+ # * can't completely override the include or library searchg
+ # path, ie. no "cc -I -Idir1 -Idir2" or "cc -L -Ldir1 -Ldir2".
+ # I'm not sure how widely supported this is even by Unix
+ # compilers, much less on other platforms. And I'm even less
+ # sure how useful it is; maybe for cross-compiling, but
+ # support for that is a ways off. (And anyways, cross
+ # compilers probably have a dedicated binary with the
+ # right paths compiled in. I hope.)
+ # * can't do really freaky things with the library list/library
+ # dirs, e.g. "-Ldir1 -lfoo -Ldir2 -lfoo" to link against
+ # different versions of libfoo.a in different locations. I
+ # think this is useless without the ability to null out the
+ # library search path anyways.
+
+ executables: ClassVar[dict]
+
+ # Subclasses that rely on the standard filename generation methods
+ # implemented below should override these; see the comment near
+ # those methods ('object_filenames()' et. al.) for details:
+ src_extensions: ClassVar[list[str] | None] = None
+ obj_extension: ClassVar[str | None] = None
+ static_lib_extension: ClassVar[str | None] = None
+ shared_lib_extension: ClassVar[str | None] = None
+ static_lib_format: ClassVar[str | None] = None # format string
+ shared_lib_format: ClassVar[str | None] = None # prob. same as static_lib_format
+ exe_extension: ClassVar[str | None] = None
+
+ # Default language settings. language_map is used to detect a source
+ # file or Extension target language, checking source filenames.
+ # language_order is used to detect the language precedence, when deciding
+ # what language to use when mixing source types. For example, if some
+ # extension has two files with ".c" extension, and one with ".cpp", it
+ # is still linked as c++.
+ language_map: ClassVar[dict[str, str]] = {
+ ".c": "c",
+ ".cc": "c++",
+ ".cpp": "c++",
+ ".cxx": "c++",
+ ".m": "objc",
+ }
+ language_order: ClassVar[list[str]] = ["c++", "objc", "c"]
+
+ include_dirs: list[str] = []
+ """
+ include dirs specific to this compiler class
+ """
+
+ library_dirs: list[str] = []
+ """
+ library dirs specific to this compiler class
+ """
+
+ def __init__(
+ self, verbose: bool = False, dry_run: bool = False, force: bool = False
+ ) -> None:
+ self.dry_run = dry_run
+ self.force = force
+ self.verbose = verbose
+
+ # 'output_dir': a common output directory for object, library,
+ # shared object, and shared library files
+ self.output_dir: str | None = None
+
+ # 'macros': a list of macro definitions (or undefinitions). A
+ # macro definition is a 2-tuple (name, value), where the value is
+ # either a string or None (no explicit value). A macro
+ # undefinition is a 1-tuple (name,).
+ self.macros: list[_Macro] = []
+
+ # 'include_dirs': a list of directories to search for include files
+ self.include_dirs = []
+
+ # 'libraries': a list of libraries to include in any link
+ # (library names, not filenames: eg. "foo" not "libfoo.a")
+ self.libraries: list[str] = []
+
+ # 'library_dirs': a list of directories to search for libraries
+ self.library_dirs = []
+
+ # 'runtime_library_dirs': a list of directories to search for
+ # shared libraries/objects at runtime
+ self.runtime_library_dirs: list[str] = []
+
+ # 'objects': a list of object files (or similar, such as explicitly
+ # named library files) to include on any link
+ self.objects: list[str] = []
+
+ for key in self.executables.keys():
+ self.set_executable(key, self.executables[key])
+
+ def set_executables(self, **kwargs: str) -> None:
+ """Define the executables (and options for them) that will be run
+ to perform the various stages of compilation. The exact set of
+ executables that may be specified here depends on the compiler
+ class (via the 'executables' class attribute), but most will have:
+ compiler the C/C++ compiler
+ linker_so linker used to create shared objects and libraries
+ linker_exe linker used to create binary executables
+ archiver static library creator
+
+ On platforms with a command-line (Unix, DOS/Windows), each of these
+ is a string that will be split into executable name and (optional)
+ list of arguments. (Splitting the string is done similarly to how
+ Unix shells operate: words are delimited by spaces, but quotes and
+ backslashes can override this. See
+ 'distutils.util.split_quoted()'.)
+ """
+
+ # Note that some CCompiler implementation classes will define class
+ # attributes 'cpp', 'cc', etc. with hard-coded executable names;
+ # this is appropriate when a compiler class is for exactly one
+ # compiler/OS combination (eg. MSVCCompiler). Other compiler
+ # classes (UnixCCompiler, in particular) are driven by information
+ # discovered at run-time, since there are many different ways to do
+ # basically the same things with Unix C compilers.
+
+ for key in kwargs:
+ if key not in self.executables:
+ raise ValueError(
+ f"unknown executable '{key}' for class {self.__class__.__name__}"
+ )
+ self.set_executable(key, kwargs[key])
+
+ def set_executable(self, key, value):
+ if isinstance(value, str):
+ setattr(self, key, split_quoted(value))
+ else:
+ setattr(self, key, value)
+
+ def _find_macro(self, name):
+ i = 0
+ for defn in self.macros:
+ if defn[0] == name:
+ return i
+ i += 1
+ return None
+
+ def _check_macro_definitions(self, definitions):
+ """Ensure that every element of 'definitions' is valid."""
+ for defn in definitions:
+ self._check_macro_definition(*defn)
+
+ def _check_macro_definition(self, defn):
+ """
+ Raise a TypeError if defn is not valid.
+
+ A valid definition is either a (name, value) 2-tuple or a (name,) tuple.
+ """
+ if not isinstance(defn, tuple) or not self._is_valid_macro(*defn):
+ raise TypeError(
+ f"invalid macro definition '{defn}': "
+ "must be tuple (string,), (string, string), or (string, None)"
+ )
+
+ @staticmethod
+ def _is_valid_macro(name, value=None):
+ """
+ A valid macro is a ``name : str`` and a ``value : str | None``.
+
+ >>> Compiler._is_valid_macro('foo', None)
+ True
+ """
+ return isinstance(name, str) and isinstance(value, (str, type(None)))
+
+ # -- Bookkeeping methods -------------------------------------------
+
+ def define_macro(self, name: str, value: str | None = None) -> None:
+ """Define a preprocessor macro for all compilations driven by this
+ compiler object. The optional parameter 'value' should be a
+ string; if it is not supplied, then the macro will be defined
+ without an explicit value and the exact outcome depends on the
+ compiler used (XXX true? does ANSI say anything about this?)
+ """
+ # Delete from the list of macro definitions/undefinitions if
+ # already there (so that this one will take precedence).
+ i = self._find_macro(name)
+ if i is not None:
+ del self.macros[i]
+
+ self.macros.append((name, value))
+
+ def undefine_macro(self, name: str) -> None:
+ """Undefine a preprocessor macro for all compilations driven by
+ this compiler object. If the same macro is defined by
+ 'define_macro()' and undefined by 'undefine_macro()' the last call
+ takes precedence (including multiple redefinitions or
+ undefinitions). If the macro is redefined/undefined on a
+ per-compilation basis (ie. in the call to 'compile()'), then that
+ takes precedence.
+ """
+ # Delete from the list of macro definitions/undefinitions if
+ # already there (so that this one will take precedence).
+ i = self._find_macro(name)
+ if i is not None:
+ del self.macros[i]
+
+ undefn = (name,)
+ self.macros.append(undefn)
+
+ def add_include_dir(self, dir: str) -> None:
+ """Add 'dir' to the list of directories that will be searched for
+ header files. The compiler is instructed to search directories in
+ the order in which they are supplied by successive calls to
+ 'add_include_dir()'.
+ """
+ self.include_dirs.append(dir)
+
+ def set_include_dirs(self, dirs: list[str]) -> None:
+ """Set the list of directories that will be searched to 'dirs' (a
+ list of strings). Overrides any preceding calls to
+ 'add_include_dir()'; subsequence calls to 'add_include_dir()' add
+ to the list passed to 'set_include_dirs()'. This does not affect
+ any list of standard include directories that the compiler may
+ search by default.
+ """
+ self.include_dirs = dirs[:]
+
+ def add_library(self, libname: str) -> None:
+ """Add 'libname' to the list of libraries that will be included in
+ all links driven by this compiler object. Note that 'libname'
+ should *not* be the name of a file containing a library, but the
+ name of the library itself: the actual filename will be inferred by
+ the linker, the compiler, or the compiler class (depending on the
+ platform).
+
+ The linker will be instructed to link against libraries in the
+ order they were supplied to 'add_library()' and/or
+ 'set_libraries()'. It is perfectly valid to duplicate library
+ names; the linker will be instructed to link against libraries as
+ many times as they are mentioned.
+ """
+ self.libraries.append(libname)
+
+ def set_libraries(self, libnames: list[str]) -> None:
+ """Set the list of libraries to be included in all links driven by
+ this compiler object to 'libnames' (a list of strings). This does
+ not affect any standard system libraries that the linker may
+ include by default.
+ """
+ self.libraries = libnames[:]
+
+ def add_library_dir(self, dir: str) -> None:
+ """Add 'dir' to the list of directories that will be searched for
+ libraries specified to 'add_library()' and 'set_libraries()'. The
+ linker will be instructed to search for libraries in the order they
+ are supplied to 'add_library_dir()' and/or 'set_library_dirs()'.
+ """
+ self.library_dirs.append(dir)
+
+ def set_library_dirs(self, dirs: list[str]) -> None:
+ """Set the list of library search directories to 'dirs' (a list of
+ strings). This does not affect any standard library search path
+ that the linker may search by default.
+ """
+ self.library_dirs = dirs[:]
+
+ def add_runtime_library_dir(self, dir: str) -> None:
+ """Add 'dir' to the list of directories that will be searched for
+ shared libraries at runtime.
+ """
+ self.runtime_library_dirs.append(dir)
+
+ def set_runtime_library_dirs(self, dirs: list[str]) -> None:
+ """Set the list of directories to search for shared libraries at
+ runtime to 'dirs' (a list of strings). This does not affect any
+ standard search path that the runtime linker may search by
+ default.
+ """
+ self.runtime_library_dirs = dirs[:]
+
+ def add_link_object(self, object: str) -> None:
+ """Add 'object' to the list of object files (or analogues, such as
+ explicitly named library files or the output of "resource
+ compilers") to be included in every link driven by this compiler
+ object.
+ """
+ self.objects.append(object)
+
+ def set_link_objects(self, objects: list[str]) -> None:
+ """Set the list of object files (or analogues) to be included in
+ every link to 'objects'. This does not affect any standard object
+ files that the linker may include by default (such as system
+ libraries).
+ """
+ self.objects = objects[:]
+
+ # -- Private utility methods --------------------------------------
+ # (here for the convenience of subclasses)
+
+ # Helper method to prep compiler in subclass compile() methods
+
+ def _setup_compile(
+ self,
+ outdir: str | None,
+ macros: list[_Macro] | None,
+ incdirs: list[str] | tuple[str, ...] | None,
+ sources,
+ depends,
+ extra,
+ ):
+ """Process arguments and decide which source files to compile."""
+ outdir, macros, incdirs = self._fix_compile_args(outdir, macros, incdirs)
+
+ if extra is None:
+ extra = []
+
+ # Get the list of expected output (object) files
+ objects = self.object_filenames(sources, strip_dir=False, output_dir=outdir)
+ assert len(objects) == len(sources)
+
+ pp_opts = gen_preprocess_options(macros, incdirs)
+
+ build = {}
+ for i in range(len(sources)):
+ src = sources[i]
+ obj = objects[i]
+ ext = os.path.splitext(src)[1]
+ self.mkpath(os.path.dirname(obj))
+ build[obj] = (src, ext)
+
+ return macros, objects, extra, pp_opts, build
+
+ def _get_cc_args(self, pp_opts, debug, before):
+ # works for unixccompiler, cygwinccompiler
+ cc_args = pp_opts + ['-c']
+ if debug:
+ cc_args[:0] = ['-g']
+ if before:
+ cc_args[:0] = before
+ return cc_args
+
+ def _fix_compile_args(
+ self,
+ output_dir: str | None,
+ macros: list[_Macro] | None,
+ include_dirs: list[str] | tuple[str, ...] | None,
+ ) -> tuple[str, list[_Macro], list[str]]:
+ """Typecheck and fix-up some of the arguments to the 'compile()'
+ method, and return fixed-up values. Specifically: if 'output_dir'
+ is None, replaces it with 'self.output_dir'; ensures that 'macros'
+ is a list, and augments it with 'self.macros'; ensures that
+ 'include_dirs' is a list, and augments it with 'self.include_dirs'.
+ Guarantees that the returned values are of the correct type,
+ i.e. for 'output_dir' either string or None, and for 'macros' and
+ 'include_dirs' either list or None.
+ """
+ if output_dir is None:
+ output_dir = self.output_dir
+ elif not isinstance(output_dir, str):
+ raise TypeError("'output_dir' must be a string or None")
+
+ if macros is None:
+ macros = list(self.macros)
+ elif isinstance(macros, list):
+ macros = macros + (self.macros or [])
+ else:
+ raise TypeError("'macros' (if supplied) must be a list of tuples")
+
+ if include_dirs is None:
+ include_dirs = list(self.include_dirs)
+ elif isinstance(include_dirs, (list, tuple)):
+ include_dirs = list(include_dirs) + (self.include_dirs or [])
+ else:
+ raise TypeError("'include_dirs' (if supplied) must be a list of strings")
+
+ # add include dirs for class
+ include_dirs += self.__class__.include_dirs
+
+ return output_dir, macros, include_dirs
+
+ def _prep_compile(self, sources, output_dir, depends=None):
+ """Decide which source files must be recompiled.
+
+ Determine the list of object files corresponding to 'sources',
+ and figure out which ones really need to be recompiled.
+ Return a list of all object files and a dictionary telling
+ which source files can be skipped.
+ """
+ # Get the list of expected output (object) files
+ objects = self.object_filenames(sources, output_dir=output_dir)
+ assert len(objects) == len(sources)
+
+ # Return an empty dict for the "which source files can be skipped"
+ # return value to preserve API compatibility.
+ return objects, {}
+
+ def _fix_object_args(
+ self, objects: list[str] | tuple[str, ...], output_dir: str | None
+ ) -> tuple[list[str], str]:
+ """Typecheck and fix up some arguments supplied to various methods.
+ Specifically: ensure that 'objects' is a list; if output_dir is
+ None, replace with self.output_dir. Return fixed versions of
+ 'objects' and 'output_dir'.
+ """
+ if not isinstance(objects, (list, tuple)):
+ raise TypeError("'objects' must be a list or tuple of strings")
+ objects = list(objects)
+
+ if output_dir is None:
+ output_dir = self.output_dir
+ elif not isinstance(output_dir, str):
+ raise TypeError("'output_dir' must be a string or None")
+
+ return (objects, output_dir)
+
+ def _fix_lib_args(
+ self,
+ libraries: list[str] | tuple[str, ...] | None,
+ library_dirs: list[str] | tuple[str, ...] | None,
+ runtime_library_dirs: list[str] | tuple[str, ...] | None,
+ ) -> tuple[list[str], list[str], list[str]]:
+ """Typecheck and fix up some of the arguments supplied to the
+ 'link_*' methods. Specifically: ensure that all arguments are
+ lists, and augment them with their permanent versions
+ (eg. 'self.libraries' augments 'libraries'). Return a tuple with
+ fixed versions of all arguments.
+ """
+ if libraries is None:
+ libraries = list(self.libraries)
+ elif isinstance(libraries, (list, tuple)):
+ libraries = list(libraries) + (self.libraries or [])
+ else:
+ raise TypeError("'libraries' (if supplied) must be a list of strings")
+
+ if library_dirs is None:
+ library_dirs = list(self.library_dirs)
+ elif isinstance(library_dirs, (list, tuple)):
+ library_dirs = list(library_dirs) + (self.library_dirs or [])
+ else:
+ raise TypeError("'library_dirs' (if supplied) must be a list of strings")
+
+ # add library dirs for class
+ library_dirs += self.__class__.library_dirs
+
+ if runtime_library_dirs is None:
+ runtime_library_dirs = list(self.runtime_library_dirs)
+ elif isinstance(runtime_library_dirs, (list, tuple)):
+ runtime_library_dirs = list(runtime_library_dirs) + (
+ self.runtime_library_dirs or []
+ )
+ else:
+ raise TypeError(
+ "'runtime_library_dirs' (if supplied) must be a list of strings"
+ )
+
+ return (libraries, library_dirs, runtime_library_dirs)
+
+ def _need_link(self, objects, output_file):
+ """Return true if we need to relink the files listed in 'objects'
+ to recreate 'output_file'.
+ """
+ if self.force:
+ return True
+ else:
+ if self.dry_run:
+ newer = newer_group(objects, output_file, missing='newer')
+ else:
+ newer = newer_group(objects, output_file)
+ return newer
+
+ def detect_language(self, sources: str | list[str]) -> str | None:
+ """Detect the language of a given file, or list of files. Uses
+ language_map, and language_order to do the job.
+ """
+ if not isinstance(sources, list):
+ sources = [sources]
+ lang = None
+ index = len(self.language_order)
+ for source in sources:
+ base, ext = os.path.splitext(source)
+ extlang = self.language_map.get(ext)
+ try:
+ extindex = self.language_order.index(extlang)
+ if extindex < index:
+ lang = extlang
+ index = extindex
+ except ValueError:
+ pass
+ return lang
+
+ # -- Worker methods ------------------------------------------------
+ # (must be implemented by subclasses)
+
+ def preprocess(
+ self,
+ source: str | os.PathLike[str],
+ output_file: str | os.PathLike[str] | None = None,
+ macros: list[_Macro] | None = None,
+ include_dirs: list[str] | tuple[str, ...] | None = None,
+ extra_preargs: list[str] | None = None,
+ extra_postargs: Iterable[str] | None = None,
+ ):
+ """Preprocess a single C/C++ source file, named in 'source'.
+ Output will be written to file named 'output_file', or stdout if
+ 'output_file' not supplied. 'macros' is a list of macro
+ definitions as for 'compile()', which will augment the macros set
+ with 'define_macro()' and 'undefine_macro()'. 'include_dirs' is a
+ list of directory names that will be added to the default list.
+
+ Raises PreprocessError on failure.
+ """
+ pass
+
+ def compile(
+ self,
+ sources: Sequence[str | os.PathLike[str]],
+ output_dir: str | None = None,
+ macros: list[_Macro] | None = None,
+ include_dirs: list[str] | tuple[str, ...] | None = None,
+ debug: bool = False,
+ extra_preargs: list[str] | None = None,
+ extra_postargs: list[str] | None = None,
+ depends: list[str] | tuple[str, ...] | None = None,
+ ) -> list[str]:
+ """Compile one or more source files.
+
+ 'sources' must be a list of filenames, most likely C/C++
+ files, but in reality anything that can be handled by a
+ particular compiler and compiler class (eg. MSVCCompiler can
+ handle resource files in 'sources'). Return a list of object
+ filenames, one per source filename in 'sources'. Depending on
+ the implementation, not all source files will necessarily be
+ compiled, but all corresponding object filenames will be
+ returned.
+
+ If 'output_dir' is given, object files will be put under it, while
+ retaining their original path component. That is, "foo/bar.c"
+ normally compiles to "foo/bar.o" (for a Unix implementation); if
+ 'output_dir' is "build", then it would compile to
+ "build/foo/bar.o".
+
+ 'macros', if given, must be a list of macro definitions. A macro
+ definition is either a (name, value) 2-tuple or a (name,) 1-tuple.
+ The former defines a macro; if the value is None, the macro is
+ defined without an explicit value. The 1-tuple case undefines a
+ macro. Later definitions/redefinitions/ undefinitions take
+ precedence.
+
+ 'include_dirs', if given, must be a list of strings, the
+ directories to add to the default include file search path for this
+ compilation only.
+
+ 'debug' is a boolean; if true, the compiler will be instructed to
+ output debug symbols in (or alongside) the object file(s).
+
+ 'extra_preargs' and 'extra_postargs' are implementation- dependent.
+ On platforms that have the notion of a command-line (e.g. Unix,
+ DOS/Windows), they are most likely lists of strings: extra
+ command-line arguments to prepend/append to the compiler command
+ line. On other platforms, consult the implementation class
+ documentation. In any event, they are intended as an escape hatch
+ for those occasions when the abstract compiler framework doesn't
+ cut the mustard.
+
+ 'depends', if given, is a list of filenames that all targets
+ depend on. If a source file is older than any file in
+ depends, then the source file will be recompiled. This
+ supports dependency tracking, but only at a coarse
+ granularity.
+
+ Raises CompileError on failure.
+ """
+ # A concrete compiler class can either override this method
+ # entirely or implement _compile().
+ macros, objects, extra_postargs, pp_opts, build = self._setup_compile(
+ output_dir, macros, include_dirs, sources, depends, extra_postargs
+ )
+ cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
+
+ for obj in objects:
+ try:
+ src, ext = build[obj]
+ except KeyError:
+ continue
+ self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
+
+ # Return *all* object filenames, not just the ones we just built.
+ return objects
+
+ def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
+ """Compile 'src' to product 'obj'."""
+ # A concrete compiler class that does not override compile()
+ # should implement _compile().
+ pass
+
+ def create_static_lib(
+ self,
+ objects: list[str] | tuple[str, ...],
+ output_libname: str,
+ output_dir: str | None = None,
+ debug: bool = False,
+ target_lang: str | None = None,
+ ) -> None:
+ """Link a bunch of stuff together to create a static library file.
+ The "bunch of stuff" consists of the list of object files supplied
+ as 'objects', the extra object files supplied to
+ 'add_link_object()' and/or 'set_link_objects()', the libraries
+ supplied to 'add_library()' and/or 'set_libraries()', and the
+ libraries supplied as 'libraries' (if any).
+
+ 'output_libname' should be a library name, not a filename; the
+ filename will be inferred from the library name. 'output_dir' is
+ the directory where the library file will be put.
+
+ 'debug' is a boolean; if true, debugging information will be
+ included in the library (note that on most platforms, it is the
+ compile step where this matters: the 'debug' flag is included here
+ just for consistency).
+
+ 'target_lang' is the target language for which the given objects
+ are being compiled. This allows specific linkage time treatment of
+ certain languages.
+
+ Raises LibError on failure.
+ """
+ pass
+
+ # values for target_desc parameter in link()
+ SHARED_OBJECT = "shared_object"
+ SHARED_LIBRARY = "shared_library"
+ EXECUTABLE = "executable"
+
+ def link(
+ self,
+ target_desc: str,
+ objects: list[str] | tuple[str, ...],
+ output_filename: str,
+ output_dir: str | None = None,
+ libraries: list[str] | tuple[str, ...] | None = None,
+ library_dirs: list[str] | tuple[str, ...] | None = None,
+ runtime_library_dirs: list[str] | tuple[str, ...] | None = None,
+ export_symbols: Iterable[str] | None = None,
+ debug: bool = False,
+ extra_preargs: list[str] | None = None,
+ extra_postargs: list[str] | None = None,
+ build_temp: str | os.PathLike[str] | None = None,
+ target_lang: str | None = None,
+ ):
+ """Link a bunch of stuff together to create an executable or
+ shared library file.
+
+ The "bunch of stuff" consists of the list of object files supplied
+ as 'objects'. 'output_filename' should be a filename. If
+ 'output_dir' is supplied, 'output_filename' is relative to it
+ (i.e. 'output_filename' can provide directory components if
+ needed).
+
+ 'libraries' is a list of libraries to link against. These are
+ library names, not filenames, since they're translated into
+ filenames in a platform-specific way (eg. "foo" becomes "libfoo.a"
+ on Unix and "foo.lib" on DOS/Windows). However, they can include a
+ directory component, which means the linker will look in that
+ specific directory rather than searching all the normal locations.
+
+ 'library_dirs', if supplied, should be a list of directories to
+ search for libraries that were specified as bare library names
+ (ie. no directory component). These are on top of the system
+ default and those supplied to 'add_library_dir()' and/or
+ 'set_library_dirs()'. 'runtime_library_dirs' is a list of
+ directories that will be embedded into the shared library and used
+ to search for other shared libraries that *it* depends on at
+ run-time. (This may only be relevant on Unix.)
+
+ 'export_symbols' is a list of symbols that the shared library will
+ export. (This appears to be relevant only on Windows.)
+
+ 'debug' is as for 'compile()' and 'create_static_lib()', with the
+ slight distinction that it actually matters on most platforms (as
+ opposed to 'create_static_lib()', which includes a 'debug' flag
+ mostly for form's sake).
+
+ 'extra_preargs' and 'extra_postargs' are as for 'compile()' (except
+ of course that they supply command-line arguments for the
+ particular linker being used).
+
+ 'target_lang' is the target language for which the given objects
+ are being compiled. This allows specific linkage time treatment of
+ certain languages.
+
+ Raises LinkError on failure.
+ """
+ raise NotImplementedError
+
+ # Old 'link_*()' methods, rewritten to use the new 'link()' method.
+
+ def link_shared_lib(
+ self,
+ objects: list[str] | tuple[str, ...],
+ output_libname: str,
+ output_dir: str | None = None,
+ libraries: list[str] | tuple[str, ...] | None = None,
+ library_dirs: list[str] | tuple[str, ...] | None = None,
+ runtime_library_dirs: list[str] | tuple[str, ...] | None = None,
+ export_symbols: Iterable[str] | None = None,
+ debug: bool = False,
+ extra_preargs: list[str] | None = None,
+ extra_postargs: list[str] | None = None,
+ build_temp: str | os.PathLike[str] | None = None,
+ target_lang: str | None = None,
+ ):
+ self.link(
+ Compiler.SHARED_LIBRARY,
+ objects,
+ self.library_filename(output_libname, lib_type='shared'),
+ output_dir,
+ libraries,
+ library_dirs,
+ runtime_library_dirs,
+ export_symbols,
+ debug,
+ extra_preargs,
+ extra_postargs,
+ build_temp,
+ target_lang,
+ )
+
+ def link_shared_object(
+ self,
+ objects: list[str] | tuple[str, ...],
+ output_filename: str,
+ output_dir: str | None = None,
+ libraries: list[str] | tuple[str, ...] | None = None,
+ library_dirs: list[str] | tuple[str, ...] | None = None,
+ runtime_library_dirs: list[str] | tuple[str, ...] | None = None,
+ export_symbols: Iterable[str] | None = None,
+ debug: bool = False,
+ extra_preargs: list[str] | None = None,
+ extra_postargs: list[str] | None = None,
+ build_temp: str | os.PathLike[str] | None = None,
+ target_lang: str | None = None,
+ ):
+ self.link(
+ Compiler.SHARED_OBJECT,
+ objects,
+ output_filename,
+ output_dir,
+ libraries,
+ library_dirs,
+ runtime_library_dirs,
+ export_symbols,
+ debug,
+ extra_preargs,
+ extra_postargs,
+ build_temp,
+ target_lang,
+ )
+
+ def link_executable(
+ self,
+ objects: list[str] | tuple[str, ...],
+ output_progname: str,
+ output_dir: str | None = None,
+ libraries: list[str] | tuple[str, ...] | None = None,
+ library_dirs: list[str] | tuple[str, ...] | None = None,
+ runtime_library_dirs: list[str] | tuple[str, ...] | None = None,
+ debug: bool = False,
+ extra_preargs: list[str] | None = None,
+ extra_postargs: list[str] | None = None,
+ target_lang: str | None = None,
+ ):
+ self.link(
+ Compiler.EXECUTABLE,
+ objects,
+ self.executable_filename(output_progname),
+ output_dir,
+ libraries,
+ library_dirs,
+ runtime_library_dirs,
+ None,
+ debug,
+ extra_preargs,
+ extra_postargs,
+ None,
+ target_lang,
+ )
+
+ # -- Miscellaneous methods -----------------------------------------
+ # These are all used by the 'gen_lib_options() function; there is
+ # no appropriate default implementation so subclasses should
+ # implement all of these.
+
+ def library_dir_option(self, dir: str) -> str:
+ """Return the compiler option to add 'dir' to the list of
+ directories searched for libraries.
+ """
+ raise NotImplementedError
+
+ def runtime_library_dir_option(self, dir: str) -> str:
+ """Return the compiler option to add 'dir' to the list of
+ directories searched for runtime libraries.
+ """
+ raise NotImplementedError
+
+ def library_option(self, lib: str) -> str:
+ """Return the compiler option to add 'lib' to the list of libraries
+ linked into the shared library or executable.
+ """
+ raise NotImplementedError
+
+ def has_function( # noqa: C901
+ self,
+ funcname: str,
+ includes: Iterable[str] | None = None,
+ include_dirs: list[str] | tuple[str, ...] | None = None,
+ libraries: list[str] | None = None,
+ library_dirs: list[str] | tuple[str, ...] | None = None,
+ ) -> bool:
+ """Return a boolean indicating whether funcname is provided as
+ a symbol on the current platform. The optional arguments can
+ be used to augment the compilation environment.
+
+ The libraries argument is a list of flags to be passed to the
+ linker to make additional symbol definitions available for
+ linking.
+
+ The includes and include_dirs arguments are deprecated.
+ Usually, supplying include files with function declarations
+ will cause function detection to fail even in cases where the
+ symbol is available for linking.
+
+ """
+ # this can't be included at module scope because it tries to
+ # import math which might not be available at that point - maybe
+ # the necessary logic should just be inlined?
+ import tempfile
+
+ if includes is None:
+ includes = []
+ else:
+ warnings.warn("includes is deprecated", DeprecationWarning)
+ if include_dirs is None:
+ include_dirs = []
+ else:
+ warnings.warn("include_dirs is deprecated", DeprecationWarning)
+ if libraries is None:
+ libraries = []
+ if library_dirs is None:
+ library_dirs = []
+ fd, fname = tempfile.mkstemp(".c", funcname, text=True)
+ with os.fdopen(fd, "w", encoding='utf-8') as f:
+ for incl in includes:
+ f.write(f"""#include "{incl}"\n""")
+ if not includes:
+ # Use "char func(void);" as the prototype to follow
+ # what autoconf does. This prototype does not match
+ # any well-known function the compiler might recognize
+ # as a builtin, so this ends up as a true link test.
+ # Without a fake prototype, the test would need to
+ # know the exact argument types, and the has_function
+ # interface does not provide that level of information.
+ f.write(
+ f"""\
+#ifdef __cplusplus
+extern "C"
+#endif
+char {funcname}(void);
+"""
+ )
+ f.write(
+ f"""\
+int main (int argc, char **argv) {{
+ {funcname}();
+ return 0;
+}}
+"""
+ )
+
+ try:
+ objects = self.compile([fname], include_dirs=include_dirs)
+ except CompileError:
+ return False
+ finally:
+ os.remove(fname)
+
+ try:
+ self.link_executable(
+ objects, "a.out", libraries=libraries, library_dirs=library_dirs
+ )
+ except (LinkError, TypeError):
+ return False
+ else:
+ os.remove(
+ self.executable_filename("a.out", output_dir=self.output_dir or '')
+ )
+ finally:
+ for fn in objects:
+ os.remove(fn)
+ return True
+
+ def find_library_file(
+ self, dirs: Iterable[str], lib: str, debug: bool = False
+ ) -> str | None:
+ """Search the specified list of directories for a static or shared
+ library file 'lib' and return the full path to that file. If
+ 'debug' true, look for a debugging version (if that makes sense on
+ the current platform). Return None if 'lib' wasn't found in any of
+ the specified directories.
+ """
+ raise NotImplementedError
+
+ # -- Filename generation methods -----------------------------------
+
+ # The default implementation of the filename generating methods are
+ # prejudiced towards the Unix/DOS/Windows view of the world:
+ # * object files are named by replacing the source file extension
+ # (eg. .c/.cpp -> .o/.obj)
+ # * library files (shared or static) are named by plugging the
+ # library name and extension into a format string, eg.
+ # "lib%s.%s" % (lib_name, ".a") for Unix static libraries
+ # * executables are named by appending an extension (possibly
+ # empty) to the program name: eg. progname + ".exe" for
+ # Windows
+ #
+ # To reduce redundant code, these methods expect to find
+ # several attributes in the current object (presumably defined
+ # as class attributes):
+ # * src_extensions -
+ # list of C/C++ source file extensions, eg. ['.c', '.cpp']
+ # * obj_extension -
+ # object file extension, eg. '.o' or '.obj'
+ # * static_lib_extension -
+ # extension for static library files, eg. '.a' or '.lib'
+ # * shared_lib_extension -
+ # extension for shared library/object files, eg. '.so', '.dll'
+ # * static_lib_format -
+ # format string for generating static library filenames,
+ # eg. 'lib%s.%s' or '%s.%s'
+ # * shared_lib_format
+ # format string for generating shared library filenames
+ # (probably same as static_lib_format, since the extension
+ # is one of the intended parameters to the format string)
+ # * exe_extension -
+ # extension for executable files, eg. '' or '.exe'
+
+ def object_filenames(
+ self,
+ source_filenames: Iterable[str | os.PathLike[str]],
+ strip_dir: bool = False,
+ output_dir: str | os.PathLike[str] | None = '',
+ ) -> list[str]:
+ if output_dir is None:
+ output_dir = ''
+ return list(
+ self._make_out_path(output_dir, strip_dir, src_name)
+ for src_name in source_filenames
+ )
+
+ @property
+ def out_extensions(self):
+ return dict.fromkeys(self.src_extensions, self.obj_extension)
+
+ def _make_out_path(self, output_dir, strip_dir, src_name):
+ return self._make_out_path_exts(
+ output_dir, strip_dir, src_name, self.out_extensions
+ )
+
+ @classmethod
+ def _make_out_path_exts(cls, output_dir, strip_dir, src_name, extensions):
+ r"""
+ >>> exts = {'.c': '.o'}
+ >>> Compiler._make_out_path_exts('.', False, '/foo/bar.c', exts).replace('\\', '/')
+ './foo/bar.o'
+ >>> Compiler._make_out_path_exts('.', True, '/foo/bar.c', exts).replace('\\', '/')
+ './bar.o'
+ """
+ src = pathlib.PurePath(src_name)
+ # Ensure base is relative to honor output_dir (python/cpython#37775).
+ base = cls._make_relative(src)
+ try:
+ new_ext = extensions[src.suffix]
+ except LookupError:
+ raise UnknownFileType(f"unknown file type '{src.suffix}' (from '{src}')")
+ if strip_dir:
+ base = pathlib.PurePath(base.name)
+ return os.path.join(output_dir, base.with_suffix(new_ext))
+
+ @staticmethod
+ def _make_relative(base: pathlib.Path):
+ return base.relative_to(base.anchor)
+
+ @overload
+ def shared_object_filename(
+ self,
+ basename: str,
+ strip_dir: Literal[False] = False,
+ output_dir: str | os.PathLike[str] = "",
+ ) -> str: ...
+ @overload
+ def shared_object_filename(
+ self,
+ basename: str | os.PathLike[str],
+ strip_dir: Literal[True],
+ output_dir: str | os.PathLike[str] = "",
+ ) -> str: ...
+ def shared_object_filename(
+ self,
+ basename: str | os.PathLike[str],
+ strip_dir: bool = False,
+ output_dir: str | os.PathLike[str] = '',
+ ) -> str:
+ assert output_dir is not None
+ if strip_dir:
+ basename = os.path.basename(basename)
+ return os.path.join(output_dir, basename + self.shared_lib_extension)
+
+ @overload
+ def executable_filename(
+ self,
+ basename: str,
+ strip_dir: Literal[False] = False,
+ output_dir: str | os.PathLike[str] = "",
+ ) -> str: ...
+ @overload
+ def executable_filename(
+ self,
+ basename: str | os.PathLike[str],
+ strip_dir: Literal[True],
+ output_dir: str | os.PathLike[str] = "",
+ ) -> str: ...
+ def executable_filename(
+ self,
+ basename: str | os.PathLike[str],
+ strip_dir: bool = False,
+ output_dir: str | os.PathLike[str] = '',
+ ) -> str:
+ assert output_dir is not None
+ if strip_dir:
+ basename = os.path.basename(basename)
+ return os.path.join(output_dir, basename + (self.exe_extension or ''))
+
+ def library_filename(
+ self,
+ libname: str,
+ lib_type: str = "static",
+ strip_dir: bool = False,
+ output_dir: str | os.PathLike[str] = "", # or 'shared'
+ ):
+ assert output_dir is not None
+ expected = '"static", "shared", "dylib", "xcode_stub"'
+ if lib_type not in eval(expected):
+ raise ValueError(f"'lib_type' must be {expected}")
+ fmt = getattr(self, lib_type + "_lib_format")
+ ext = getattr(self, lib_type + "_lib_extension")
+
+ dir, base = os.path.split(libname)
+ filename = fmt % (base, ext)
+ if strip_dir:
+ dir = ''
+
+ return os.path.join(output_dir, dir, filename)
+
+ # -- Utility methods -----------------------------------------------
+
+ def announce(self, msg: object, level: int = 1) -> None:
+ log.debug(msg)
+
+ def debug_print(self, msg: object) -> None:
+ from distutils.debug import DEBUG
+
+ if DEBUG:
+ print(msg)
+
+ def warn(self, msg: object) -> None:
+ sys.stderr.write(f"warning: {msg}\n")
+
+ def execute(
+ self,
+ func: Callable[[Unpack[_Ts]], object],
+ args: tuple[Unpack[_Ts]],
+ msg: object = None,
+ level: int = 1,
+ ) -> None:
+ execute(func, args, msg, self.dry_run)
+
+ def spawn(
+ self, cmd: MutableSequence[bytes | str | os.PathLike[str]], **kwargs
+ ) -> None:
+ spawn(cmd, dry_run=self.dry_run, **kwargs)
+
+ @overload
+ def move_file(
+ self, src: str | os.PathLike[str], dst: _StrPathT
+ ) -> _StrPathT | str: ...
+ @overload
+ def move_file(
+ self, src: bytes | os.PathLike[bytes], dst: _BytesPathT
+ ) -> _BytesPathT | bytes: ...
+ def move_file(
+ self,
+ src: str | os.PathLike[str] | bytes | os.PathLike[bytes],
+ dst: str | os.PathLike[str] | bytes | os.PathLike[bytes],
+ ) -> str | os.PathLike[str] | bytes | os.PathLike[bytes]:
+ return move_file(src, dst, dry_run=self.dry_run)
+
+ def mkpath(self, name, mode=0o777):
+ mkpath(name, mode, dry_run=self.dry_run)
+
+
+# Map a sys.platform/os.name ('posix', 'nt') to the default compiler
+# type for that platform. Keys are interpreted as re match
+# patterns. Order is important; platform mappings are preferred over
+# OS names.
+_default_compilers = (
+ # Platform string mappings
+ # on a cygwin built python we can use gcc like an ordinary UNIXish
+ # compiler
+ ('cygwin.*', 'unix'),
+ ('zos', 'zos'),
+ # OS name mappings
+ ('posix', 'unix'),
+ ('nt', 'msvc'),
+)
+
+
+def get_default_compiler(osname: str | None = None, platform: str | None = None) -> str:
+ """Determine the default compiler to use for the given platform.
+
+ osname should be one of the standard Python OS names (i.e. the
+ ones returned by os.name) and platform the common value
+ returned by sys.platform for the platform in question.
+
+ The default values are os.name and sys.platform in case the
+ parameters are not given.
+ """
+ if osname is None:
+ osname = os.name
+ if platform is None:
+ platform = sys.platform
+ # Mingw is a special case where sys.platform is 'win32' but we
+ # want to use the 'mingw32' compiler, so check it first
+ if is_mingw():
+ return 'mingw32'
+ for pattern, compiler in _default_compilers:
+ if (
+ re.match(pattern, platform) is not None
+ or re.match(pattern, osname) is not None
+ ):
+ return compiler
+ # Default to Unix compiler
+ return 'unix'
+
+
+# Map compiler types to (module_name, class_name) pairs -- ie. where to
+# find the code that implements an interface to this compiler. (The module
+# is assumed to be in the 'distutils' package.)
+compiler_class = {
+ 'unix': ('unixccompiler', 'UnixCCompiler', "standard UNIX-style compiler"),
+ 'msvc': ('_msvccompiler', 'MSVCCompiler', "Microsoft Visual C++"),
+ 'cygwin': (
+ 'cygwinccompiler',
+ 'CygwinCCompiler',
+ "Cygwin port of GNU C Compiler for Win32",
+ ),
+ 'mingw32': (
+ 'cygwinccompiler',
+ 'Mingw32CCompiler',
+ "Mingw32 port of GNU C Compiler for Win32",
+ ),
+ 'bcpp': ('bcppcompiler', 'BCPPCompiler', "Borland C++ Compiler"),
+ 'zos': ('zosccompiler', 'zOSCCompiler', 'IBM XL C/C++ Compilers'),
+}
+
+
+def show_compilers() -> None:
+ """Print list of available compilers (used by the "--help-compiler"
+ options to "build", "build_ext", "build_clib").
+ """
+ # XXX this "knows" that the compiler option it's describing is
+ # "--compiler", which just happens to be the case for the three
+ # commands that use it.
+ from distutils.fancy_getopt import FancyGetopt
+
+ compilers = sorted(
+ ("compiler=" + compiler, None, compiler_class[compiler][2])
+ for compiler in compiler_class.keys()
+ )
+ pretty_printer = FancyGetopt(compilers)
+ pretty_printer.print_help("List of available compilers:")
+
+
+def new_compiler(
+ plat: str | None = None,
+ compiler: str | None = None,
+ verbose: bool = False,
+ dry_run: bool = False,
+ force: bool = False,
+) -> Compiler:
+ """Generate an instance of some CCompiler subclass for the supplied
+ platform/compiler combination. 'plat' defaults to 'os.name'
+ (eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler
+ for that platform. Currently only 'posix' and 'nt' are supported, and
+ the default compilers are "traditional Unix interface" (UnixCCompiler
+ class) and Visual C++ (MSVCCompiler class). Note that it's perfectly
+ possible to ask for a Unix compiler object under Windows, and a
+ Microsoft compiler object under Unix -- if you supply a value for
+ 'compiler', 'plat' is ignored.
+ """
+ if plat is None:
+ plat = os.name
+
+ try:
+ if compiler is None:
+ compiler = get_default_compiler(plat)
+
+ (module_name, class_name, long_description) = compiler_class[compiler]
+ except KeyError:
+ msg = f"don't know how to compile C/C++ code on platform '{plat}'"
+ if compiler is not None:
+ msg = msg + f" with '{compiler}' compiler"
+ raise DistutilsPlatformError(msg)
+
+ try:
+ module_name = "distutils." + module_name
+ __import__(module_name)
+ module = sys.modules[module_name]
+ klass = vars(module)[class_name]
+ except ImportError:
+ raise DistutilsModuleError(
+ f"can't compile C/C++ code: unable to load module '{module_name}'"
+ )
+ except KeyError:
+ raise DistutilsModuleError(
+ f"can't compile C/C++ code: unable to find class '{class_name}' "
+ f"in module '{module_name}'"
+ )
+
+ # XXX The None is necessary to preserve backwards compatibility
+ # with classes that expect verbose to be the first positional
+ # argument.
+ return klass(None, dry_run, force)
+
+
+def gen_preprocess_options(
+ macros: Iterable[_Macro], include_dirs: Iterable[str]
+) -> list[str]:
+ """Generate C pre-processor options (-D, -U, -I) as used by at least
+ two types of compilers: the typical Unix compiler and Visual C++.
+ 'macros' is the usual thing, a list of 1- or 2-tuples, where (name,)
+ means undefine (-U) macro 'name', and (name,value) means define (-D)
+ macro 'name' to 'value'. 'include_dirs' is just a list of directory
+ names to be added to the header file search path (-I). Returns a list
+ of command-line options suitable for either Unix compilers or Visual
+ C++.
+ """
+ # XXX it would be nice (mainly aesthetic, and so we don't generate
+ # stupid-looking command lines) to go over 'macros' and eliminate
+ # redundant definitions/undefinitions (ie. ensure that only the
+ # latest mention of a particular macro winds up on the command
+ # line). I don't think it's essential, though, since most (all?)
+ # Unix C compilers only pay attention to the latest -D or -U
+ # mention of a macro on their command line. Similar situation for
+ # 'include_dirs'. I'm punting on both for now. Anyways, weeding out
+ # redundancies like this should probably be the province of
+ # CCompiler, since the data structures used are inherited from it
+ # and therefore common to all CCompiler classes.
+ pp_opts = []
+ for macro in macros:
+ if not (isinstance(macro, tuple) and 1 <= len(macro) <= 2):
+ raise TypeError(
+ f"bad macro definition '{macro}': "
+ "each element of 'macros' list must be a 1- or 2-tuple"
+ )
+
+ if len(macro) == 1: # undefine this macro
+ pp_opts.append(f"-U{macro[0]}")
+ elif len(macro) == 2:
+ if macro[1] is None: # define with no explicit value
+ pp_opts.append(f"-D{macro[0]}")
+ else:
+ # XXX *don't* need to be clever about quoting the
+ # macro value here, because we're going to avoid the
+ # shell at all costs when we spawn the command!
+ pp_opts.append("-D{}={}".format(*macro))
+
+ pp_opts.extend(f"-I{dir}" for dir in include_dirs)
+ return pp_opts
+
+
+def gen_lib_options(
+ compiler: Compiler,
+ library_dirs: Iterable[str],
+ runtime_library_dirs: Iterable[str],
+ libraries: Iterable[str],
+) -> list[str]:
+ """Generate linker options for searching library directories and
+ linking with specific libraries. 'libraries' and 'library_dirs' are,
+ respectively, lists of library names (not filenames!) and search
+ directories. Returns a list of command-line options suitable for use
+ with some compiler (depending on the two format strings passed in).
+ """
+ lib_opts = [compiler.library_dir_option(dir) for dir in library_dirs]
+
+ for dir in runtime_library_dirs:
+ lib_opts.extend(always_iterable(compiler.runtime_library_dir_option(dir)))
+
+ # XXX it's important that we *not* remove redundant library mentions!
+ # sometimes you really do have to say "-lfoo -lbar -lfoo" in order to
+ # resolve all symbols. I just hope we never have to say "-lfoo obj.o
+ # -lbar" to get things to work -- that's certainly a possibility, but a
+ # pretty nasty way to arrange your C code.
+
+ for lib in libraries:
+ (lib_dir, lib_name) = os.path.split(lib)
+ if lib_dir:
+ lib_file = compiler.find_library_file([lib_dir], lib_name)
+ if lib_file:
+ lib_opts.append(lib_file)
+ else:
+ compiler.warn(
+ f"no library file corresponding to '{lib}' found (skipping)"
+ )
+ else:
+ lib_opts.append(compiler.library_option(lib))
+ return lib_opts
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/cygwin.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/cygwin.py
new file mode 100644
index 0000000..bfabbb3
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/cygwin.py
@@ -0,0 +1,340 @@
+"""distutils.cygwinccompiler
+
+Provides the CygwinCCompiler class, a subclass of UnixCCompiler that
+handles the Cygwin port of the GNU C compiler to Windows. It also contains
+the Mingw32CCompiler class which handles the mingw32 port of GCC (same as
+cygwin in no-cygwin mode).
+"""
+
+import copy
+import os
+import pathlib
+import shlex
+import sys
+import warnings
+from subprocess import check_output
+
+from ...errors import (
+ DistutilsExecError,
+ DistutilsPlatformError,
+)
+from ...file_util import write_file
+from ...sysconfig import get_config_vars
+from ...version import LooseVersion, suppress_known_deprecation
+from . import unix
+from .errors import (
+ CompileError,
+ Error,
+)
+
+
+def get_msvcr():
+ """No longer needed, but kept for backward compatibility."""
+ return []
+
+
+_runtime_library_dirs_msg = (
+ "Unable to set runtime library search path on Windows, "
+ "usually indicated by `runtime_library_dirs` parameter to Extension"
+)
+
+
+class Compiler(unix.Compiler):
+ """Handles the Cygwin port of the GNU C compiler to Windows."""
+
+ compiler_type = 'cygwin'
+ obj_extension = ".o"
+ static_lib_extension = ".a"
+ shared_lib_extension = ".dll.a"
+ dylib_lib_extension = ".dll"
+ static_lib_format = "lib%s%s"
+ shared_lib_format = "lib%s%s"
+ dylib_lib_format = "cyg%s%s"
+ exe_extension = ".exe"
+
+ def __init__(self, verbose=False, dry_run=False, force=False):
+ super().__init__(verbose, dry_run, force)
+
+ status, details = check_config_h()
+ self.debug_print(f"Python's GCC status: {status} (details: {details})")
+ if status is not CONFIG_H_OK:
+ self.warn(
+ "Python's pyconfig.h doesn't seem to support your compiler. "
+ f"Reason: {details}. "
+ "Compiling may fail because of undefined preprocessor macros."
+ )
+
+ self.cc, self.cxx = get_config_vars('CC', 'CXX')
+
+ # Override 'CC' and 'CXX' environment variables for
+ # building using MINGW compiler for MSVC python.
+ self.cc = os.environ.get('CC', self.cc or 'gcc')
+ self.cxx = os.environ.get('CXX', self.cxx or 'g++')
+
+ self.linker_dll = self.cc
+ self.linker_dll_cxx = self.cxx
+ shared_option = "-shared"
+
+ self.set_executables(
+ compiler=f'{self.cc} -mcygwin -O -Wall',
+ compiler_so=f'{self.cc} -mcygwin -mdll -O -Wall',
+ compiler_cxx=f'{self.cxx} -mcygwin -O -Wall',
+ compiler_so_cxx=f'{self.cxx} -mcygwin -mdll -O -Wall',
+ linker_exe=f'{self.cc} -mcygwin',
+ linker_so=f'{self.linker_dll} -mcygwin {shared_option}',
+ linker_exe_cxx=f'{self.cxx} -mcygwin',
+ linker_so_cxx=f'{self.linker_dll_cxx} -mcygwin {shared_option}',
+ )
+
+ self.dll_libraries = get_msvcr()
+
+ @property
+ def gcc_version(self):
+ # Older numpy depended on this existing to check for ancient
+ # gcc versions. This doesn't make much sense with clang etc so
+ # just hardcode to something recent.
+ # https://github.com/numpy/numpy/pull/20333
+ warnings.warn(
+ "gcc_version attribute of CygwinCCompiler is deprecated. "
+ "Instead of returning actual gcc version a fixed value 11.2.0 is returned.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ with suppress_known_deprecation():
+ return LooseVersion("11.2.0")
+
+ def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
+ """Compiles the source by spawning GCC and windres if needed."""
+ if ext in ('.rc', '.res'):
+ # gcc needs '.res' and '.rc' compiled to object files !!!
+ try:
+ self.spawn(["windres", "-i", src, "-o", obj])
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
+ else: # for other files use the C-compiler
+ try:
+ if self.detect_language(src) == 'c++':
+ self.spawn(
+ self.compiler_so_cxx
+ + cc_args
+ + [src, '-o', obj]
+ + extra_postargs
+ )
+ else:
+ self.spawn(
+ self.compiler_so + cc_args + [src, '-o', obj] + extra_postargs
+ )
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
+
+ def link(
+ self,
+ target_desc,
+ objects,
+ output_filename,
+ output_dir=None,
+ libraries=None,
+ library_dirs=None,
+ runtime_library_dirs=None,
+ export_symbols=None,
+ debug=False,
+ extra_preargs=None,
+ extra_postargs=None,
+ build_temp=None,
+ target_lang=None,
+ ):
+ """Link the objects."""
+ # use separate copies, so we can modify the lists
+ extra_preargs = copy.copy(extra_preargs or [])
+ libraries = copy.copy(libraries or [])
+ objects = copy.copy(objects or [])
+
+ if runtime_library_dirs:
+ self.warn(_runtime_library_dirs_msg)
+
+ # Additional libraries
+ libraries.extend(self.dll_libraries)
+
+ # handle export symbols by creating a def-file
+ # with executables this only works with gcc/ld as linker
+ if (export_symbols is not None) and (
+ target_desc != self.EXECUTABLE or self.linker_dll == "gcc"
+ ):
+ # (The linker doesn't do anything if output is up-to-date.
+ # So it would probably better to check if we really need this,
+ # but for this we had to insert some unchanged parts of
+ # UnixCCompiler, and this is not what we want.)
+
+ # we want to put some files in the same directory as the
+ # object files are, build_temp doesn't help much
+ # where are the object files
+ temp_dir = os.path.dirname(objects[0])
+ # name of dll to give the helper files the same base name
+ (dll_name, dll_extension) = os.path.splitext(
+ os.path.basename(output_filename)
+ )
+
+ # generate the filenames for these files
+ def_file = os.path.join(temp_dir, dll_name + ".def")
+
+ # Generate .def file
+ contents = [f"LIBRARY {os.path.basename(output_filename)}", "EXPORTS"]
+ contents.extend(export_symbols)
+ self.execute(write_file, (def_file, contents), f"writing {def_file}")
+
+ # next add options for def-file
+
+ # for gcc/ld the def-file is specified as any object files
+ objects.append(def_file)
+
+ # end: if ((export_symbols is not None) and
+ # (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
+
+ # who wants symbols and a many times larger output file
+ # should explicitly switch the debug mode on
+ # otherwise we let ld strip the output file
+ # (On my machine: 10KiB < stripped_file < ??100KiB
+ # unstripped_file = stripped_file + XXX KiB
+ # ( XXX=254 for a typical python extension))
+ if not debug:
+ extra_preargs.append("-s")
+
+ super().link(
+ target_desc,
+ objects,
+ output_filename,
+ output_dir,
+ libraries,
+ library_dirs,
+ runtime_library_dirs,
+ None, # export_symbols, we do this in our def-file
+ debug,
+ extra_preargs,
+ extra_postargs,
+ build_temp,
+ target_lang,
+ )
+
+ def runtime_library_dir_option(self, dir):
+ # cygwin doesn't support rpath. While in theory we could error
+ # out like MSVC does, code might expect it to work like on Unix, so
+ # just warn and hope for the best.
+ self.warn(_runtime_library_dirs_msg)
+ return []
+
+ # -- Miscellaneous methods -----------------------------------------
+
+ def _make_out_path(self, output_dir, strip_dir, src_name):
+ # use normcase to make sure '.rc' is really '.rc' and not '.RC'
+ norm_src_name = os.path.normcase(src_name)
+ return super()._make_out_path(output_dir, strip_dir, norm_src_name)
+
+ @property
+ def out_extensions(self):
+ """
+ Add support for rc and res files.
+ """
+ return {
+ **super().out_extensions,
+ **{ext: ext + self.obj_extension for ext in ('.res', '.rc')},
+ }
+
+
+# the same as cygwin plus some additional parameters
+class MinGW32Compiler(Compiler):
+ """Handles the Mingw32 port of the GNU C compiler to Windows."""
+
+ compiler_type = 'mingw32'
+
+ def __init__(self, verbose=False, dry_run=False, force=False):
+ super().__init__(verbose, dry_run, force)
+
+ shared_option = "-shared"
+
+ if is_cygwincc(self.cc):
+ raise Error('Cygwin gcc cannot be used with --compiler=mingw32')
+
+ self.set_executables(
+ compiler=f'{self.cc} -O -Wall',
+ compiler_so=f'{self.cc} -shared -O -Wall',
+ compiler_so_cxx=f'{self.cxx} -shared -O -Wall',
+ compiler_cxx=f'{self.cxx} -O -Wall',
+ linker_exe=f'{self.cc}',
+ linker_so=f'{self.linker_dll} {shared_option}',
+ linker_exe_cxx=f'{self.cxx}',
+ linker_so_cxx=f'{self.linker_dll_cxx} {shared_option}',
+ )
+
+ def runtime_library_dir_option(self, dir):
+ raise DistutilsPlatformError(_runtime_library_dirs_msg)
+
+
+# Because these compilers aren't configured in Python's pyconfig.h file by
+# default, we should at least warn the user if he is using an unmodified
+# version.
+
+CONFIG_H_OK = "ok"
+CONFIG_H_NOTOK = "not ok"
+CONFIG_H_UNCERTAIN = "uncertain"
+
+
+def check_config_h():
+ """Check if the current Python installation appears amenable to building
+ extensions with GCC.
+
+ Returns a tuple (status, details), where 'status' is one of the following
+ constants:
+
+ - CONFIG_H_OK: all is well, go ahead and compile
+ - CONFIG_H_NOTOK: doesn't look good
+ - CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h
+
+ 'details' is a human-readable string explaining the situation.
+
+ Note there are two ways to conclude "OK": either 'sys.version' contains
+ the string "GCC" (implying that this Python was built with GCC), or the
+ installed "pyconfig.h" contains the string "__GNUC__".
+ """
+
+ # XXX since this function also checks sys.version, it's not strictly a
+ # "pyconfig.h" check -- should probably be renamed...
+
+ from distutils import sysconfig
+
+ # if sys.version contains GCC then python was compiled with GCC, and the
+ # pyconfig.h file should be OK
+ if "GCC" in sys.version:
+ return CONFIG_H_OK, "sys.version mentions 'GCC'"
+
+ # Clang would also work
+ if "Clang" in sys.version:
+ return CONFIG_H_OK, "sys.version mentions 'Clang'"
+
+ # let's see if __GNUC__ is mentioned in python.h
+ fn = sysconfig.get_config_h_filename()
+ try:
+ config_h = pathlib.Path(fn).read_text(encoding='utf-8')
+ except OSError as exc:
+ return (CONFIG_H_UNCERTAIN, f"couldn't read '{fn}': {exc.strerror}")
+ else:
+ substring = '__GNUC__'
+ if substring in config_h:
+ code = CONFIG_H_OK
+ mention_inflected = 'mentions'
+ else:
+ code = CONFIG_H_NOTOK
+ mention_inflected = 'does not mention'
+ return code, f"{fn!r} {mention_inflected} {substring!r}"
+
+
+def is_cygwincc(cc):
+ """Try to determine if the compiler that would be used is from cygwin."""
+ out_string = check_output(shlex.split(cc) + ['-dumpmachine'])
+ return out_string.strip().endswith(b'cygwin')
+
+
+get_versions = None
+"""
+A stand-in for the previous get_versions() function to prevent failures
+when monkeypatched. See pypa/setuptools#2969.
+"""
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/errors.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/errors.py
new file mode 100644
index 0000000..0132859
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/errors.py
@@ -0,0 +1,24 @@
+class Error(Exception):
+ """Some compile/link operation failed."""
+
+
+class PreprocessError(Error):
+ """Failure to preprocess one or more C/C++ files."""
+
+
+class CompileError(Error):
+ """Failure to compile one or more C/C++ source files."""
+
+
+class LibError(Error):
+ """Failure to create a static library from one or more C/C++ object
+ files."""
+
+
+class LinkError(Error):
+ """Failure to link one or more C/C++ object files into an executable
+ or shared library file."""
+
+
+class UnknownFileType(Error):
+ """Attempt to process an unknown file type."""
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/msvc.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/msvc.py
new file mode 100644
index 0000000..6db062a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/msvc.py
@@ -0,0 +1,614 @@
+"""distutils._msvccompiler
+
+Contains MSVCCompiler, an implementation of the abstract CCompiler class
+for Microsoft Visual Studio 2015.
+
+This module requires VS 2015 or later.
+"""
+
+# Written by Perry Stoll
+# hacked by Robin Becker and Thomas Heller to do a better job of
+# finding DevStudio (through the registry)
+# ported to VS 2005 and VS 2008 by Christian Heimes
+# ported to VS 2015 by Steve Dower
+from __future__ import annotations
+
+import contextlib
+import os
+import subprocess
+import unittest.mock as mock
+import warnings
+from collections.abc import Iterable
+
+with contextlib.suppress(ImportError):
+ import winreg
+
+from itertools import count
+
+from ..._log import log
+from ...errors import (
+ DistutilsExecError,
+ DistutilsPlatformError,
+)
+from ...util import get_host_platform, get_platform
+from . import base
+from .base import gen_lib_options
+from .errors import (
+ CompileError,
+ LibError,
+ LinkError,
+)
+
+
+def _find_vc2015():
+ try:
+ key = winreg.OpenKeyEx(
+ winreg.HKEY_LOCAL_MACHINE,
+ r"Software\Microsoft\VisualStudio\SxS\VC7",
+ access=winreg.KEY_READ | winreg.KEY_WOW64_32KEY,
+ )
+ except OSError:
+ log.debug("Visual C++ is not registered")
+ return None, None
+
+ best_version = 0
+ best_dir = None
+ with key:
+ for i in count():
+ try:
+ v, vc_dir, vt = winreg.EnumValue(key, i)
+ except OSError:
+ break
+ if v and vt == winreg.REG_SZ and os.path.isdir(vc_dir):
+ try:
+ version = int(float(v))
+ except (ValueError, TypeError):
+ continue
+ if version >= 14 and version > best_version:
+ best_version, best_dir = version, vc_dir
+ return best_version, best_dir
+
+
+def _find_vc2017():
+ """Returns "15, path" based on the result of invoking vswhere.exe
+ If no install is found, returns "None, None"
+
+ The version is returned to avoid unnecessarily changing the function
+ result. It may be ignored when the path is not None.
+
+ If vswhere.exe is not available, by definition, VS 2017 is not
+ installed.
+ """
+ root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles")
+ if not root:
+ return None, None
+
+ variant = 'arm64' if get_platform() == 'win-arm64' else 'x86.x64'
+ suitable_components = (
+ f"Microsoft.VisualStudio.Component.VC.Tools.{variant}",
+ "Microsoft.VisualStudio.Workload.WDExpress",
+ )
+
+ for component in suitable_components:
+ # Workaround for `-requiresAny` (only available on VS 2017 > 15.6)
+ with contextlib.suppress(
+ subprocess.CalledProcessError, OSError, UnicodeDecodeError
+ ):
+ path = (
+ subprocess.check_output([
+ os.path.join(
+ root, "Microsoft Visual Studio", "Installer", "vswhere.exe"
+ ),
+ "-latest",
+ "-prerelease",
+ "-requires",
+ component,
+ "-property",
+ "installationPath",
+ "-products",
+ "*",
+ ])
+ .decode(encoding="mbcs", errors="strict")
+ .strip()
+ )
+
+ path = os.path.join(path, "VC", "Auxiliary", "Build")
+ if os.path.isdir(path):
+ return 15, path
+
+ return None, None # no suitable component found
+
+
+PLAT_SPEC_TO_RUNTIME = {
+ 'x86': 'x86',
+ 'x86_amd64': 'x64',
+ 'x86_arm': 'arm',
+ 'x86_arm64': 'arm64',
+}
+
+
+def _find_vcvarsall(plat_spec):
+ # bpo-38597: Removed vcruntime return value
+ _, best_dir = _find_vc2017()
+
+ if not best_dir:
+ best_version, best_dir = _find_vc2015()
+
+ if not best_dir:
+ log.debug("No suitable Visual C++ version found")
+ return None, None
+
+ vcvarsall = os.path.join(best_dir, "vcvarsall.bat")
+ if not os.path.isfile(vcvarsall):
+ log.debug("%s cannot be found", vcvarsall)
+ return None, None
+
+ return vcvarsall, None
+
+
+def _get_vc_env(plat_spec):
+ if os.getenv("DISTUTILS_USE_SDK"):
+ return {key.lower(): value for key, value in os.environ.items()}
+
+ vcvarsall, _ = _find_vcvarsall(plat_spec)
+ if not vcvarsall:
+ raise DistutilsPlatformError(
+ 'Microsoft Visual C++ 14.0 or greater is required. '
+ 'Get it with "Microsoft C++ Build Tools": '
+ 'https://visualstudio.microsoft.com/visual-cpp-build-tools/'
+ )
+
+ try:
+ out = subprocess.check_output(
+ f'cmd /u /c "{vcvarsall}" {plat_spec} && set',
+ stderr=subprocess.STDOUT,
+ ).decode('utf-16le', errors='replace')
+ except subprocess.CalledProcessError as exc:
+ log.error(exc.output)
+ raise DistutilsPlatformError(f"Error executing {exc.cmd}")
+
+ env = {
+ key.lower(): value
+ for key, _, value in (line.partition('=') for line in out.splitlines())
+ if key and value
+ }
+
+ return env
+
+
+def _find_exe(exe, paths=None):
+ """Return path to an MSVC executable program.
+
+ Tries to find the program in several places: first, one of the
+ MSVC program search paths from the registry; next, the directories
+ in the PATH environment variable. If any of those work, return an
+ absolute path that is known to exist. If none of them work, just
+ return the original program name, 'exe'.
+ """
+ if not paths:
+ paths = os.getenv('path').split(os.pathsep)
+ for p in paths:
+ fn = os.path.join(os.path.abspath(p), exe)
+ if os.path.isfile(fn):
+ return fn
+ return exe
+
+
+_vcvars_names = {
+ 'win32': 'x86',
+ 'win-amd64': 'amd64',
+ 'win-arm32': 'arm',
+ 'win-arm64': 'arm64',
+}
+
+
+def _get_vcvars_spec(host_platform, platform):
+ """
+ Given a host platform and platform, determine the spec for vcvarsall.
+
+ Uses the native MSVC host if the host platform would need expensive
+ emulation for x86.
+
+ >>> _get_vcvars_spec('win-arm64', 'win32')
+ 'arm64_x86'
+ >>> _get_vcvars_spec('win-arm64', 'win-amd64')
+ 'arm64_amd64'
+
+ Otherwise, always cross-compile from x86 to work with the
+ lighter-weight MSVC installs that do not include native 64-bit tools.
+
+ >>> _get_vcvars_spec('win32', 'win32')
+ 'x86'
+ >>> _get_vcvars_spec('win-arm32', 'win-arm32')
+ 'x86_arm'
+ >>> _get_vcvars_spec('win-amd64', 'win-arm64')
+ 'x86_arm64'
+ """
+ if host_platform != 'win-arm64':
+ host_platform = 'win32'
+ vc_hp = _vcvars_names[host_platform]
+ vc_plat = _vcvars_names[platform]
+ return vc_hp if vc_hp == vc_plat else f'{vc_hp}_{vc_plat}'
+
+
+class Compiler(base.Compiler):
+ """Concrete class that implements an interface to Microsoft Visual C++,
+ as defined by the CCompiler abstract class."""
+
+ compiler_type = 'msvc'
+
+ # Just set this so CCompiler's constructor doesn't barf. We currently
+ # don't use the 'set_executables()' bureaucracy provided by CCompiler,
+ # as it really isn't necessary for this sort of single-compiler class.
+ # Would be nice to have a consistent interface with UnixCCompiler,
+ # though, so it's worth thinking about.
+ executables = {}
+
+ # Private class data (need to distinguish C from C++ source for compiler)
+ _c_extensions = ['.c']
+ _cpp_extensions = ['.cc', '.cpp', '.cxx']
+ _rc_extensions = ['.rc']
+ _mc_extensions = ['.mc']
+
+ # Needed for the filename generation methods provided by the
+ # base class, CCompiler.
+ src_extensions = _c_extensions + _cpp_extensions + _rc_extensions + _mc_extensions
+ res_extension = '.res'
+ obj_extension = '.obj'
+ static_lib_extension = '.lib'
+ shared_lib_extension = '.dll'
+ static_lib_format = shared_lib_format = '%s%s'
+ exe_extension = '.exe'
+
+ def __init__(self, verbose=False, dry_run=False, force=False) -> None:
+ super().__init__(verbose, dry_run, force)
+ # target platform (.plat_name is consistent with 'bdist')
+ self.plat_name = None
+ self.initialized = False
+
+ @classmethod
+ def _configure(cls, vc_env):
+ """
+ Set class-level include/lib dirs.
+ """
+ cls.include_dirs = cls._parse_path(vc_env.get('include', ''))
+ cls.library_dirs = cls._parse_path(vc_env.get('lib', ''))
+
+ @staticmethod
+ def _parse_path(val):
+ return [dir.rstrip(os.sep) for dir in val.split(os.pathsep) if dir]
+
+ def initialize(self, plat_name: str | None = None) -> None:
+ # multi-init means we would need to check platform same each time...
+ assert not self.initialized, "don't init multiple times"
+ if plat_name is None:
+ plat_name = get_platform()
+ # sanity check for platforms to prevent obscure errors later.
+ if plat_name not in _vcvars_names:
+ raise DistutilsPlatformError(
+ f"--plat-name must be one of {tuple(_vcvars_names)}"
+ )
+
+ plat_spec = _get_vcvars_spec(get_host_platform(), plat_name)
+
+ vc_env = _get_vc_env(plat_spec)
+ if not vc_env:
+ raise DistutilsPlatformError(
+ "Unable to find a compatible Visual Studio installation."
+ )
+ self._configure(vc_env)
+
+ self._paths = vc_env.get('path', '')
+ paths = self._paths.split(os.pathsep)
+ self.cc = _find_exe("cl.exe", paths)
+ self.linker = _find_exe("link.exe", paths)
+ self.lib = _find_exe("lib.exe", paths)
+ self.rc = _find_exe("rc.exe", paths) # resource compiler
+ self.mc = _find_exe("mc.exe", paths) # message compiler
+ self.mt = _find_exe("mt.exe", paths) # message compiler
+
+ self.preprocess_options = None
+ # bpo-38597: Always compile with dynamic linking
+ # Future releases of Python 3.x will include all past
+ # versions of vcruntime*.dll for compatibility.
+ self.compile_options = ['/nologo', '/O2', '/W3', '/GL', '/DNDEBUG', '/MD']
+
+ self.compile_options_debug = [
+ '/nologo',
+ '/Od',
+ '/MDd',
+ '/Zi',
+ '/W3',
+ '/D_DEBUG',
+ ]
+
+ ldflags = ['/nologo', '/INCREMENTAL:NO', '/LTCG']
+
+ ldflags_debug = ['/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL']
+
+ self.ldflags_exe = [*ldflags, '/MANIFEST:EMBED,ID=1']
+ self.ldflags_exe_debug = [*ldflags_debug, '/MANIFEST:EMBED,ID=1']
+ self.ldflags_shared = [
+ *ldflags,
+ '/DLL',
+ '/MANIFEST:EMBED,ID=2',
+ '/MANIFESTUAC:NO',
+ ]
+ self.ldflags_shared_debug = [
+ *ldflags_debug,
+ '/DLL',
+ '/MANIFEST:EMBED,ID=2',
+ '/MANIFESTUAC:NO',
+ ]
+ self.ldflags_static = [*ldflags]
+ self.ldflags_static_debug = [*ldflags_debug]
+
+ self._ldflags = {
+ (base.Compiler.EXECUTABLE, None): self.ldflags_exe,
+ (base.Compiler.EXECUTABLE, False): self.ldflags_exe,
+ (base.Compiler.EXECUTABLE, True): self.ldflags_exe_debug,
+ (base.Compiler.SHARED_OBJECT, None): self.ldflags_shared,
+ (base.Compiler.SHARED_OBJECT, False): self.ldflags_shared,
+ (base.Compiler.SHARED_OBJECT, True): self.ldflags_shared_debug,
+ (base.Compiler.SHARED_LIBRARY, None): self.ldflags_static,
+ (base.Compiler.SHARED_LIBRARY, False): self.ldflags_static,
+ (base.Compiler.SHARED_LIBRARY, True): self.ldflags_static_debug,
+ }
+
+ self.initialized = True
+
+ # -- Worker methods ------------------------------------------------
+
+ @property
+ def out_extensions(self) -> dict[str, str]:
+ return {
+ **super().out_extensions,
+ **{
+ ext: self.res_extension
+ for ext in self._rc_extensions + self._mc_extensions
+ },
+ }
+
+ def compile( # noqa: C901
+ self,
+ sources,
+ output_dir=None,
+ macros=None,
+ include_dirs=None,
+ debug=False,
+ extra_preargs=None,
+ extra_postargs=None,
+ depends=None,
+ ):
+ if not self.initialized:
+ self.initialize()
+ compile_info = self._setup_compile(
+ output_dir, macros, include_dirs, sources, depends, extra_postargs
+ )
+ macros, objects, extra_postargs, pp_opts, build = compile_info
+
+ compile_opts = extra_preargs or []
+ compile_opts.append('/c')
+ if debug:
+ compile_opts.extend(self.compile_options_debug)
+ else:
+ compile_opts.extend(self.compile_options)
+
+ add_cpp_opts = False
+
+ for obj in objects:
+ try:
+ src, ext = build[obj]
+ except KeyError:
+ continue
+ if debug:
+ # pass the full pathname to MSVC in debug mode,
+ # this allows the debugger to find the source file
+ # without asking the user to browse for it
+ src = os.path.abspath(src)
+
+ if ext in self._c_extensions:
+ input_opt = f"/Tc{src}"
+ elif ext in self._cpp_extensions:
+ input_opt = f"/Tp{src}"
+ add_cpp_opts = True
+ elif ext in self._rc_extensions:
+ # compile .RC to .RES file
+ input_opt = src
+ output_opt = "/fo" + obj
+ try:
+ self.spawn([self.rc] + pp_opts + [output_opt, input_opt])
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
+ continue
+ elif ext in self._mc_extensions:
+ # Compile .MC to .RC file to .RES file.
+ # * '-h dir' specifies the directory for the
+ # generated include file
+ # * '-r dir' specifies the target directory of the
+ # generated RC file and the binary message resource
+ # it includes
+ #
+ # For now (since there are no options to change this),
+ # we use the source-directory for the include file and
+ # the build directory for the RC file and message
+ # resources. This works at least for win32all.
+ h_dir = os.path.dirname(src)
+ rc_dir = os.path.dirname(obj)
+ try:
+ # first compile .MC to .RC and .H file
+ self.spawn([self.mc, '-h', h_dir, '-r', rc_dir, src])
+ base, _ = os.path.splitext(os.path.basename(src))
+ rc_file = os.path.join(rc_dir, base + '.rc')
+ # then compile .RC to .RES file
+ self.spawn([self.rc, "/fo" + obj, rc_file])
+
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
+ continue
+ else:
+ # how to handle this file?
+ raise CompileError(f"Don't know how to compile {src} to {obj}")
+
+ args = [self.cc] + compile_opts + pp_opts
+ if add_cpp_opts:
+ args.append('/EHsc')
+ args.extend((input_opt, "/Fo" + obj))
+ args.extend(extra_postargs)
+
+ try:
+ self.spawn(args)
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
+
+ return objects
+
+ def create_static_lib(
+ self,
+ objects: list[str] | tuple[str, ...],
+ output_libname: str,
+ output_dir: str | None = None,
+ debug: bool = False,
+ target_lang: str | None = None,
+ ) -> None:
+ if not self.initialized:
+ self.initialize()
+ objects, output_dir = self._fix_object_args(objects, output_dir)
+ output_filename = self.library_filename(output_libname, output_dir=output_dir)
+
+ if self._need_link(objects, output_filename):
+ lib_args = objects + ['/OUT:' + output_filename]
+ if debug:
+ pass # XXX what goes here?
+ try:
+ log.debug('Executing "%s" %s', self.lib, ' '.join(lib_args))
+ self.spawn([self.lib] + lib_args)
+ except DistutilsExecError as msg:
+ raise LibError(msg)
+ else:
+ log.debug("skipping %s (up-to-date)", output_filename)
+
+ def link(
+ self,
+ target_desc: str,
+ objects: list[str] | tuple[str, ...],
+ output_filename: str,
+ output_dir: str | None = None,
+ libraries: list[str] | tuple[str, ...] | None = None,
+ library_dirs: list[str] | tuple[str, ...] | None = None,
+ runtime_library_dirs: list[str] | tuple[str, ...] | None = None,
+ export_symbols: Iterable[str] | None = None,
+ debug: bool = False,
+ extra_preargs: list[str] | None = None,
+ extra_postargs: Iterable[str] | None = None,
+ build_temp: str | os.PathLike[str] | None = None,
+ target_lang: str | None = None,
+ ) -> None:
+ if not self.initialized:
+ self.initialize()
+ objects, output_dir = self._fix_object_args(objects, output_dir)
+ fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
+ libraries, library_dirs, runtime_library_dirs = fixed_args
+
+ if runtime_library_dirs:
+ self.warn(
+ "I don't know what to do with 'runtime_library_dirs': "
+ + str(runtime_library_dirs)
+ )
+
+ lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries)
+ if output_dir is not None:
+ output_filename = os.path.join(output_dir, output_filename)
+
+ if self._need_link(objects, output_filename):
+ ldflags = self._ldflags[target_desc, debug]
+
+ export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])]
+
+ ld_args = (
+ ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]
+ )
+
+ # The MSVC linker generates .lib and .exp files, which cannot be
+ # suppressed by any linker switches. The .lib files may even be
+ # needed! Make sure they are generated in the temporary build
+ # directory. Since they have different names for debug and release
+ # builds, they can go into the same directory.
+ build_temp = os.path.dirname(objects[0])
+ if export_symbols is not None:
+ (dll_name, dll_ext) = os.path.splitext(
+ os.path.basename(output_filename)
+ )
+ implib_file = os.path.join(build_temp, self.library_filename(dll_name))
+ ld_args.append('/IMPLIB:' + implib_file)
+
+ if extra_preargs:
+ ld_args[:0] = extra_preargs
+ if extra_postargs:
+ ld_args.extend(extra_postargs)
+
+ output_dir = os.path.dirname(os.path.abspath(output_filename))
+ self.mkpath(output_dir)
+ try:
+ log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args))
+ self.spawn([self.linker] + ld_args)
+ except DistutilsExecError as msg:
+ raise LinkError(msg)
+ else:
+ log.debug("skipping %s (up-to-date)", output_filename)
+
+ def spawn(self, cmd):
+ env = dict(os.environ, PATH=self._paths)
+ with self._fallback_spawn(cmd, env) as fallback:
+ return super().spawn(cmd, env=env)
+ return fallback.value
+
+ @contextlib.contextmanager
+ def _fallback_spawn(self, cmd, env):
+ """
+ Discovered in pypa/distutils#15, some tools monkeypatch the compiler,
+ so the 'env' kwarg causes a TypeError. Detect this condition and
+ restore the legacy, unsafe behavior.
+ """
+ bag = type('Bag', (), {})()
+ try:
+ yield bag
+ except TypeError as exc:
+ if "unexpected keyword argument 'env'" not in str(exc):
+ raise
+ else:
+ return
+ warnings.warn("Fallback spawn triggered. Please update distutils monkeypatch.")
+ with mock.patch.dict('os.environ', env):
+ bag.value = super().spawn(cmd)
+
+ # -- Miscellaneous methods -----------------------------------------
+ # These are all used by the 'gen_lib_options() function, in
+ # ccompiler.py.
+
+ def library_dir_option(self, dir):
+ return "/LIBPATH:" + dir
+
+ def runtime_library_dir_option(self, dir):
+ raise DistutilsPlatformError(
+ "don't know how to set runtime library search path for MSVC"
+ )
+
+ def library_option(self, lib):
+ return self.library_filename(lib)
+
+ def find_library_file(self, dirs, lib, debug=False):
+ # Prefer a debugging library if found (and requested), but deal
+ # with it if we don't have one.
+ if debug:
+ try_names = [lib + "_d", lib]
+ else:
+ try_names = [lib]
+ for dir in dirs:
+ for name in try_names:
+ libfile = os.path.join(dir, self.library_filename(name))
+ if os.path.isfile(libfile):
+ return libfile
+ else:
+ # Oops, didn't find it in *any* of 'dirs'
+ return None
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_base.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_base.cpython-312.pyc
new file mode 100644
index 0000000..9c9a1d6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_base.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_cygwin.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_cygwin.cpython-312.pyc
new file mode 100644
index 0000000..666a045
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_cygwin.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_mingw.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_mingw.cpython-312.pyc
new file mode 100644
index 0000000..7199e95
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_mingw.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_msvc.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_msvc.cpython-312.pyc
new file mode 100644
index 0000000..fe1e8fd
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_msvc.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_unix.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_unix.cpython-312.pyc
new file mode 100644
index 0000000..ee72ce2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/__pycache__/test_unix.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_base.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_base.py
new file mode 100644
index 0000000..a762e2b
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_base.py
@@ -0,0 +1,83 @@
+import platform
+import sysconfig
+import textwrap
+
+import pytest
+
+from .. import base
+
+pytestmark = pytest.mark.usefixtures('suppress_path_mangle')
+
+
+@pytest.fixture
+def c_file(tmp_path):
+ c_file = tmp_path / 'foo.c'
+ gen_headers = ('Python.h',)
+ is_windows = platform.system() == "Windows"
+ plat_headers = ('windows.h',) * is_windows
+ all_headers = gen_headers + plat_headers
+ headers = '\n'.join(f'#include <{header}>\n' for header in all_headers)
+ payload = (
+ textwrap.dedent(
+ """
+ #headers
+ void PyInit_foo(void) {}
+ """
+ )
+ .lstrip()
+ .replace('#headers', headers)
+ )
+ c_file.write_text(payload, encoding='utf-8')
+ return c_file
+
+
+def test_set_include_dirs(c_file):
+ """
+ Extensions should build even if set_include_dirs is invoked.
+ In particular, compiler-specific paths should not be overridden.
+ """
+ compiler = base.new_compiler()
+ python = sysconfig.get_paths()['include']
+ compiler.set_include_dirs([python])
+ compiler.compile([c_file])
+
+ # do it again, setting include dirs after any initialization
+ compiler.set_include_dirs([python])
+ compiler.compile([c_file])
+
+
+def test_has_function_prototype():
+ # Issue https://github.com/pypa/setuptools/issues/3648
+ # Test prototype-generating behavior.
+
+ compiler = base.new_compiler()
+
+ # Every C implementation should have these.
+ assert compiler.has_function('abort')
+ assert compiler.has_function('exit')
+ with pytest.deprecated_call(match='includes is deprecated'):
+ # abort() is a valid expression with the prototype.
+ assert compiler.has_function('abort', includes=['stdlib.h'])
+ with pytest.deprecated_call(match='includes is deprecated'):
+ # But exit() is not valid with the actual prototype in scope.
+ assert not compiler.has_function('exit', includes=['stdlib.h'])
+ # And setuptools_does_not_exist is not declared or defined at all.
+ assert not compiler.has_function('setuptools_does_not_exist')
+ with pytest.deprecated_call(match='includes is deprecated'):
+ assert not compiler.has_function(
+ 'setuptools_does_not_exist', includes=['stdio.h']
+ )
+
+
+def test_include_dirs_after_multiple_compile_calls(c_file):
+ """
+ Calling compile multiple times should not change the include dirs
+ (regression test for setuptools issue #3591).
+ """
+ compiler = base.new_compiler()
+ python = sysconfig.get_paths()['include']
+ compiler.set_include_dirs([python])
+ compiler.compile([c_file])
+ assert compiler.include_dirs == [python]
+ compiler.compile([c_file])
+ assert compiler.include_dirs == [python]
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_cygwin.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_cygwin.py
new file mode 100644
index 0000000..9adf6b8
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_cygwin.py
@@ -0,0 +1,76 @@
+"""Tests for distutils.cygwinccompiler."""
+
+import os
+import sys
+from distutils import sysconfig
+from distutils.tests import support
+
+import pytest
+
+from .. import cygwin
+
+
+@pytest.fixture(autouse=True)
+def stuff(request, monkeypatch, distutils_managed_tempdir):
+ self = request.instance
+ self.python_h = os.path.join(self.mkdtemp(), 'python.h')
+ monkeypatch.setattr(sysconfig, 'get_config_h_filename', self._get_config_h_filename)
+ monkeypatch.setattr(sys, 'version', sys.version)
+
+
+class TestCygwinCCompiler(support.TempdirManager):
+ def _get_config_h_filename(self):
+ return self.python_h
+
+ @pytest.mark.skipif('sys.platform != "cygwin"')
+ @pytest.mark.skipif('not os.path.exists("/usr/lib/libbash.dll.a")')
+ def test_find_library_file(self):
+ from distutils.cygwinccompiler import CygwinCCompiler
+
+ compiler = CygwinCCompiler()
+ link_name = "bash"
+ linkable_file = compiler.find_library_file(["/usr/lib"], link_name)
+ assert linkable_file is not None
+ assert os.path.exists(linkable_file)
+ assert linkable_file == f"/usr/lib/lib{link_name:s}.dll.a"
+
+ @pytest.mark.skipif('sys.platform != "cygwin"')
+ def test_runtime_library_dir_option(self):
+ from distutils.cygwinccompiler import CygwinCCompiler
+
+ compiler = CygwinCCompiler()
+ assert compiler.runtime_library_dir_option('/foo') == []
+
+ def test_check_config_h(self):
+ # check_config_h looks for "GCC" in sys.version first
+ # returns CONFIG_H_OK if found
+ sys.version = (
+ '2.6.1 (r261:67515, Dec 6 2008, 16:42:21) \n[GCC '
+ '4.0.1 (Apple Computer, Inc. build 5370)]'
+ )
+
+ assert cygwin.check_config_h()[0] == cygwin.CONFIG_H_OK
+
+ # then it tries to see if it can find "__GNUC__" in pyconfig.h
+ sys.version = 'something without the *CC word'
+
+ # if the file doesn't exist it returns CONFIG_H_UNCERTAIN
+ assert cygwin.check_config_h()[0] == cygwin.CONFIG_H_UNCERTAIN
+
+ # if it exists but does not contain __GNUC__, it returns CONFIG_H_NOTOK
+ self.write_file(self.python_h, 'xxx')
+ assert cygwin.check_config_h()[0] == cygwin.CONFIG_H_NOTOK
+
+ # and CONFIG_H_OK if __GNUC__ is found
+ self.write_file(self.python_h, 'xxx __GNUC__ xxx')
+ assert cygwin.check_config_h()[0] == cygwin.CONFIG_H_OK
+
+ def test_get_msvcr(self):
+ assert cygwin.get_msvcr() == []
+
+ @pytest.mark.skipif('sys.platform != "cygwin"')
+ def test_dll_libraries_not_none(self):
+ from distutils.cygwinccompiler import CygwinCCompiler
+
+ compiler = CygwinCCompiler()
+ assert compiler.dll_libraries is not None
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_mingw.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_mingw.py
new file mode 100644
index 0000000..dc45687
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_mingw.py
@@ -0,0 +1,48 @@
+from distutils import sysconfig
+from distutils.errors import DistutilsPlatformError
+from distutils.util import is_mingw, split_quoted
+
+import pytest
+
+from .. import cygwin, errors
+
+
+class TestMinGW32Compiler:
+ @pytest.mark.skipif(not is_mingw(), reason='not on mingw')
+ def test_compiler_type(self):
+ compiler = cygwin.MinGW32Compiler()
+ assert compiler.compiler_type == 'mingw32'
+
+ @pytest.mark.skipif(not is_mingw(), reason='not on mingw')
+ def test_set_executables(self, monkeypatch):
+ monkeypatch.setenv('CC', 'cc')
+ monkeypatch.setenv('CXX', 'c++')
+
+ compiler = cygwin.MinGW32Compiler()
+
+ assert compiler.compiler == split_quoted('cc -O -Wall')
+ assert compiler.compiler_so == split_quoted('cc -shared -O -Wall')
+ assert compiler.compiler_cxx == split_quoted('c++ -O -Wall')
+ assert compiler.linker_exe == split_quoted('cc')
+ assert compiler.linker_so == split_quoted('cc -shared')
+
+ @pytest.mark.skipif(not is_mingw(), reason='not on mingw')
+ def test_runtime_library_dir_option(self):
+ compiler = cygwin.MinGW32Compiler()
+ with pytest.raises(DistutilsPlatformError):
+ compiler.runtime_library_dir_option('/usr/lib')
+
+ @pytest.mark.skipif(not is_mingw(), reason='not on mingw')
+ def test_cygwincc_error(self, monkeypatch):
+ monkeypatch.setattr(cygwin, 'is_cygwincc', lambda _: True)
+
+ with pytest.raises(errors.Error):
+ cygwin.MinGW32Compiler()
+
+ @pytest.mark.skipif('sys.platform == "cygwin"')
+ def test_customize_compiler_with_msvc_python(self):
+ # In case we have an MSVC Python build, but still want to use
+ # MinGW32Compiler, then customize_compiler() shouldn't fail at least.
+ # https://github.com/pypa/setuptools/issues/4456
+ compiler = cygwin.MinGW32Compiler()
+ sysconfig.customize_compiler(compiler)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_msvc.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_msvc.py
new file mode 100644
index 0000000..eca8319
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_msvc.py
@@ -0,0 +1,136 @@
+import os
+import sys
+import sysconfig
+import threading
+import unittest.mock as mock
+from distutils.errors import DistutilsPlatformError
+from distutils.tests import support
+from distutils.util import get_platform
+
+import pytest
+
+from .. import msvc
+
+needs_winreg = pytest.mark.skipif('not hasattr(msvc, "winreg")')
+
+
+class Testmsvccompiler(support.TempdirManager):
+ def test_no_compiler(self, monkeypatch):
+ # makes sure query_vcvarsall raises
+ # a DistutilsPlatformError if the compiler
+ # is not found
+ def _find_vcvarsall(plat_spec):
+ return None, None
+
+ monkeypatch.setattr(msvc, '_find_vcvarsall', _find_vcvarsall)
+
+ with pytest.raises(DistutilsPlatformError):
+ msvc._get_vc_env(
+ 'wont find this version',
+ )
+
+ @pytest.mark.skipif(
+ not sysconfig.get_platform().startswith("win"),
+ reason="Only run test for non-mingw Windows platforms",
+ )
+ @pytest.mark.parametrize(
+ "plat_name, expected",
+ [
+ ("win-arm64", "win-arm64"),
+ ("win-amd64", "win-amd64"),
+ (None, get_platform()),
+ ],
+ )
+ def test_cross_platform_compilation_paths(self, monkeypatch, plat_name, expected):
+ """
+ Ensure a specified target platform is passed to _get_vcvars_spec.
+ """
+ compiler = msvc.Compiler()
+
+ def _get_vcvars_spec(host_platform, platform):
+ assert platform == expected
+
+ monkeypatch.setattr(msvc, '_get_vcvars_spec', _get_vcvars_spec)
+ compiler.initialize(plat_name)
+
+ @needs_winreg
+ def test_get_vc_env_unicode(self):
+ test_var = 'ṰḖṤṪ┅ṼẨṜ'
+ test_value = '₃⁴₅'
+
+ # Ensure we don't early exit from _get_vc_env
+ old_distutils_use_sdk = os.environ.pop('DISTUTILS_USE_SDK', None)
+ os.environ[test_var] = test_value
+ try:
+ env = msvc._get_vc_env('x86')
+ assert test_var.lower() in env
+ assert test_value == env[test_var.lower()]
+ finally:
+ os.environ.pop(test_var)
+ if old_distutils_use_sdk:
+ os.environ['DISTUTILS_USE_SDK'] = old_distutils_use_sdk
+
+ @needs_winreg
+ @pytest.mark.parametrize('ver', (2015, 2017))
+ def test_get_vc(self, ver):
+ # This function cannot be mocked, so pass if VC is found
+ # and skip otherwise.
+ lookup = getattr(msvc, f'_find_vc{ver}')
+ expected_version = {2015: 14, 2017: 15}[ver]
+ version, path = lookup()
+ if not version:
+ pytest.skip(f"VS {ver} is not installed")
+ assert version >= expected_version
+ assert os.path.isdir(path)
+
+
+class CheckThread(threading.Thread):
+ exc_info = None
+
+ def run(self):
+ try:
+ super().run()
+ except Exception:
+ self.exc_info = sys.exc_info()
+
+ def __bool__(self):
+ return not self.exc_info
+
+
+class TestSpawn:
+ def test_concurrent_safe(self):
+ """
+ Concurrent calls to spawn should have consistent results.
+ """
+ compiler = msvc.Compiler()
+ compiler._paths = "expected"
+ inner_cmd = 'import os; assert os.environ["PATH"] == "expected"'
+ command = [sys.executable, '-c', inner_cmd]
+
+ threads = [
+ CheckThread(target=compiler.spawn, args=[command]) for n in range(100)
+ ]
+ for thread in threads:
+ thread.start()
+ for thread in threads:
+ thread.join()
+ assert all(threads)
+
+ def test_concurrent_safe_fallback(self):
+ """
+ If CCompiler.spawn has been monkey-patched without support
+ for an env, it should still execute.
+ """
+ from distutils import ccompiler
+
+ compiler = msvc.Compiler()
+ compiler._paths = "expected"
+
+ def CCompiler_spawn(self, cmd):
+ "A spawn without an env argument."
+ assert os.environ["PATH"] == "expected"
+
+ with mock.patch.object(ccompiler.CCompiler, 'spawn', CCompiler_spawn):
+ compiler.spawn(["n/a"])
+
+ assert os.environ.get("PATH") != "expected"
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_unix.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_unix.py
new file mode 100644
index 0000000..f4e2898
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_unix.py
@@ -0,0 +1,350 @@
+"""Tests for distutils.unixccompiler."""
+
+import os
+import sys
+import unittest.mock as mock
+from distutils import sysconfig
+from distutils.compat import consolidate_linker_args
+from distutils.errors import DistutilsPlatformError
+from distutils.tests import support
+from distutils.tests.compat.py39 import EnvironmentVarGuard
+from distutils.util import _clear_cached_macosx_ver
+
+import pytest
+
+from .. import unix
+
+
+@pytest.fixture(autouse=True)
+def save_values(monkeypatch):
+ monkeypatch.setattr(sys, 'platform', sys.platform)
+ monkeypatch.setattr(sysconfig, 'get_config_var', sysconfig.get_config_var)
+ monkeypatch.setattr(sysconfig, 'get_config_vars', sysconfig.get_config_vars)
+
+
+@pytest.fixture(autouse=True)
+def compiler_wrapper(request):
+ class CompilerWrapper(unix.Compiler):
+ def rpath_foo(self):
+ return self.runtime_library_dir_option('/foo')
+
+ request.instance.cc = CompilerWrapper()
+
+
+class TestUnixCCompiler(support.TempdirManager):
+ @pytest.mark.skipif('platform.system == "Windows"')
+ def test_runtime_libdir_option(self): # noqa: C901
+ # Issue #5900; GitHub Issue #37
+ #
+ # Ensure RUNPATH is added to extension modules with RPATH if
+ # GNU ld is used
+
+ # darwin
+ sys.platform = 'darwin'
+ darwin_ver_var = 'MACOSX_DEPLOYMENT_TARGET'
+ darwin_rpath_flag = '-Wl,-rpath,/foo'
+ darwin_lib_flag = '-L/foo'
+
+ # (macOS version from syscfg, macOS version from env var) -> flag
+ # Version value of None generates two tests: as None and as empty string
+ # Expected flag value of None means an mismatch exception is expected
+ darwin_test_cases = [
+ ((None, None), darwin_lib_flag),
+ ((None, '11'), darwin_rpath_flag),
+ (('10', None), darwin_lib_flag),
+ (('10.3', None), darwin_lib_flag),
+ (('10.3.1', None), darwin_lib_flag),
+ (('10.5', None), darwin_rpath_flag),
+ (('10.5.1', None), darwin_rpath_flag),
+ (('10.3', '10.3'), darwin_lib_flag),
+ (('10.3', '10.5'), darwin_rpath_flag),
+ (('10.5', '10.3'), darwin_lib_flag),
+ (('10.5', '11'), darwin_rpath_flag),
+ (('10.4', '10'), None),
+ ]
+
+ def make_darwin_gcv(syscfg_macosx_ver):
+ def gcv(var):
+ if var == darwin_ver_var:
+ return syscfg_macosx_ver
+ return "xxx"
+
+ return gcv
+
+ def do_darwin_test(syscfg_macosx_ver, env_macosx_ver, expected_flag):
+ env = os.environ
+ msg = f"macOS version = (sysconfig={syscfg_macosx_ver!r}, env={env_macosx_ver!r})"
+
+ # Save
+ old_gcv = sysconfig.get_config_var
+ old_env_macosx_ver = env.get(darwin_ver_var)
+
+ # Setup environment
+ _clear_cached_macosx_ver()
+ sysconfig.get_config_var = make_darwin_gcv(syscfg_macosx_ver)
+ if env_macosx_ver is not None:
+ env[darwin_ver_var] = env_macosx_ver
+ elif darwin_ver_var in env:
+ env.pop(darwin_ver_var)
+
+ # Run the test
+ if expected_flag is not None:
+ assert self.cc.rpath_foo() == expected_flag, msg
+ else:
+ with pytest.raises(
+ DistutilsPlatformError, match=darwin_ver_var + r' mismatch'
+ ):
+ self.cc.rpath_foo()
+
+ # Restore
+ if old_env_macosx_ver is not None:
+ env[darwin_ver_var] = old_env_macosx_ver
+ elif darwin_ver_var in env:
+ env.pop(darwin_ver_var)
+ sysconfig.get_config_var = old_gcv
+ _clear_cached_macosx_ver()
+
+ for macosx_vers, expected_flag in darwin_test_cases:
+ syscfg_macosx_ver, env_macosx_ver = macosx_vers
+ do_darwin_test(syscfg_macosx_ver, env_macosx_ver, expected_flag)
+ # Bonus test cases with None interpreted as empty string
+ if syscfg_macosx_ver is None:
+ do_darwin_test("", env_macosx_ver, expected_flag)
+ if env_macosx_ver is None:
+ do_darwin_test(syscfg_macosx_ver, "", expected_flag)
+ if syscfg_macosx_ver is None and env_macosx_ver is None:
+ do_darwin_test("", "", expected_flag)
+
+ old_gcv = sysconfig.get_config_var
+
+ # hp-ux
+ sys.platform = 'hp-ux'
+
+ def gcv(v):
+ return 'xxx'
+
+ sysconfig.get_config_var = gcv
+ assert self.cc.rpath_foo() == ['+s', '-L/foo']
+
+ def gcv(v):
+ return 'gcc'
+
+ sysconfig.get_config_var = gcv
+ assert self.cc.rpath_foo() == ['-Wl,+s', '-L/foo']
+
+ def gcv(v):
+ return 'g++'
+
+ sysconfig.get_config_var = gcv
+ assert self.cc.rpath_foo() == ['-Wl,+s', '-L/foo']
+
+ sysconfig.get_config_var = old_gcv
+
+ # GCC GNULD
+ sys.platform = 'bar'
+
+ def gcv(v):
+ if v == 'CC':
+ return 'gcc'
+ elif v == 'GNULD':
+ return 'yes'
+
+ sysconfig.get_config_var = gcv
+ assert self.cc.rpath_foo() == consolidate_linker_args([
+ '-Wl,--enable-new-dtags',
+ '-Wl,-rpath,/foo',
+ ])
+
+ def gcv(v):
+ if v == 'CC':
+ return 'gcc -pthread -B /bar'
+ elif v == 'GNULD':
+ return 'yes'
+
+ sysconfig.get_config_var = gcv
+ assert self.cc.rpath_foo() == consolidate_linker_args([
+ '-Wl,--enable-new-dtags',
+ '-Wl,-rpath,/foo',
+ ])
+
+ # GCC non-GNULD
+ sys.platform = 'bar'
+
+ def gcv(v):
+ if v == 'CC':
+ return 'gcc'
+ elif v == 'GNULD':
+ return 'no'
+
+ sysconfig.get_config_var = gcv
+ assert self.cc.rpath_foo() == '-Wl,-R/foo'
+
+ # GCC GNULD with fully qualified configuration prefix
+ # see #7617
+ sys.platform = 'bar'
+
+ def gcv(v):
+ if v == 'CC':
+ return 'x86_64-pc-linux-gnu-gcc-4.4.2'
+ elif v == 'GNULD':
+ return 'yes'
+
+ sysconfig.get_config_var = gcv
+ assert self.cc.rpath_foo() == consolidate_linker_args([
+ '-Wl,--enable-new-dtags',
+ '-Wl,-rpath,/foo',
+ ])
+
+ # non-GCC GNULD
+ sys.platform = 'bar'
+
+ def gcv(v):
+ if v == 'CC':
+ return 'cc'
+ elif v == 'GNULD':
+ return 'yes'
+
+ sysconfig.get_config_var = gcv
+ assert self.cc.rpath_foo() == consolidate_linker_args([
+ '-Wl,--enable-new-dtags',
+ '-Wl,-rpath,/foo',
+ ])
+
+ # non-GCC non-GNULD
+ sys.platform = 'bar'
+
+ def gcv(v):
+ if v == 'CC':
+ return 'cc'
+ elif v == 'GNULD':
+ return 'no'
+
+ sysconfig.get_config_var = gcv
+ assert self.cc.rpath_foo() == '-Wl,-R/foo'
+
+ @pytest.mark.skipif('platform.system == "Windows"')
+ def test_cc_overrides_ldshared(self):
+ # Issue #18080:
+ # ensure that setting CC env variable also changes default linker
+ def gcv(v):
+ if v == 'LDSHARED':
+ return 'gcc-4.2 -bundle -undefined dynamic_lookup '
+ return 'gcc-4.2'
+
+ def gcvs(*args, _orig=sysconfig.get_config_vars):
+ if args:
+ return list(map(sysconfig.get_config_var, args))
+ return _orig()
+
+ sysconfig.get_config_var = gcv
+ sysconfig.get_config_vars = gcvs
+ with EnvironmentVarGuard() as env:
+ env['CC'] = 'my_cc'
+ del env['LDSHARED']
+ sysconfig.customize_compiler(self.cc)
+ assert self.cc.linker_so[0] == 'my_cc'
+
+ @pytest.mark.skipif('platform.system == "Windows"')
+ @pytest.mark.usefixtures('disable_macos_customization')
+ def test_cc_overrides_ldshared_for_cxx_correctly(self):
+ """
+ Ensure that setting CC env variable also changes default linker
+ correctly when building C++ extensions.
+
+ pypa/distutils#126
+ """
+
+ def gcv(v):
+ if v == 'LDSHARED':
+ return 'gcc-4.2 -bundle -undefined dynamic_lookup '
+ elif v == 'LDCXXSHARED':
+ return 'g++-4.2 -bundle -undefined dynamic_lookup '
+ elif v == 'CXX':
+ return 'g++-4.2'
+ elif v == 'CC':
+ return 'gcc-4.2'
+ return ''
+
+ def gcvs(*args, _orig=sysconfig.get_config_vars):
+ if args:
+ return list(map(sysconfig.get_config_var, args))
+ return _orig()
+
+ sysconfig.get_config_var = gcv
+ sysconfig.get_config_vars = gcvs
+ with (
+ mock.patch.object(self.cc, 'spawn', return_value=None) as mock_spawn,
+ mock.patch.object(self.cc, '_need_link', return_value=True),
+ mock.patch.object(self.cc, 'mkpath', return_value=None),
+ EnvironmentVarGuard() as env,
+ ):
+ env['CC'] = 'ccache my_cc'
+ env['CXX'] = 'my_cxx'
+ del env['LDSHARED']
+ sysconfig.customize_compiler(self.cc)
+ assert self.cc.linker_so[0:2] == ['ccache', 'my_cc']
+ self.cc.link(None, [], 'a.out', target_lang='c++')
+ call_args = mock_spawn.call_args[0][0]
+ expected = ['my_cxx', '-bundle', '-undefined', 'dynamic_lookup']
+ assert call_args[:4] == expected
+
+ @pytest.mark.skipif('platform.system == "Windows"')
+ def test_explicit_ldshared(self):
+ # Issue #18080:
+ # ensure that setting CC env variable does not change
+ # explicit LDSHARED setting for linker
+ def gcv(v):
+ if v == 'LDSHARED':
+ return 'gcc-4.2 -bundle -undefined dynamic_lookup '
+ return 'gcc-4.2'
+
+ def gcvs(*args, _orig=sysconfig.get_config_vars):
+ if args:
+ return list(map(sysconfig.get_config_var, args))
+ return _orig()
+
+ sysconfig.get_config_var = gcv
+ sysconfig.get_config_vars = gcvs
+ with EnvironmentVarGuard() as env:
+ env['CC'] = 'my_cc'
+ env['LDSHARED'] = 'my_ld -bundle -dynamic'
+ sysconfig.customize_compiler(self.cc)
+ assert self.cc.linker_so[0] == 'my_ld'
+
+ def test_has_function(self):
+ # Issue https://github.com/pypa/distutils/issues/64:
+ # ensure that setting output_dir does not raise
+ # FileNotFoundError: [Errno 2] No such file or directory: 'a.out'
+ self.cc.output_dir = 'scratch'
+ os.chdir(self.mkdtemp())
+ self.cc.has_function('abort')
+
+ def test_find_library_file(self, monkeypatch):
+ compiler = unix.Compiler()
+ compiler._library_root = lambda dir: dir
+ monkeypatch.setattr(os.path, 'exists', lambda d: 'existing' in d)
+
+ libname = 'libabc.dylib' if sys.platform != 'cygwin' else 'cygabc.dll'
+ dirs = ('/foo/bar/missing', '/foo/bar/existing')
+ assert (
+ compiler.find_library_file(dirs, 'abc').replace('\\', '/')
+ == f'/foo/bar/existing/{libname}'
+ )
+ assert (
+ compiler.find_library_file(reversed(dirs), 'abc').replace('\\', '/')
+ == f'/foo/bar/existing/{libname}'
+ )
+
+ monkeypatch.setattr(
+ os.path,
+ 'exists',
+ lambda d: 'existing' in d and '.a' in d and '.dll.a' not in d,
+ )
+ assert (
+ compiler.find_library_file(dirs, 'abc').replace('\\', '/')
+ == '/foo/bar/existing/libabc.a'
+ )
+ assert (
+ compiler.find_library_file(reversed(dirs), 'abc').replace('\\', '/')
+ == '/foo/bar/existing/libabc.a'
+ )
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/unix.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/unix.py
new file mode 100644
index 0000000..e8a53d4
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/unix.py
@@ -0,0 +1,423 @@
+"""distutils.unixccompiler
+
+Contains the UnixCCompiler class, a subclass of CCompiler that handles
+the "typical" Unix-style command-line C compiler:
+ * macros defined with -Dname[=value]
+ * macros undefined with -Uname
+ * include search directories specified with -Idir
+ * libraries specified with -lllib
+ * library search directories specified with -Ldir
+ * compile handled by 'cc' (or similar) executable with -c option:
+ compiles .c to .o
+ * link static library handled by 'ar' command (possibly with 'ranlib')
+ * link shared library handled by 'cc -shared'
+"""
+
+from __future__ import annotations
+
+import itertools
+import os
+import re
+import shlex
+import sys
+from collections.abc import Iterable
+
+from ... import sysconfig
+from ..._log import log
+from ..._macos_compat import compiler_fixup
+from ..._modified import newer
+from ...compat import consolidate_linker_args
+from ...errors import DistutilsExecError
+from . import base
+from .base import _Macro, gen_lib_options, gen_preprocess_options
+from .errors import (
+ CompileError,
+ LibError,
+ LinkError,
+)
+
+# XXX Things not currently handled:
+# * optimization/debug/warning flags; we just use whatever's in Python's
+# Makefile and live with it. Is this adequate? If not, we might
+# have to have a bunch of subclasses GNUCCompiler, SGICCompiler,
+# SunCCompiler, and I suspect down that road lies madness.
+# * even if we don't know a warning flag from an optimization flag,
+# we need some way for outsiders to feed preprocessor/compiler/linker
+# flags in to us -- eg. a sysadmin might want to mandate certain flags
+# via a site config file, or a user might want to set something for
+# compiling this module distribution only via the setup.py command
+# line, whatever. As long as these options come from something on the
+# current system, they can be as system-dependent as they like, and we
+# should just happily stuff them into the preprocessor/compiler/linker
+# options and carry on.
+
+
+def _split_env(cmd):
+ """
+ For macOS, split command into 'env' portion (if any)
+ and the rest of the linker command.
+
+ >>> _split_env(['a', 'b', 'c'])
+ ([], ['a', 'b', 'c'])
+ >>> _split_env(['/usr/bin/env', 'A=3', 'gcc'])
+ (['/usr/bin/env', 'A=3'], ['gcc'])
+ """
+ pivot = 0
+ if os.path.basename(cmd[0]) == "env":
+ pivot = 1
+ while '=' in cmd[pivot]:
+ pivot += 1
+ return cmd[:pivot], cmd[pivot:]
+
+
+def _split_aix(cmd):
+ """
+ AIX platforms prefix the compiler with the ld_so_aix
+ script, so split that from the linker command.
+
+ >>> _split_aix(['a', 'b', 'c'])
+ ([], ['a', 'b', 'c'])
+ >>> _split_aix(['/bin/foo/ld_so_aix', 'gcc'])
+ (['/bin/foo/ld_so_aix'], ['gcc'])
+ """
+ pivot = os.path.basename(cmd[0]) == 'ld_so_aix'
+ return cmd[:pivot], cmd[pivot:]
+
+
+def _linker_params(linker_cmd, compiler_cmd):
+ """
+ The linker command usually begins with the compiler
+ command (possibly multiple elements), followed by zero or more
+ params for shared library building.
+
+ If the LDSHARED env variable overrides the linker command,
+ however, the commands may not match.
+
+ Return the best guess of the linker parameters by stripping
+ the linker command. If the compiler command does not
+ match the linker command, assume the linker command is
+ just the first element.
+
+ >>> _linker_params('gcc foo bar'.split(), ['gcc'])
+ ['foo', 'bar']
+ >>> _linker_params('gcc foo bar'.split(), ['other'])
+ ['foo', 'bar']
+ >>> _linker_params('ccache gcc foo bar'.split(), 'ccache gcc'.split())
+ ['foo', 'bar']
+ >>> _linker_params(['gcc'], ['gcc'])
+ []
+ """
+ c_len = len(compiler_cmd)
+ pivot = c_len if linker_cmd[:c_len] == compiler_cmd else 1
+ return linker_cmd[pivot:]
+
+
+class Compiler(base.Compiler):
+ compiler_type = 'unix'
+
+ # These are used by CCompiler in two places: the constructor sets
+ # instance attributes 'preprocessor', 'compiler', etc. from them, and
+ # 'set_executable()' allows any of these to be set. The defaults here
+ # are pretty generic; they will probably have to be set by an outsider
+ # (eg. using information discovered by the sysconfig about building
+ # Python extensions).
+ executables = {
+ 'preprocessor': None,
+ 'compiler': ["cc"],
+ 'compiler_so': ["cc"],
+ 'compiler_cxx': ["c++"],
+ 'compiler_so_cxx': ["c++"],
+ 'linker_so': ["cc", "-shared"],
+ 'linker_so_cxx': ["c++", "-shared"],
+ 'linker_exe': ["cc"],
+ 'linker_exe_cxx': ["c++", "-shared"],
+ 'archiver': ["ar", "-cr"],
+ 'ranlib': None,
+ }
+
+ if sys.platform[:6] == "darwin":
+ executables['ranlib'] = ["ranlib"]
+
+ # Needed for the filename generation methods provided by the base
+ # class, CCompiler. NB. whoever instantiates/uses a particular
+ # UnixCCompiler instance should set 'shared_lib_ext' -- we set a
+ # reasonable common default here, but it's not necessarily used on all
+ # Unices!
+
+ src_extensions = [".c", ".C", ".cc", ".cxx", ".cpp", ".m"]
+ obj_extension = ".o"
+ static_lib_extension = ".a"
+ shared_lib_extension = ".so"
+ dylib_lib_extension = ".dylib"
+ xcode_stub_lib_extension = ".tbd"
+ static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"
+ xcode_stub_lib_format = dylib_lib_format
+ if sys.platform == "cygwin":
+ exe_extension = ".exe"
+ shared_lib_extension = ".dll.a"
+ dylib_lib_extension = ".dll"
+ dylib_lib_format = "cyg%s%s"
+
+ def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs):
+ """Remove standard library path from rpath"""
+ libraries, library_dirs, runtime_library_dirs = super()._fix_lib_args(
+ libraries, library_dirs, runtime_library_dirs
+ )
+ libdir = sysconfig.get_config_var('LIBDIR')
+ if (
+ runtime_library_dirs
+ and libdir.startswith("/usr/lib")
+ and (libdir in runtime_library_dirs)
+ ):
+ runtime_library_dirs.remove(libdir)
+ return libraries, library_dirs, runtime_library_dirs
+
+ def preprocess(
+ self,
+ source: str | os.PathLike[str],
+ output_file: str | os.PathLike[str] | None = None,
+ macros: list[_Macro] | None = None,
+ include_dirs: list[str] | tuple[str, ...] | None = None,
+ extra_preargs: list[str] | None = None,
+ extra_postargs: Iterable[str] | None = None,
+ ):
+ fixed_args = self._fix_compile_args(None, macros, include_dirs)
+ ignore, macros, include_dirs = fixed_args
+ pp_opts = gen_preprocess_options(macros, include_dirs)
+ pp_args = self.preprocessor + pp_opts
+ if output_file:
+ pp_args.extend(['-o', output_file])
+ if extra_preargs:
+ pp_args[:0] = extra_preargs
+ if extra_postargs:
+ pp_args.extend(extra_postargs)
+ pp_args.append(source)
+
+ # reasons to preprocess:
+ # - force is indicated
+ # - output is directed to stdout
+ # - source file is newer than the target
+ preprocess = self.force or output_file is None or newer(source, output_file)
+ if not preprocess:
+ return
+
+ if output_file:
+ self.mkpath(os.path.dirname(output_file))
+
+ try:
+ self.spawn(pp_args)
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
+
+ def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
+ compiler_so = compiler_fixup(self.compiler_so, cc_args + extra_postargs)
+ compiler_so_cxx = compiler_fixup(self.compiler_so_cxx, cc_args + extra_postargs)
+ try:
+ if self.detect_language(src) == 'c++':
+ self.spawn(
+ compiler_so_cxx + cc_args + [src, '-o', obj] + extra_postargs
+ )
+ else:
+ self.spawn(compiler_so + cc_args + [src, '-o', obj] + extra_postargs)
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
+
+ def create_static_lib(
+ self, objects, output_libname, output_dir=None, debug=False, target_lang=None
+ ):
+ objects, output_dir = self._fix_object_args(objects, output_dir)
+
+ output_filename = self.library_filename(output_libname, output_dir=output_dir)
+
+ if self._need_link(objects, output_filename):
+ self.mkpath(os.path.dirname(output_filename))
+ self.spawn(self.archiver + [output_filename] + objects + self.objects)
+
+ # Not many Unices required ranlib anymore -- SunOS 4.x is, I
+ # think the only major Unix that does. Maybe we need some
+ # platform intelligence here to skip ranlib if it's not
+ # needed -- or maybe Python's configure script took care of
+ # it for us, hence the check for leading colon.
+ if self.ranlib:
+ try:
+ self.spawn(self.ranlib + [output_filename])
+ except DistutilsExecError as msg:
+ raise LibError(msg)
+ else:
+ log.debug("skipping %s (up-to-date)", output_filename)
+
+ def link(
+ self,
+ target_desc,
+ objects: list[str] | tuple[str, ...],
+ output_filename,
+ output_dir: str | None = None,
+ libraries: list[str] | tuple[str, ...] | None = None,
+ library_dirs: list[str] | tuple[str, ...] | None = None,
+ runtime_library_dirs: list[str] | tuple[str, ...] | None = None,
+ export_symbols=None,
+ debug=False,
+ extra_preargs=None,
+ extra_postargs=None,
+ build_temp=None,
+ target_lang=None,
+ ):
+ objects, output_dir = self._fix_object_args(objects, output_dir)
+ fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
+ libraries, library_dirs, runtime_library_dirs = fixed_args
+
+ lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries)
+ if not isinstance(output_dir, (str, type(None))):
+ raise TypeError("'output_dir' must be a string or None")
+ if output_dir is not None:
+ output_filename = os.path.join(output_dir, output_filename)
+
+ if self._need_link(objects, output_filename):
+ ld_args = objects + self.objects + lib_opts + ['-o', output_filename]
+ if debug:
+ ld_args[:0] = ['-g']
+ if extra_preargs:
+ ld_args[:0] = extra_preargs
+ if extra_postargs:
+ ld_args.extend(extra_postargs)
+ self.mkpath(os.path.dirname(output_filename))
+ try:
+ # Select a linker based on context: linker_exe when
+ # building an executable or linker_so (with shared options)
+ # when building a shared library.
+ building_exe = target_desc == base.Compiler.EXECUTABLE
+ linker = (
+ self.linker_exe
+ if building_exe
+ else (
+ self.linker_so_cxx if target_lang == "c++" else self.linker_so
+ )
+ )[:]
+
+ if target_lang == "c++" and self.compiler_cxx:
+ env, linker_ne = _split_env(linker)
+ aix, linker_na = _split_aix(linker_ne)
+ _, compiler_cxx_ne = _split_env(self.compiler_cxx)
+ _, linker_exe_ne = _split_env(self.linker_exe)
+
+ params = _linker_params(linker_na, linker_exe_ne)
+ linker = env + aix + compiler_cxx_ne + params
+
+ linker = compiler_fixup(linker, ld_args)
+
+ self.spawn(linker + ld_args)
+ except DistutilsExecError as msg:
+ raise LinkError(msg)
+ else:
+ log.debug("skipping %s (up-to-date)", output_filename)
+
+ # -- Miscellaneous methods -----------------------------------------
+ # These are all used by the 'gen_lib_options() function, in
+ # ccompiler.py.
+
+ def library_dir_option(self, dir):
+ return "-L" + dir
+
+ def _is_gcc(self):
+ cc_var = sysconfig.get_config_var("CC")
+ compiler = os.path.basename(shlex.split(cc_var)[0])
+ return "gcc" in compiler or "g++" in compiler
+
+ def runtime_library_dir_option(self, dir: str) -> str | list[str]: # type: ignore[override] # Fixed in pypa/distutils#339
+ # XXX Hackish, at the very least. See Python bug #445902:
+ # https://bugs.python.org/issue445902
+ # Linkers on different platforms need different options to
+ # specify that directories need to be added to the list of
+ # directories searched for dependencies when a dynamic library
+ # is sought. GCC on GNU systems (Linux, FreeBSD, ...) has to
+ # be told to pass the -R option through to the linker, whereas
+ # other compilers and gcc on other systems just know this.
+ # Other compilers may need something slightly different. At
+ # this time, there's no way to determine this information from
+ # the configuration data stored in the Python installation, so
+ # we use this hack.
+ if sys.platform[:6] == "darwin":
+ from distutils.util import get_macosx_target_ver, split_version
+
+ macosx_target_ver = get_macosx_target_ver()
+ if macosx_target_ver and split_version(macosx_target_ver) >= [10, 5]:
+ return "-Wl,-rpath," + dir
+ else: # no support for -rpath on earlier macOS versions
+ return "-L" + dir
+ elif sys.platform[:7] == "freebsd":
+ return "-Wl,-rpath=" + dir
+ elif sys.platform[:5] == "hp-ux":
+ return [
+ "-Wl,+s" if self._is_gcc() else "+s",
+ "-L" + dir,
+ ]
+
+ # For all compilers, `-Wl` is the presumed way to pass a
+ # compiler option to the linker
+ if sysconfig.get_config_var("GNULD") == "yes":
+ return consolidate_linker_args([
+ # Force RUNPATH instead of RPATH
+ "-Wl,--enable-new-dtags",
+ "-Wl,-rpath," + dir,
+ ])
+ else:
+ return "-Wl,-R" + dir
+
+ def library_option(self, lib):
+ return "-l" + lib
+
+ @staticmethod
+ def _library_root(dir):
+ """
+ macOS users can specify an alternate SDK using'-isysroot'.
+ Calculate the SDK root if it is specified.
+
+ Note that, as of Xcode 7, Apple SDKs may contain textual stub
+ libraries with .tbd extensions rather than the normal .dylib
+ shared libraries installed in /. The Apple compiler tool
+ chain handles this transparently but it can cause problems
+ for programs that are being built with an SDK and searching
+ for specific libraries. Callers of find_library_file need to
+ keep in mind that the base filename of the returned SDK library
+ file might have a different extension from that of the library
+ file installed on the running system, for example:
+ /Applications/Xcode.app/Contents/Developer/Platforms/
+ MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/
+ usr/lib/libedit.tbd
+ vs
+ /usr/lib/libedit.dylib
+ """
+ cflags = sysconfig.get_config_var('CFLAGS')
+ match = re.search(r'-isysroot\s*(\S+)', cflags)
+
+ apply_root = (
+ sys.platform == 'darwin'
+ and match
+ and (
+ dir.startswith('/System/')
+ or (dir.startswith('/usr/') and not dir.startswith('/usr/local/'))
+ )
+ )
+
+ return os.path.join(match.group(1), dir[1:]) if apply_root else dir
+
+ def find_library_file(self, dirs, lib, debug=False):
+ """
+ Second-guess the linker with not much hard
+ data to go on: GCC seems to prefer the shared library, so
+ assume that *all* Unix C compilers do,
+ ignoring even GCC's "-static" option.
+ """
+ lib_names = (
+ self.library_filename(lib, lib_type=type)
+ for type in 'dylib xcode_stub shared static'.split()
+ )
+
+ roots = map(self._library_root, dirs)
+
+ searched = itertools.starmap(os.path.join, itertools.product(roots, lib_names))
+
+ found = filter(os.path.exists, searched)
+
+ # Return None if it could not be found in any dir.
+ return next(found, None)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/zos.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/zos.py
new file mode 100644
index 0000000..82d017f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/zos.py
@@ -0,0 +1,230 @@
+"""distutils.zosccompiler
+
+Contains the selection of the c & c++ compilers on z/OS. There are several
+different c compilers on z/OS, all of them are optional, so the correct
+one needs to be chosen based on the users input. This is compatible with
+the following compilers:
+
+IBM C/C++ For Open Enterprise Languages on z/OS 2.0
+IBM Open XL C/C++ 1.1 for z/OS
+IBM XL C/C++ V2.4.1 for z/OS 2.4 and 2.5
+IBM z/OS XL C/C++
+"""
+
+import os
+
+from ... import sysconfig
+from ...errors import DistutilsExecError
+from . import unix
+from .errors import CompileError
+
+_cc_args = {
+ 'ibm-openxl': [
+ '-m64',
+ '-fvisibility=default',
+ '-fzos-le-char-mode=ascii',
+ '-fno-short-enums',
+ ],
+ 'ibm-xlclang': [
+ '-q64',
+ '-qexportall',
+ '-qascii',
+ '-qstrict',
+ '-qnocsect',
+ '-Wa,asa,goff',
+ '-Wa,xplink',
+ '-qgonumber',
+ '-qenum=int',
+ '-Wc,DLL',
+ ],
+ 'ibm-xlc': [
+ '-q64',
+ '-qexportall',
+ '-qascii',
+ '-qstrict',
+ '-qnocsect',
+ '-Wa,asa,goff',
+ '-Wa,xplink',
+ '-qgonumber',
+ '-qenum=int',
+ '-Wc,DLL',
+ '-qlanglvl=extc99',
+ ],
+}
+
+_cxx_args = {
+ 'ibm-openxl': [
+ '-m64',
+ '-fvisibility=default',
+ '-fzos-le-char-mode=ascii',
+ '-fno-short-enums',
+ ],
+ 'ibm-xlclang': [
+ '-q64',
+ '-qexportall',
+ '-qascii',
+ '-qstrict',
+ '-qnocsect',
+ '-Wa,asa,goff',
+ '-Wa,xplink',
+ '-qgonumber',
+ '-qenum=int',
+ '-Wc,DLL',
+ ],
+ 'ibm-xlc': [
+ '-q64',
+ '-qexportall',
+ '-qascii',
+ '-qstrict',
+ '-qnocsect',
+ '-Wa,asa,goff',
+ '-Wa,xplink',
+ '-qgonumber',
+ '-qenum=int',
+ '-Wc,DLL',
+ '-qlanglvl=extended0x',
+ ],
+}
+
+_asm_args = {
+ 'ibm-openxl': ['-fasm', '-fno-integrated-as', '-Wa,--ASA', '-Wa,--GOFF'],
+ 'ibm-xlclang': [],
+ 'ibm-xlc': [],
+}
+
+_ld_args = {
+ 'ibm-openxl': [],
+ 'ibm-xlclang': ['-Wl,dll', '-q64'],
+ 'ibm-xlc': ['-Wl,dll', '-q64'],
+}
+
+
+# Python on z/OS is built with no compiler specific options in it's CFLAGS.
+# But each compiler requires it's own specific options to build successfully,
+# though some of the options are common between them
+class Compiler(unix.Compiler):
+ src_extensions = ['.c', '.C', '.cc', '.cxx', '.cpp', '.m', '.s']
+ _cpp_extensions = ['.cc', '.cpp', '.cxx', '.C']
+ _asm_extensions = ['.s']
+
+ def _get_zos_compiler_name(self):
+ zos_compiler_names = [
+ os.path.basename(binary)
+ for envvar in ('CC', 'CXX', 'LDSHARED')
+ if (binary := os.environ.get(envvar, None))
+ ]
+ if len(zos_compiler_names) == 0:
+ return 'ibm-openxl'
+
+ zos_compilers = {}
+ for compiler in (
+ 'ibm-clang',
+ 'ibm-clang64',
+ 'ibm-clang++',
+ 'ibm-clang++64',
+ 'clang',
+ 'clang++',
+ 'clang-14',
+ ):
+ zos_compilers[compiler] = 'ibm-openxl'
+
+ for compiler in ('xlclang', 'xlclang++', 'njsc', 'njsc++'):
+ zos_compilers[compiler] = 'ibm-xlclang'
+
+ for compiler in ('xlc', 'xlC', 'xlc++'):
+ zos_compilers[compiler] = 'ibm-xlc'
+
+ return zos_compilers.get(zos_compiler_names[0], 'ibm-openxl')
+
+ def __init__(self, verbose=False, dry_run=False, force=False):
+ super().__init__(verbose, dry_run, force)
+ self.zos_compiler = self._get_zos_compiler_name()
+ sysconfig.customize_compiler(self)
+
+ def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
+ local_args = []
+ if ext in self._cpp_extensions:
+ compiler = self.compiler_cxx
+ local_args.extend(_cxx_args[self.zos_compiler])
+ elif ext in self._asm_extensions:
+ compiler = self.compiler_so
+ local_args.extend(_cc_args[self.zos_compiler])
+ local_args.extend(_asm_args[self.zos_compiler])
+ else:
+ compiler = self.compiler_so
+ local_args.extend(_cc_args[self.zos_compiler])
+ local_args.extend(cc_args)
+
+ try:
+ self.spawn(compiler + local_args + [src, '-o', obj] + extra_postargs)
+ except DistutilsExecError as msg:
+ raise CompileError(msg)
+
+ def runtime_library_dir_option(self, dir):
+ return '-L' + dir
+
+ def link(
+ self,
+ target_desc,
+ objects,
+ output_filename,
+ output_dir=None,
+ libraries=None,
+ library_dirs=None,
+ runtime_library_dirs=None,
+ export_symbols=None,
+ debug=False,
+ extra_preargs=None,
+ extra_postargs=None,
+ build_temp=None,
+ target_lang=None,
+ ):
+ # For a built module to use functions from cpython, it needs to use Pythons
+ # side deck file. The side deck is located beside the libpython3.xx.so
+ ldversion = sysconfig.get_config_var('LDVERSION')
+ if sysconfig.python_build:
+ side_deck_path = os.path.join(
+ sysconfig.get_config_var('abs_builddir'),
+ f'libpython{ldversion}.x',
+ )
+ else:
+ side_deck_path = os.path.join(
+ sysconfig.get_config_var('installed_base'),
+ sysconfig.get_config_var('platlibdir'),
+ f'libpython{ldversion}.x',
+ )
+
+ if os.path.exists(side_deck_path):
+ if extra_postargs:
+ extra_postargs.append(side_deck_path)
+ else:
+ extra_postargs = [side_deck_path]
+
+ # Check and replace libraries included side deck files
+ if runtime_library_dirs:
+ for dir in runtime_library_dirs:
+ for library in libraries[:]:
+ library_side_deck = os.path.join(dir, f'{library}.x')
+ if os.path.exists(library_side_deck):
+ libraries.remove(library)
+ extra_postargs.append(library_side_deck)
+ break
+
+ # Any required ld args for the given compiler
+ extra_postargs.extend(_ld_args[self.zos_compiler])
+
+ super().link(
+ target_desc,
+ objects,
+ output_filename,
+ output_dir,
+ libraries,
+ library_dirs,
+ runtime_library_dirs,
+ export_symbols,
+ debug,
+ extra_preargs,
+ extra_postargs,
+ build_temp,
+ target_lang,
+ )
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/core.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/core.py
new file mode 100644
index 0000000..bd62546
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/core.py
@@ -0,0 +1,289 @@
+"""distutils.core
+
+The only module that needs to be imported to use the Distutils; provides
+the 'setup' function (which is to be called from the setup script). Also
+indirectly provides the Distribution and Command classes, although they are
+really defined in distutils.dist and distutils.cmd.
+"""
+
+from __future__ import annotations
+
+import os
+import sys
+import tokenize
+from collections.abc import Iterable
+
+from .cmd import Command
+from .debug import DEBUG
+
+# Mainly import these so setup scripts can "from distutils.core import" them.
+from .dist import Distribution
+from .errors import (
+ CCompilerError,
+ DistutilsArgError,
+ DistutilsError,
+ DistutilsSetupError,
+)
+from .extension import Extension
+
+__all__ = ['Distribution', 'Command', 'Extension', 'setup']
+
+# This is a barebones help message generated displayed when the user
+# runs the setup script with no arguments at all. More useful help
+# is generated with various --help options: global help, list commands,
+# and per-command help.
+USAGE = """\
+usage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
+ or: %(script)s --help [cmd1 cmd2 ...]
+ or: %(script)s --help-commands
+ or: %(script)s cmd --help
+"""
+
+
+def gen_usage(script_name):
+ script = os.path.basename(script_name)
+ return USAGE % locals()
+
+
+# Some mild magic to control the behaviour of 'setup()' from 'run_setup()'.
+_setup_stop_after = None
+_setup_distribution = None
+
+# Legal keyword arguments for the setup() function
+setup_keywords = (
+ 'distclass',
+ 'script_name',
+ 'script_args',
+ 'options',
+ 'name',
+ 'version',
+ 'author',
+ 'author_email',
+ 'maintainer',
+ 'maintainer_email',
+ 'url',
+ 'license',
+ 'description',
+ 'long_description',
+ 'keywords',
+ 'platforms',
+ 'classifiers',
+ 'download_url',
+ 'requires',
+ 'provides',
+ 'obsoletes',
+)
+
+# Legal keyword arguments for the Extension constructor
+extension_keywords = (
+ 'name',
+ 'sources',
+ 'include_dirs',
+ 'define_macros',
+ 'undef_macros',
+ 'library_dirs',
+ 'libraries',
+ 'runtime_library_dirs',
+ 'extra_objects',
+ 'extra_compile_args',
+ 'extra_link_args',
+ 'swig_opts',
+ 'export_symbols',
+ 'depends',
+ 'language',
+)
+
+
+def setup(**attrs): # noqa: C901
+ """The gateway to the Distutils: do everything your setup script needs
+ to do, in a highly flexible and user-driven way. Briefly: create a
+ Distribution instance; find and parse config files; parse the command
+ line; run each Distutils command found there, customized by the options
+ supplied to 'setup()' (as keyword arguments), in config files, and on
+ the command line.
+
+ The Distribution instance might be an instance of a class supplied via
+ the 'distclass' keyword argument to 'setup'; if no such class is
+ supplied, then the Distribution class (in dist.py) is instantiated.
+ All other arguments to 'setup' (except for 'cmdclass') are used to set
+ attributes of the Distribution instance.
+
+ The 'cmdclass' argument, if supplied, is a dictionary mapping command
+ names to command classes. Each command encountered on the command line
+ will be turned into a command class, which is in turn instantiated; any
+ class found in 'cmdclass' is used in place of the default, which is
+ (for command 'foo_bar') class 'foo_bar' in module
+ 'distutils.command.foo_bar'. The command class must provide a
+ 'user_options' attribute which is a list of option specifiers for
+ 'distutils.fancy_getopt'. Any command-line options between the current
+ and the next command are used to set attributes of the current command
+ object.
+
+ When the entire command-line has been successfully parsed, calls the
+ 'run()' method on each command object in turn. This method will be
+ driven entirely by the Distribution object (which each command object
+ has a reference to, thanks to its constructor), and the
+ command-specific options that became attributes of each command
+ object.
+ """
+
+ global _setup_stop_after, _setup_distribution
+
+ # Determine the distribution class -- either caller-supplied or
+ # our Distribution (see below).
+ klass = attrs.get('distclass')
+ if klass:
+ attrs.pop('distclass')
+ else:
+ klass = Distribution
+
+ if 'script_name' not in attrs:
+ attrs['script_name'] = os.path.basename(sys.argv[0])
+ if 'script_args' not in attrs:
+ attrs['script_args'] = sys.argv[1:]
+
+ # Create the Distribution instance, using the remaining arguments
+ # (ie. everything except distclass) to initialize it
+ try:
+ _setup_distribution = dist = klass(attrs)
+ except DistutilsSetupError as msg:
+ if 'name' not in attrs:
+ raise SystemExit(f"error in setup command: {msg}")
+ else:
+ raise SystemExit("error in {} setup command: {}".format(attrs['name'], msg))
+
+ if _setup_stop_after == "init":
+ return dist
+
+ # Find and parse the config file(s): they will override options from
+ # the setup script, but be overridden by the command line.
+ dist.parse_config_files()
+
+ if DEBUG:
+ print("options (after parsing config files):")
+ dist.dump_option_dicts()
+
+ if _setup_stop_after == "config":
+ return dist
+
+ # Parse the command line and override config files; any
+ # command-line errors are the end user's fault, so turn them into
+ # SystemExit to suppress tracebacks.
+ try:
+ ok = dist.parse_command_line()
+ except DistutilsArgError as msg:
+ raise SystemExit(gen_usage(dist.script_name) + f"\nerror: {msg}")
+
+ if DEBUG:
+ print("options (after parsing command line):")
+ dist.dump_option_dicts()
+
+ if _setup_stop_after == "commandline":
+ return dist
+
+ # And finally, run all the commands found on the command line.
+ if ok:
+ return run_commands(dist)
+
+ return dist
+
+
+# setup ()
+
+
+def run_commands(dist):
+ """Given a Distribution object run all the commands,
+ raising ``SystemExit`` errors in the case of failure.
+
+ This function assumes that either ``sys.argv`` or ``dist.script_args``
+ is already set accordingly.
+ """
+ try:
+ dist.run_commands()
+ except KeyboardInterrupt:
+ raise SystemExit("interrupted")
+ except OSError as exc:
+ if DEBUG:
+ sys.stderr.write(f"error: {exc}\n")
+ raise
+ else:
+ raise SystemExit(f"error: {exc}")
+
+ except (DistutilsError, CCompilerError) as msg:
+ if DEBUG:
+ raise
+ else:
+ raise SystemExit("error: " + str(msg))
+
+ return dist
+
+
+def run_setup(script_name, script_args: Iterable[str] | None = None, stop_after="run"):
+ """Run a setup script in a somewhat controlled environment, and
+ return the Distribution instance that drives things. This is useful
+ if you need to find out the distribution meta-data (passed as
+ keyword args from 'script' to 'setup()', or the contents of the
+ config files or command-line.
+
+ 'script_name' is a file that will be read and run with 'exec()';
+ 'sys.argv[0]' will be replaced with 'script' for the duration of the
+ call. 'script_args' is a list of strings; if supplied,
+ 'sys.argv[1:]' will be replaced by 'script_args' for the duration of
+ the call.
+
+ 'stop_after' tells 'setup()' when to stop processing; possible
+ values:
+ init
+ stop after the Distribution instance has been created and
+ populated with the keyword arguments to 'setup()'
+ config
+ stop after config files have been parsed (and their data
+ stored in the Distribution instance)
+ commandline
+ stop after the command-line ('sys.argv[1:]' or 'script_args')
+ have been parsed (and the data stored in the Distribution)
+ run [default]
+ stop after all commands have been run (the same as if 'setup()'
+ had been called in the usual way
+
+ Returns the Distribution instance, which provides all information
+ used to drive the Distutils.
+ """
+ if stop_after not in ('init', 'config', 'commandline', 'run'):
+ raise ValueError(f"invalid value for 'stop_after': {stop_after!r}")
+
+ global _setup_stop_after, _setup_distribution
+ _setup_stop_after = stop_after
+
+ save_argv = sys.argv.copy()
+ g = {'__file__': script_name, '__name__': '__main__'}
+ try:
+ try:
+ sys.argv[0] = script_name
+ if script_args is not None:
+ sys.argv[1:] = script_args
+ # tokenize.open supports automatic encoding detection
+ with tokenize.open(script_name) as f:
+ code = f.read().replace(r'\r\n', r'\n')
+ exec(code, g)
+ finally:
+ sys.argv = save_argv
+ _setup_stop_after = None
+ except SystemExit:
+ # Hmm, should we do something if exiting with a non-zero code
+ # (ie. error)?
+ pass
+
+ if _setup_distribution is None:
+ raise RuntimeError(
+ "'distutils.core.setup()' was never called -- "
+ f"perhaps '{script_name}' is not a Distutils setup script?"
+ )
+
+ # I wonder if the setup script's namespace -- g and l -- would be of
+ # any interest to callers?
+ # print "_setup_distribution:", _setup_distribution
+ return _setup_distribution
+
+
+# run_setup ()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/cygwinccompiler.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/cygwinccompiler.py
new file mode 100644
index 0000000..de89e3c
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/cygwinccompiler.py
@@ -0,0 +1,31 @@
+from .compilers.C import cygwin
+from .compilers.C.cygwin import (
+ CONFIG_H_NOTOK,
+ CONFIG_H_OK,
+ CONFIG_H_UNCERTAIN,
+ check_config_h,
+ get_msvcr,
+ is_cygwincc,
+)
+
+__all__ = [
+ 'CONFIG_H_NOTOK',
+ 'CONFIG_H_OK',
+ 'CONFIG_H_UNCERTAIN',
+ 'CygwinCCompiler',
+ 'Mingw32CCompiler',
+ 'check_config_h',
+ 'get_msvcr',
+ 'is_cygwincc',
+]
+
+
+CygwinCCompiler = cygwin.Compiler
+Mingw32CCompiler = cygwin.MinGW32Compiler
+
+
+get_versions = None
+"""
+A stand-in for the previous get_versions() function to prevent failures
+when monkeypatched. See pypa/setuptools#2969.
+"""
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/debug.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/debug.py
new file mode 100644
index 0000000..daf1660
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/debug.py
@@ -0,0 +1,5 @@
+import os
+
+# If DISTUTILS_DEBUG is anything other than the empty string, we run in
+# debug mode.
+DEBUG = os.environ.get('DISTUTILS_DEBUG')
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/dep_util.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/dep_util.py
new file mode 100644
index 0000000..09a8a2e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/dep_util.py
@@ -0,0 +1,14 @@
+import warnings
+
+from . import _modified
+
+
+def __getattr__(name):
+ if name not in ['newer', 'newer_group', 'newer_pairwise']:
+ raise AttributeError(name)
+ warnings.warn(
+ "dep_util is Deprecated. Use functions from setuptools instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return getattr(_modified, name)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/dir_util.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/dir_util.py
new file mode 100644
index 0000000..d978260
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/dir_util.py
@@ -0,0 +1,244 @@
+"""distutils.dir_util
+
+Utility functions for manipulating directories and directory trees."""
+
+import functools
+import itertools
+import os
+import pathlib
+
+from . import file_util
+from ._log import log
+from .errors import DistutilsFileError, DistutilsInternalError
+
+
+class SkipRepeatAbsolutePaths(set):
+ """
+ Cache for mkpath.
+
+ In addition to cheapening redundant calls, eliminates redundant
+ "creating /foo/bar/baz" messages in dry-run mode.
+ """
+
+ def __init__(self):
+ SkipRepeatAbsolutePaths.instance = self
+
+ @classmethod
+ def clear(cls):
+ super(cls, cls.instance).clear()
+
+ def wrap(self, func):
+ @functools.wraps(func)
+ def wrapper(path, *args, **kwargs):
+ if path.absolute() in self:
+ return
+ result = func(path, *args, **kwargs)
+ self.add(path.absolute())
+ return result
+
+ return wrapper
+
+
+# Python 3.8 compatibility
+wrapper = SkipRepeatAbsolutePaths().wrap
+
+
+@functools.singledispatch
+@wrapper
+def mkpath(name: pathlib.Path, mode=0o777, verbose=True, dry_run=False) -> None:
+ """Create a directory and any missing ancestor directories.
+
+ If the directory already exists (or if 'name' is the empty string, which
+ means the current directory, which of course exists), then do nothing.
+ Raise DistutilsFileError if unable to create some directory along the way
+ (eg. some sub-path exists, but is a file rather than a directory).
+ If 'verbose' is true, log the directory created.
+ """
+ if verbose and not name.is_dir():
+ log.info("creating %s", name)
+
+ try:
+ dry_run or name.mkdir(mode=mode, parents=True, exist_ok=True)
+ except OSError as exc:
+ raise DistutilsFileError(f"could not create '{name}': {exc.args[-1]}")
+
+
+@mkpath.register
+def _(name: str, *args, **kwargs):
+ return mkpath(pathlib.Path(name), *args, **kwargs)
+
+
+@mkpath.register
+def _(name: None, *args, **kwargs):
+ """
+ Detect a common bug -- name is None.
+ """
+ raise DistutilsInternalError(f"mkpath: 'name' must be a string (got {name!r})")
+
+
+def create_tree(base_dir, files, mode=0o777, verbose=True, dry_run=False):
+ """Create all the empty directories under 'base_dir' needed to put 'files'
+ there.
+
+ 'base_dir' is just the name of a directory which doesn't necessarily
+ exist yet; 'files' is a list of filenames to be interpreted relative to
+ 'base_dir'. 'base_dir' + the directory portion of every file in 'files'
+ will be created if it doesn't already exist. 'mode', 'verbose' and
+ 'dry_run' flags are as for 'mkpath()'.
+ """
+ # First get the list of directories to create
+ need_dir = set(os.path.join(base_dir, os.path.dirname(file)) for file in files)
+
+ # Now create them
+ for dir in sorted(need_dir):
+ mkpath(dir, mode, verbose=verbose, dry_run=dry_run)
+
+
+def copy_tree(
+ src,
+ dst,
+ preserve_mode=True,
+ preserve_times=True,
+ preserve_symlinks=False,
+ update=False,
+ verbose=True,
+ dry_run=False,
+):
+ """Copy an entire directory tree 'src' to a new location 'dst'.
+
+ Both 'src' and 'dst' must be directory names. If 'src' is not a
+ directory, raise DistutilsFileError. If 'dst' does not exist, it is
+ created with 'mkpath()'. The end result of the copy is that every
+ file in 'src' is copied to 'dst', and directories under 'src' are
+ recursively copied to 'dst'. Return the list of files that were
+ copied or might have been copied, using their output name. The
+ return value is unaffected by 'update' or 'dry_run': it is simply
+ the list of all files under 'src', with the names changed to be
+ under 'dst'.
+
+ 'preserve_mode' and 'preserve_times' are the same as for
+ 'copy_file'; note that they only apply to regular files, not to
+ directories. If 'preserve_symlinks' is true, symlinks will be
+ copied as symlinks (on platforms that support them!); otherwise
+ (the default), the destination of the symlink will be copied.
+ 'update' and 'verbose' are the same as for 'copy_file'.
+ """
+ if not dry_run and not os.path.isdir(src):
+ raise DistutilsFileError(f"cannot copy tree '{src}': not a directory")
+ try:
+ names = os.listdir(src)
+ except OSError as e:
+ if dry_run:
+ names = []
+ else:
+ raise DistutilsFileError(f"error listing files in '{src}': {e.strerror}")
+
+ if not dry_run:
+ mkpath(dst, verbose=verbose)
+
+ copy_one = functools.partial(
+ _copy_one,
+ src=src,
+ dst=dst,
+ preserve_symlinks=preserve_symlinks,
+ verbose=verbose,
+ dry_run=dry_run,
+ preserve_mode=preserve_mode,
+ preserve_times=preserve_times,
+ update=update,
+ )
+ return list(itertools.chain.from_iterable(map(copy_one, names)))
+
+
+def _copy_one(
+ name,
+ *,
+ src,
+ dst,
+ preserve_symlinks,
+ verbose,
+ dry_run,
+ preserve_mode,
+ preserve_times,
+ update,
+):
+ src_name = os.path.join(src, name)
+ dst_name = os.path.join(dst, name)
+
+ if name.startswith('.nfs'):
+ # skip NFS rename files
+ return
+
+ if preserve_symlinks and os.path.islink(src_name):
+ link_dest = os.readlink(src_name)
+ if verbose >= 1:
+ log.info("linking %s -> %s", dst_name, link_dest)
+ if not dry_run:
+ os.symlink(link_dest, dst_name)
+ yield dst_name
+
+ elif os.path.isdir(src_name):
+ yield from copy_tree(
+ src_name,
+ dst_name,
+ preserve_mode,
+ preserve_times,
+ preserve_symlinks,
+ update,
+ verbose=verbose,
+ dry_run=dry_run,
+ )
+ else:
+ file_util.copy_file(
+ src_name,
+ dst_name,
+ preserve_mode,
+ preserve_times,
+ update,
+ verbose=verbose,
+ dry_run=dry_run,
+ )
+ yield dst_name
+
+
+def _build_cmdtuple(path, cmdtuples):
+ """Helper for remove_tree()."""
+ for f in os.listdir(path):
+ real_f = os.path.join(path, f)
+ if os.path.isdir(real_f) and not os.path.islink(real_f):
+ _build_cmdtuple(real_f, cmdtuples)
+ else:
+ cmdtuples.append((os.remove, real_f))
+ cmdtuples.append((os.rmdir, path))
+
+
+def remove_tree(directory, verbose=True, dry_run=False):
+ """Recursively remove an entire directory tree.
+
+ Any errors are ignored (apart from being reported to stdout if 'verbose'
+ is true).
+ """
+ if verbose >= 1:
+ log.info("removing '%s' (and everything under it)", directory)
+ if dry_run:
+ return
+ cmdtuples = []
+ _build_cmdtuple(directory, cmdtuples)
+ for cmd in cmdtuples:
+ try:
+ cmd[0](cmd[1])
+ # Clear the cache
+ SkipRepeatAbsolutePaths.clear()
+ except OSError as exc:
+ log.warning("error removing %s: %s", directory, exc)
+
+
+def ensure_relative(path):
+ """Take the full path 'path', and make it a relative path.
+
+ This is useful to make 'path' the second argument to os.path.join().
+ """
+ drive, path = os.path.splitdrive(path)
+ if path[0:1] == os.sep:
+ path = drive + path[1:]
+ return path
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/dist.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/dist.py
new file mode 100644
index 0000000..37b788d
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/dist.py
@@ -0,0 +1,1386 @@
+"""distutils.dist
+
+Provides the Distribution class, which represents the module distribution
+being built/installed/distributed.
+"""
+
+from __future__ import annotations
+
+import contextlib
+import logging
+import os
+import pathlib
+import re
+import sys
+import warnings
+from collections.abc import Iterable, MutableMapping
+from email import message_from_file
+from typing import (
+ IO,
+ TYPE_CHECKING,
+ Any,
+ ClassVar,
+ Literal,
+ TypeVar,
+ Union,
+ overload,
+)
+
+from packaging.utils import canonicalize_name, canonicalize_version
+
+from ._log import log
+from .debug import DEBUG
+from .errors import (
+ DistutilsArgError,
+ DistutilsClassError,
+ DistutilsModuleError,
+ DistutilsOptionError,
+)
+from .fancy_getopt import FancyGetopt, translate_longopt
+from .util import check_environ, rfc822_escape, strtobool
+
+if TYPE_CHECKING:
+ from _typeshed import SupportsWrite
+ from typing_extensions import TypeAlias
+
+ # type-only import because of mutual dependence between these modules
+ from .cmd import Command
+
+_CommandT = TypeVar("_CommandT", bound="Command")
+_OptionsList: TypeAlias = list[
+ Union[tuple[str, Union[str, None], str, int], tuple[str, Union[str, None], str]]
+]
+
+
+# Regex to define acceptable Distutils command names. This is not *quite*
+# the same as a Python NAME -- I don't allow leading underscores. The fact
+# that they're very similar is no coincidence; the default naming scheme is
+# to look for a Python module named after the command.
+command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
+
+
+def _ensure_list(value: str | Iterable[str], fieldname) -> str | list[str]:
+ if isinstance(value, str):
+ # a string containing comma separated values is okay. It will
+ # be converted to a list by Distribution.finalize_options().
+ pass
+ elif not isinstance(value, list):
+ # passing a tuple or an iterator perhaps, warn and convert
+ typename = type(value).__name__
+ msg = "Warning: '{fieldname}' should be a list, got type '{typename}'"
+ msg = msg.format(**locals())
+ log.warning(msg)
+ value = list(value)
+ return value
+
+
+class Distribution:
+ """The core of the Distutils. Most of the work hiding behind 'setup'
+ is really done within a Distribution instance, which farms the work out
+ to the Distutils commands specified on the command line.
+
+ Setup scripts will almost never instantiate Distribution directly,
+ unless the 'setup()' function is totally inadequate to their needs.
+ However, it is conceivable that a setup script might wish to subclass
+ Distribution for some specialized purpose, and then pass the subclass
+ to 'setup()' as the 'distclass' keyword argument. If so, it is
+ necessary to respect the expectations that 'setup' has of Distribution.
+ See the code for 'setup()', in core.py, for details.
+ """
+
+ # 'global_options' describes the command-line options that may be
+ # supplied to the setup script prior to any actual commands.
+ # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
+ # these global options. This list should be kept to a bare minimum,
+ # since every global option is also valid as a command option -- and we
+ # don't want to pollute the commands with too many options that they
+ # have minimal control over.
+ # The fourth entry for verbose means that it can be repeated.
+ global_options: ClassVar[_OptionsList] = [
+ ('verbose', 'v', "run verbosely (default)", 1),
+ ('quiet', 'q', "run quietly (turns verbosity off)"),
+ ('dry-run', 'n', "don't actually do anything"),
+ ('help', 'h', "show detailed help message"),
+ ('no-user-cfg', None, 'ignore pydistutils.cfg in your home directory'),
+ ]
+
+ # 'common_usage' is a short (2-3 line) string describing the common
+ # usage of the setup script.
+ common_usage: ClassVar[str] = """\
+Common commands: (see '--help-commands' for more)
+
+ setup.py build will build the package underneath 'build/'
+ setup.py install will install the package
+"""
+
+ # options that are not propagated to the commands
+ display_options: ClassVar[_OptionsList] = [
+ ('help-commands', None, "list all available commands"),
+ ('name', None, "print package name"),
+ ('version', 'V', "print package version"),
+ ('fullname', None, "print -"),
+ ('author', None, "print the author's name"),
+ ('author-email', None, "print the author's email address"),
+ ('maintainer', None, "print the maintainer's name"),
+ ('maintainer-email', None, "print the maintainer's email address"),
+ ('contact', None, "print the maintainer's name if known, else the author's"),
+ (
+ 'contact-email',
+ None,
+ "print the maintainer's email address if known, else the author's",
+ ),
+ ('url', None, "print the URL for this package"),
+ ('license', None, "print the license of the package"),
+ ('licence', None, "alias for --license"),
+ ('description', None, "print the package description"),
+ ('long-description', None, "print the long package description"),
+ ('platforms', None, "print the list of platforms"),
+ ('classifiers', None, "print the list of classifiers"),
+ ('keywords', None, "print the list of keywords"),
+ ('provides', None, "print the list of packages/modules provided"),
+ ('requires', None, "print the list of packages/modules required"),
+ ('obsoletes', None, "print the list of packages/modules made obsolete"),
+ ]
+ display_option_names: ClassVar[list[str]] = [
+ translate_longopt(x[0]) for x in display_options
+ ]
+
+ # negative options are options that exclude other options
+ negative_opt: ClassVar[dict[str, str]] = {'quiet': 'verbose'}
+
+ # -- Creation/initialization methods -------------------------------
+
+ # Can't Unpack a TypedDict with optional properties, so using Any instead
+ def __init__(self, attrs: MutableMapping[str, Any] | None = None) -> None: # noqa: C901
+ """Construct a new Distribution instance: initialize all the
+ attributes of a Distribution, and then use 'attrs' (a dictionary
+ mapping attribute names to values) to assign some of those
+ attributes their "real" values. (Any attributes not mentioned in
+ 'attrs' will be assigned to some null value: 0, None, an empty list
+ or dictionary, etc.) Most importantly, initialize the
+ 'command_obj' attribute to the empty dictionary; this will be
+ filled in with real command objects by 'parse_command_line()'.
+ """
+
+ # Default values for our command-line options
+ self.verbose = True
+ self.dry_run = False
+ self.help = False
+ for attr in self.display_option_names:
+ setattr(self, attr, False)
+
+ # Store the distribution meta-data (name, version, author, and so
+ # forth) in a separate object -- we're getting to have enough
+ # information here (and enough command-line options) that it's
+ # worth it. Also delegate 'get_XXX()' methods to the 'metadata'
+ # object in a sneaky and underhanded (but efficient!) way.
+ self.metadata = DistributionMetadata()
+ for basename in self.metadata._METHOD_BASENAMES:
+ method_name = "get_" + basename
+ setattr(self, method_name, getattr(self.metadata, method_name))
+
+ # 'cmdclass' maps command names to class objects, so we
+ # can 1) quickly figure out which class to instantiate when
+ # we need to create a new command object, and 2) have a way
+ # for the setup script to override command classes
+ self.cmdclass: dict[str, type[Command]] = {}
+
+ # 'command_packages' is a list of packages in which commands
+ # are searched for. The factory for command 'foo' is expected
+ # to be named 'foo' in the module 'foo' in one of the packages
+ # named here. This list is searched from the left; an error
+ # is raised if no named package provides the command being
+ # searched for. (Always access using get_command_packages().)
+ self.command_packages: str | list[str] | None = None
+
+ # 'script_name' and 'script_args' are usually set to sys.argv[0]
+ # and sys.argv[1:], but they can be overridden when the caller is
+ # not necessarily a setup script run from the command-line.
+ self.script_name: str | os.PathLike[str] | None = None
+ self.script_args: list[str] | None = None
+
+ # 'command_options' is where we store command options between
+ # parsing them (from config files, the command-line, etc.) and when
+ # they are actually needed -- ie. when the command in question is
+ # instantiated. It is a dictionary of dictionaries of 2-tuples:
+ # command_options = { command_name : { option : (source, value) } }
+ self.command_options: dict[str, dict[str, tuple[str, str]]] = {}
+
+ # 'dist_files' is the list of (command, pyversion, file) that
+ # have been created by any dist commands run so far. This is
+ # filled regardless of whether the run is dry or not. pyversion
+ # gives sysconfig.get_python_version() if the dist file is
+ # specific to a Python version, 'any' if it is good for all
+ # Python versions on the target platform, and '' for a source
+ # file. pyversion should not be used to specify minimum or
+ # maximum required Python versions; use the metainfo for that
+ # instead.
+ self.dist_files: list[tuple[str, str, str]] = []
+
+ # These options are really the business of various commands, rather
+ # than of the Distribution itself. We provide aliases for them in
+ # Distribution as a convenience to the developer.
+ self.packages = None
+ self.package_data: dict[str, list[str]] = {}
+ self.package_dir = None
+ self.py_modules = None
+ self.libraries = None
+ self.headers = None
+ self.ext_modules = None
+ self.ext_package = None
+ self.include_dirs = None
+ self.extra_path = None
+ self.scripts = None
+ self.data_files = None
+ self.password = ''
+
+ # And now initialize bookkeeping stuff that can't be supplied by
+ # the caller at all. 'command_obj' maps command names to
+ # Command instances -- that's how we enforce that every command
+ # class is a singleton.
+ self.command_obj: dict[str, Command] = {}
+
+ # 'have_run' maps command names to boolean values; it keeps track
+ # of whether we have actually run a particular command, to make it
+ # cheap to "run" a command whenever we think we might need to -- if
+ # it's already been done, no need for expensive filesystem
+ # operations, we just check the 'have_run' dictionary and carry on.
+ # It's only safe to query 'have_run' for a command class that has
+ # been instantiated -- a false value will be inserted when the
+ # command object is created, and replaced with a true value when
+ # the command is successfully run. Thus it's probably best to use
+ # '.get()' rather than a straight lookup.
+ self.have_run: dict[str, bool] = {}
+
+ # Now we'll use the attrs dictionary (ultimately, keyword args from
+ # the setup script) to possibly override any or all of these
+ # distribution options.
+
+ if attrs:
+ # Pull out the set of command options and work on them
+ # specifically. Note that this order guarantees that aliased
+ # command options will override any supplied redundantly
+ # through the general options dictionary.
+ options = attrs.get('options')
+ if options is not None:
+ del attrs['options']
+ for command, cmd_options in options.items():
+ opt_dict = self.get_option_dict(command)
+ for opt, val in cmd_options.items():
+ opt_dict[opt] = ("setup script", val)
+
+ if 'licence' in attrs:
+ attrs['license'] = attrs['licence']
+ del attrs['licence']
+ msg = "'licence' distribution option is deprecated; use 'license'"
+ warnings.warn(msg)
+
+ # Now work on the rest of the attributes. Any attribute that's
+ # not already defined is invalid!
+ for key, val in attrs.items():
+ if hasattr(self.metadata, "set_" + key):
+ getattr(self.metadata, "set_" + key)(val)
+ elif hasattr(self.metadata, key):
+ setattr(self.metadata, key, val)
+ elif hasattr(self, key):
+ setattr(self, key, val)
+ else:
+ msg = f"Unknown distribution option: {key!r}"
+ warnings.warn(msg)
+
+ # no-user-cfg is handled before other command line args
+ # because other args override the config files, and this
+ # one is needed before we can load the config files.
+ # If attrs['script_args'] wasn't passed, assume false.
+ #
+ # This also make sure we just look at the global options
+ self.want_user_cfg = True
+
+ if self.script_args is not None:
+ # Coerce any possible iterable from attrs into a list
+ self.script_args = list(self.script_args)
+ for arg in self.script_args:
+ if not arg.startswith('-'):
+ break
+ if arg == '--no-user-cfg':
+ self.want_user_cfg = False
+ break
+
+ self.finalize_options()
+
+ def get_option_dict(self, command):
+ """Get the option dictionary for a given command. If that
+ command's option dictionary hasn't been created yet, then create it
+ and return the new dictionary; otherwise, return the existing
+ option dictionary.
+ """
+ dict = self.command_options.get(command)
+ if dict is None:
+ dict = self.command_options[command] = {}
+ return dict
+
+ def dump_option_dicts(self, header=None, commands=None, indent: str = "") -> None:
+ from pprint import pformat
+
+ if commands is None: # dump all command option dicts
+ commands = sorted(self.command_options.keys())
+
+ if header is not None:
+ self.announce(indent + header)
+ indent = indent + " "
+
+ if not commands:
+ self.announce(indent + "no commands known yet")
+ return
+
+ for cmd_name in commands:
+ opt_dict = self.command_options.get(cmd_name)
+ if opt_dict is None:
+ self.announce(indent + f"no option dict for '{cmd_name}' command")
+ else:
+ self.announce(indent + f"option dict for '{cmd_name}' command:")
+ out = pformat(opt_dict)
+ for line in out.split('\n'):
+ self.announce(indent + " " + line)
+
+ # -- Config file finding/parsing methods ---------------------------
+
+ def find_config_files(self):
+ """Find as many configuration files as should be processed for this
+ platform, and return a list of filenames in the order in which they
+ should be parsed. The filenames returned are guaranteed to exist
+ (modulo nasty race conditions).
+
+ There are multiple possible config files:
+ - distutils.cfg in the Distutils installation directory (i.e.
+ where the top-level Distutils __inst__.py file lives)
+ - a file in the user's home directory named .pydistutils.cfg
+ on Unix and pydistutils.cfg on Windows/Mac; may be disabled
+ with the ``--no-user-cfg`` option
+ - setup.cfg in the current directory
+ - a file named by an environment variable
+ """
+ check_environ()
+ files = [str(path) for path in self._gen_paths() if os.path.isfile(path)]
+
+ if DEBUG:
+ self.announce("using config files: {}".format(', '.join(files)))
+
+ return files
+
+ def _gen_paths(self):
+ # The system-wide Distutils config file
+ sys_dir = pathlib.Path(sys.modules['distutils'].__file__).parent
+ yield sys_dir / "distutils.cfg"
+
+ # The per-user config file
+ prefix = '.' * (os.name == 'posix')
+ filename = prefix + 'pydistutils.cfg'
+ if self.want_user_cfg:
+ with contextlib.suppress(RuntimeError):
+ yield pathlib.Path('~').expanduser() / filename
+
+ # All platforms support local setup.cfg
+ yield pathlib.Path('setup.cfg')
+
+ # Additional config indicated in the environment
+ with contextlib.suppress(TypeError):
+ yield pathlib.Path(os.getenv("DIST_EXTRA_CONFIG"))
+
+ def parse_config_files(self, filenames=None): # noqa: C901
+ from configparser import ConfigParser
+
+ # Ignore install directory options if we have a venv
+ if sys.prefix != sys.base_prefix:
+ ignore_options = [
+ 'install-base',
+ 'install-platbase',
+ 'install-lib',
+ 'install-platlib',
+ 'install-purelib',
+ 'install-headers',
+ 'install-scripts',
+ 'install-data',
+ 'prefix',
+ 'exec-prefix',
+ 'home',
+ 'user',
+ 'root',
+ ]
+ else:
+ ignore_options = []
+
+ ignore_options = frozenset(ignore_options)
+
+ if filenames is None:
+ filenames = self.find_config_files()
+
+ if DEBUG:
+ self.announce("Distribution.parse_config_files():")
+
+ parser = ConfigParser()
+ for filename in filenames:
+ if DEBUG:
+ self.announce(f" reading {filename}")
+ parser.read(filename, encoding='utf-8')
+ for section in parser.sections():
+ options = parser.options(section)
+ opt_dict = self.get_option_dict(section)
+
+ for opt in options:
+ if opt != '__name__' and opt not in ignore_options:
+ val = parser.get(section, opt)
+ opt = opt.replace('-', '_')
+ opt_dict[opt] = (filename, val)
+
+ # Make the ConfigParser forget everything (so we retain
+ # the original filenames that options come from)
+ parser.__init__()
+
+ # If there was a "global" section in the config file, use it
+ # to set Distribution options.
+
+ if 'global' in self.command_options:
+ for opt, (_src, val) in self.command_options['global'].items():
+ alias = self.negative_opt.get(opt)
+ try:
+ if alias:
+ setattr(self, alias, not strtobool(val))
+ elif opt in ('verbose', 'dry_run'): # ugh!
+ setattr(self, opt, strtobool(val))
+ else:
+ setattr(self, opt, val)
+ except ValueError as msg:
+ raise DistutilsOptionError(msg)
+
+ # -- Command-line parsing methods ----------------------------------
+
+ def parse_command_line(self):
+ """Parse the setup script's command line, taken from the
+ 'script_args' instance attribute (which defaults to 'sys.argv[1:]'
+ -- see 'setup()' in core.py). This list is first processed for
+ "global options" -- options that set attributes of the Distribution
+ instance. Then, it is alternately scanned for Distutils commands
+ and options for that command. Each new command terminates the
+ options for the previous command. The allowed options for a
+ command are determined by the 'user_options' attribute of the
+ command class -- thus, we have to be able to load command classes
+ in order to parse the command line. Any error in that 'options'
+ attribute raises DistutilsGetoptError; any error on the
+ command-line raises DistutilsArgError. If no Distutils commands
+ were found on the command line, raises DistutilsArgError. Return
+ true if command-line was successfully parsed and we should carry
+ on with executing commands; false if no errors but we shouldn't
+ execute commands (currently, this only happens if user asks for
+ help).
+ """
+ #
+ # We now have enough information to show the Macintosh dialog
+ # that allows the user to interactively specify the "command line".
+ #
+ toplevel_options = self._get_toplevel_options()
+
+ # We have to parse the command line a bit at a time -- global
+ # options, then the first command, then its options, and so on --
+ # because each command will be handled by a different class, and
+ # the options that are valid for a particular class aren't known
+ # until we have loaded the command class, which doesn't happen
+ # until we know what the command is.
+
+ self.commands = []
+ parser = FancyGetopt(toplevel_options + self.display_options)
+ parser.set_negative_aliases(self.negative_opt)
+ parser.set_aliases({'licence': 'license'})
+ args = parser.getopt(args=self.script_args, object=self)
+ option_order = parser.get_option_order()
+ logging.getLogger().setLevel(logging.WARN - 10 * self.verbose)
+
+ # for display options we return immediately
+ if self.handle_display_options(option_order):
+ return
+ while args:
+ args = self._parse_command_opts(parser, args)
+ if args is None: # user asked for help (and got it)
+ return
+
+ # Handle the cases of --help as a "global" option, ie.
+ # "setup.py --help" and "setup.py --help command ...". For the
+ # former, we show global options (--verbose, --dry-run, etc.)
+ # and display-only options (--name, --version, etc.); for the
+ # latter, we omit the display-only options and show help for
+ # each command listed on the command line.
+ if self.help:
+ self._show_help(
+ parser, display_options=len(self.commands) == 0, commands=self.commands
+ )
+ return
+
+ # Oops, no commands found -- an end-user error
+ if not self.commands:
+ raise DistutilsArgError("no commands supplied")
+
+ # All is well: return true
+ return True
+
+ def _get_toplevel_options(self):
+ """Return the non-display options recognized at the top level.
+
+ This includes options that are recognized *only* at the top
+ level as well as options recognized for commands.
+ """
+ return self.global_options + [
+ (
+ "command-packages=",
+ None,
+ "list of packages that provide distutils commands",
+ ),
+ ]
+
+ def _parse_command_opts(self, parser, args): # noqa: C901
+ """Parse the command-line options for a single command.
+ 'parser' must be a FancyGetopt instance; 'args' must be the list
+ of arguments, starting with the current command (whose options
+ we are about to parse). Returns a new version of 'args' with
+ the next command at the front of the list; will be the empty
+ list if there are no more commands on the command line. Returns
+ None if the user asked for help on this command.
+ """
+ # late import because of mutual dependence between these modules
+ from distutils.cmd import Command
+
+ # Pull the current command from the head of the command line
+ command = args[0]
+ if not command_re.match(command):
+ raise SystemExit(f"invalid command name '{command}'")
+ self.commands.append(command)
+
+ # Dig up the command class that implements this command, so we
+ # 1) know that it's a valid command, and 2) know which options
+ # it takes.
+ try:
+ cmd_class = self.get_command_class(command)
+ except DistutilsModuleError as msg:
+ raise DistutilsArgError(msg)
+
+ # Require that the command class be derived from Command -- want
+ # to be sure that the basic "command" interface is implemented.
+ if not issubclass(cmd_class, Command):
+ raise DistutilsClassError(
+ f"command class {cmd_class} must subclass Command"
+ )
+
+ # Also make sure that the command object provides a list of its
+ # known options.
+ if not (
+ hasattr(cmd_class, 'user_options')
+ and isinstance(cmd_class.user_options, list)
+ ):
+ msg = (
+ "command class %s must provide "
+ "'user_options' attribute (a list of tuples)"
+ )
+ raise DistutilsClassError(msg % cmd_class)
+
+ # If the command class has a list of negative alias options,
+ # merge it in with the global negative aliases.
+ negative_opt = self.negative_opt
+ if hasattr(cmd_class, 'negative_opt'):
+ negative_opt = negative_opt.copy()
+ negative_opt.update(cmd_class.negative_opt)
+
+ # Check for help_options in command class. They have a different
+ # format (tuple of four) so we need to preprocess them here.
+ if hasattr(cmd_class, 'help_options') and isinstance(
+ cmd_class.help_options, list
+ ):
+ help_options = fix_help_options(cmd_class.help_options)
+ else:
+ help_options = []
+
+ # All commands support the global options too, just by adding
+ # in 'global_options'.
+ parser.set_option_table(
+ self.global_options + cmd_class.user_options + help_options
+ )
+ parser.set_negative_aliases(negative_opt)
+ (args, opts) = parser.getopt(args[1:])
+ if hasattr(opts, 'help') and opts.help:
+ self._show_help(parser, display_options=False, commands=[cmd_class])
+ return
+
+ if hasattr(cmd_class, 'help_options') and isinstance(
+ cmd_class.help_options, list
+ ):
+ help_option_found = 0
+ for help_option, _short, _desc, func in cmd_class.help_options:
+ if hasattr(opts, parser.get_attr_name(help_option)):
+ help_option_found = 1
+ if callable(func):
+ func()
+ else:
+ raise DistutilsClassError(
+ f"invalid help function {func!r} for help option '{help_option}': "
+ "must be a callable object (function, etc.)"
+ )
+
+ if help_option_found:
+ return
+
+ # Put the options from the command-line into their official
+ # holding pen, the 'command_options' dictionary.
+ opt_dict = self.get_option_dict(command)
+ for name, value in vars(opts).items():
+ opt_dict[name] = ("command line", value)
+
+ return args
+
+ def finalize_options(self) -> None:
+ """Set final values for all the options on the Distribution
+ instance, analogous to the .finalize_options() method of Command
+ objects.
+ """
+ for attr in ('keywords', 'platforms'):
+ value = getattr(self.metadata, attr)
+ if value is None:
+ continue
+ if isinstance(value, str):
+ value = [elm.strip() for elm in value.split(',')]
+ setattr(self.metadata, attr, value)
+
+ def _show_help(
+ self, parser, global_options=True, display_options=True, commands: Iterable = ()
+ ):
+ """Show help for the setup script command-line in the form of
+ several lists of command-line options. 'parser' should be a
+ FancyGetopt instance; do not expect it to be returned in the
+ same state, as its option table will be reset to make it
+ generate the correct help text.
+
+ If 'global_options' is true, lists the global options:
+ --verbose, --dry-run, etc. If 'display_options' is true, lists
+ the "display-only" options: --name, --version, etc. Finally,
+ lists per-command help for every command name or command class
+ in 'commands'.
+ """
+ # late import because of mutual dependence between these modules
+ from distutils.cmd import Command
+ from distutils.core import gen_usage
+
+ if global_options:
+ if display_options:
+ options = self._get_toplevel_options()
+ else:
+ options = self.global_options
+ parser.set_option_table(options)
+ parser.print_help(self.common_usage + "\nGlobal options:")
+ print()
+
+ if display_options:
+ parser.set_option_table(self.display_options)
+ parser.print_help(
+ "Information display options (just display information, ignore any commands)"
+ )
+ print()
+
+ for command in commands:
+ if isinstance(command, type) and issubclass(command, Command):
+ klass = command
+ else:
+ klass = self.get_command_class(command)
+ if hasattr(klass, 'help_options') and isinstance(klass.help_options, list):
+ parser.set_option_table(
+ klass.user_options + fix_help_options(klass.help_options)
+ )
+ else:
+ parser.set_option_table(klass.user_options)
+ parser.print_help(f"Options for '{klass.__name__}' command:")
+ print()
+
+ print(gen_usage(self.script_name))
+
+ def handle_display_options(self, option_order):
+ """If there were any non-global "display-only" options
+ (--help-commands or the metadata display options) on the command
+ line, display the requested info and return true; else return
+ false.
+ """
+ from distutils.core import gen_usage
+
+ # User just wants a list of commands -- we'll print it out and stop
+ # processing now (ie. if they ran "setup --help-commands foo bar",
+ # we ignore "foo bar").
+ if self.help_commands:
+ self.print_commands()
+ print()
+ print(gen_usage(self.script_name))
+ return 1
+
+ # If user supplied any of the "display metadata" options, then
+ # display that metadata in the order in which the user supplied the
+ # metadata options.
+ any_display_options = 0
+ is_display_option = set()
+ for option in self.display_options:
+ is_display_option.add(option[0])
+
+ for opt, val in option_order:
+ if val and opt in is_display_option:
+ opt = translate_longopt(opt)
+ value = getattr(self.metadata, "get_" + opt)()
+ if opt in ('keywords', 'platforms'):
+ print(','.join(value))
+ elif opt in ('classifiers', 'provides', 'requires', 'obsoletes'):
+ print('\n'.join(value))
+ else:
+ print(value)
+ any_display_options = 1
+
+ return any_display_options
+
+ def print_command_list(self, commands, header, max_length) -> None:
+ """Print a subset of the list of all commands -- used by
+ 'print_commands()'.
+ """
+ print(header + ":")
+
+ for cmd in commands:
+ klass = self.cmdclass.get(cmd)
+ if not klass:
+ klass = self.get_command_class(cmd)
+ try:
+ description = klass.description
+ except AttributeError:
+ description = "(no description available)"
+
+ print(f" {cmd:<{max_length}} {description}")
+
+ def print_commands(self) -> None:
+ """Print out a help message listing all available commands with a
+ description of each. The list is divided into "standard commands"
+ (listed in distutils.command.__all__) and "extra commands"
+ (mentioned in self.cmdclass, but not a standard command). The
+ descriptions come from the command class attribute
+ 'description'.
+ """
+ import distutils.command
+
+ std_commands = distutils.command.__all__
+ is_std = set(std_commands)
+
+ extra_commands = [cmd for cmd in self.cmdclass.keys() if cmd not in is_std]
+
+ max_length = 0
+ for cmd in std_commands + extra_commands:
+ if len(cmd) > max_length:
+ max_length = len(cmd)
+
+ self.print_command_list(std_commands, "Standard commands", max_length)
+ if extra_commands:
+ print()
+ self.print_command_list(extra_commands, "Extra commands", max_length)
+
+ def get_command_list(self):
+ """Get a list of (command, description) tuples.
+ The list is divided into "standard commands" (listed in
+ distutils.command.__all__) and "extra commands" (mentioned in
+ self.cmdclass, but not a standard command). The descriptions come
+ from the command class attribute 'description'.
+ """
+ # Currently this is only used on Mac OS, for the Mac-only GUI
+ # Distutils interface (by Jack Jansen)
+ import distutils.command
+
+ std_commands = distutils.command.__all__
+ is_std = set(std_commands)
+
+ extra_commands = [cmd for cmd in self.cmdclass.keys() if cmd not in is_std]
+
+ rv = []
+ for cmd in std_commands + extra_commands:
+ klass = self.cmdclass.get(cmd)
+ if not klass:
+ klass = self.get_command_class(cmd)
+ try:
+ description = klass.description
+ except AttributeError:
+ description = "(no description available)"
+ rv.append((cmd, description))
+ return rv
+
+ # -- Command class/object methods ----------------------------------
+
+ def get_command_packages(self):
+ """Return a list of packages from which commands are loaded."""
+ pkgs = self.command_packages
+ if not isinstance(pkgs, list):
+ if pkgs is None:
+ pkgs = ''
+ pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != '']
+ if "distutils.command" not in pkgs:
+ pkgs.insert(0, "distutils.command")
+ self.command_packages = pkgs
+ return pkgs
+
+ def get_command_class(self, command: str) -> type[Command]:
+ """Return the class that implements the Distutils command named by
+ 'command'. First we check the 'cmdclass' dictionary; if the
+ command is mentioned there, we fetch the class object from the
+ dictionary and return it. Otherwise we load the command module
+ ("distutils.command." + command) and fetch the command class from
+ the module. The loaded class is also stored in 'cmdclass'
+ to speed future calls to 'get_command_class()'.
+
+ Raises DistutilsModuleError if the expected module could not be
+ found, or if that module does not define the expected class.
+ """
+ klass = self.cmdclass.get(command)
+ if klass:
+ return klass
+
+ for pkgname in self.get_command_packages():
+ module_name = f"{pkgname}.{command}"
+ klass_name = command
+
+ try:
+ __import__(module_name)
+ module = sys.modules[module_name]
+ except ImportError:
+ continue
+
+ try:
+ klass = getattr(module, klass_name)
+ except AttributeError:
+ raise DistutilsModuleError(
+ f"invalid command '{command}' (no class '{klass_name}' in module '{module_name}')"
+ )
+
+ self.cmdclass[command] = klass
+ return klass
+
+ raise DistutilsModuleError(f"invalid command '{command}'")
+
+ @overload
+ def get_command_obj(
+ self, command: str, create: Literal[True] = True
+ ) -> Command: ...
+ @overload
+ def get_command_obj(
+ self, command: str, create: Literal[False]
+ ) -> Command | None: ...
+ def get_command_obj(self, command: str, create: bool = True) -> Command | None:
+ """Return the command object for 'command'. Normally this object
+ is cached on a previous call to 'get_command_obj()'; if no command
+ object for 'command' is in the cache, then we either create and
+ return it (if 'create' is true) or return None.
+ """
+ cmd_obj = self.command_obj.get(command)
+ if not cmd_obj and create:
+ if DEBUG:
+ self.announce(
+ "Distribution.get_command_obj(): "
+ f"creating '{command}' command object"
+ )
+
+ klass = self.get_command_class(command)
+ cmd_obj = self.command_obj[command] = klass(self)
+ self.have_run[command] = False
+
+ # Set any options that were supplied in config files
+ # or on the command line. (NB. support for error
+ # reporting is lame here: any errors aren't reported
+ # until 'finalize_options()' is called, which means
+ # we won't report the source of the error.)
+ options = self.command_options.get(command)
+ if options:
+ self._set_command_options(cmd_obj, options)
+
+ return cmd_obj
+
+ def _set_command_options(self, command_obj, option_dict=None): # noqa: C901
+ """Set the options for 'command_obj' from 'option_dict'. Basically
+ this means copying elements of a dictionary ('option_dict') to
+ attributes of an instance ('command').
+
+ 'command_obj' must be a Command instance. If 'option_dict' is not
+ supplied, uses the standard option dictionary for this command
+ (from 'self.command_options').
+ """
+ command_name = command_obj.get_command_name()
+ if option_dict is None:
+ option_dict = self.get_option_dict(command_name)
+
+ if DEBUG:
+ self.announce(f" setting options for '{command_name}' command:")
+ for option, (source, value) in option_dict.items():
+ if DEBUG:
+ self.announce(f" {option} = {value} (from {source})")
+ try:
+ bool_opts = [translate_longopt(o) for o in command_obj.boolean_options]
+ except AttributeError:
+ bool_opts = []
+ try:
+ neg_opt = command_obj.negative_opt
+ except AttributeError:
+ neg_opt = {}
+
+ try:
+ is_string = isinstance(value, str)
+ if option in neg_opt and is_string:
+ setattr(command_obj, neg_opt[option], not strtobool(value))
+ elif option in bool_opts and is_string:
+ setattr(command_obj, option, strtobool(value))
+ elif hasattr(command_obj, option):
+ setattr(command_obj, option, value)
+ else:
+ raise DistutilsOptionError(
+ f"error in {source}: command '{command_name}' has no such option '{option}'"
+ )
+ except ValueError as msg:
+ raise DistutilsOptionError(msg)
+
+ @overload
+ def reinitialize_command(
+ self, command: str, reinit_subcommands: bool = False
+ ) -> Command: ...
+ @overload
+ def reinitialize_command(
+ self, command: _CommandT, reinit_subcommands: bool = False
+ ) -> _CommandT: ...
+ def reinitialize_command(
+ self, command: str | Command, reinit_subcommands=False
+ ) -> Command:
+ """Reinitializes a command to the state it was in when first
+ returned by 'get_command_obj()': ie., initialized but not yet
+ finalized. This provides the opportunity to sneak option
+ values in programmatically, overriding or supplementing
+ user-supplied values from the config files and command line.
+ You'll have to re-finalize the command object (by calling
+ 'finalize_options()' or 'ensure_finalized()') before using it for
+ real.
+
+ 'command' should be a command name (string) or command object. If
+ 'reinit_subcommands' is true, also reinitializes the command's
+ sub-commands, as declared by the 'sub_commands' class attribute (if
+ it has one). See the "install" command for an example. Only
+ reinitializes the sub-commands that actually matter, ie. those
+ whose test predicates return true.
+
+ Returns the reinitialized command object.
+ """
+ from distutils.cmd import Command
+
+ if not isinstance(command, Command):
+ command_name = command
+ command = self.get_command_obj(command_name)
+ else:
+ command_name = command.get_command_name()
+
+ if not command.finalized:
+ return command
+ command.initialize_options()
+ command.finalized = False
+ self.have_run[command_name] = False
+ self._set_command_options(command)
+
+ if reinit_subcommands:
+ for sub in command.get_sub_commands():
+ self.reinitialize_command(sub, reinit_subcommands)
+
+ return command
+
+ # -- Methods that operate on the Distribution ----------------------
+
+ def announce(self, msg, level: int = logging.INFO) -> None:
+ log.log(level, msg)
+
+ def run_commands(self) -> None:
+ """Run each command that was seen on the setup script command line.
+ Uses the list of commands found and cache of command objects
+ created by 'get_command_obj()'.
+ """
+ for cmd in self.commands:
+ self.run_command(cmd)
+
+ # -- Methods that operate on its Commands --------------------------
+
+ def run_command(self, command: str) -> None:
+ """Do whatever it takes to run a command (including nothing at all,
+ if the command has already been run). Specifically: if we have
+ already created and run the command named by 'command', return
+ silently without doing anything. If the command named by 'command'
+ doesn't even have a command object yet, create one. Then invoke
+ 'run()' on that command object (or an existing one).
+ """
+ # Already been here, done that? then return silently.
+ if self.have_run.get(command):
+ return
+
+ log.info("running %s", command)
+ cmd_obj = self.get_command_obj(command)
+ cmd_obj.ensure_finalized()
+ cmd_obj.run()
+ self.have_run[command] = True
+
+ # -- Distribution query methods ------------------------------------
+
+ def has_pure_modules(self) -> bool:
+ return len(self.packages or self.py_modules or []) > 0
+
+ def has_ext_modules(self) -> bool:
+ return self.ext_modules and len(self.ext_modules) > 0
+
+ def has_c_libraries(self) -> bool:
+ return self.libraries and len(self.libraries) > 0
+
+ def has_modules(self) -> bool:
+ return self.has_pure_modules() or self.has_ext_modules()
+
+ def has_headers(self) -> bool:
+ return self.headers and len(self.headers) > 0
+
+ def has_scripts(self) -> bool:
+ return self.scripts and len(self.scripts) > 0
+
+ def has_data_files(self) -> bool:
+ return self.data_files and len(self.data_files) > 0
+
+ def is_pure(self) -> bool:
+ return (
+ self.has_pure_modules()
+ and not self.has_ext_modules()
+ and not self.has_c_libraries()
+ )
+
+ # -- Metadata query methods ----------------------------------------
+
+ # If you're looking for 'get_name()', 'get_version()', and so forth,
+ # they are defined in a sneaky way: the constructor binds self.get_XXX
+ # to self.metadata.get_XXX. The actual code is in the
+ # DistributionMetadata class, below.
+ if TYPE_CHECKING:
+ # Unfortunately this means we need to specify them manually or not expose statically
+ def _(self) -> None:
+ self.get_name = self.metadata.get_name
+ self.get_version = self.metadata.get_version
+ self.get_fullname = self.metadata.get_fullname
+ self.get_author = self.metadata.get_author
+ self.get_author_email = self.metadata.get_author_email
+ self.get_maintainer = self.metadata.get_maintainer
+ self.get_maintainer_email = self.metadata.get_maintainer_email
+ self.get_contact = self.metadata.get_contact
+ self.get_contact_email = self.metadata.get_contact_email
+ self.get_url = self.metadata.get_url
+ self.get_license = self.metadata.get_license
+ self.get_licence = self.metadata.get_licence
+ self.get_description = self.metadata.get_description
+ self.get_long_description = self.metadata.get_long_description
+ self.get_keywords = self.metadata.get_keywords
+ self.get_platforms = self.metadata.get_platforms
+ self.get_classifiers = self.metadata.get_classifiers
+ self.get_download_url = self.metadata.get_download_url
+ self.get_requires = self.metadata.get_requires
+ self.get_provides = self.metadata.get_provides
+ self.get_obsoletes = self.metadata.get_obsoletes
+
+ # Default attributes generated in __init__ from self.display_option_names
+ help_commands: bool
+ name: str | Literal[False]
+ version: str | Literal[False]
+ fullname: str | Literal[False]
+ author: str | Literal[False]
+ author_email: str | Literal[False]
+ maintainer: str | Literal[False]
+ maintainer_email: str | Literal[False]
+ contact: str | Literal[False]
+ contact_email: str | Literal[False]
+ url: str | Literal[False]
+ license: str | Literal[False]
+ licence: str | Literal[False]
+ description: str | Literal[False]
+ long_description: str | Literal[False]
+ platforms: str | list[str] | Literal[False]
+ classifiers: str | list[str] | Literal[False]
+ keywords: str | list[str] | Literal[False]
+ provides: list[str] | Literal[False]
+ requires: list[str] | Literal[False]
+ obsoletes: list[str] | Literal[False]
+
+
+class DistributionMetadata:
+ """Dummy class to hold the distribution meta-data: name, version,
+ author, and so forth.
+ """
+
+ _METHOD_BASENAMES = (
+ "name",
+ "version",
+ "author",
+ "author_email",
+ "maintainer",
+ "maintainer_email",
+ "url",
+ "license",
+ "description",
+ "long_description",
+ "keywords",
+ "platforms",
+ "fullname",
+ "contact",
+ "contact_email",
+ "classifiers",
+ "download_url",
+ # PEP 314
+ "provides",
+ "requires",
+ "obsoletes",
+ )
+
+ def __init__(
+ self, path: str | bytes | os.PathLike[str] | os.PathLike[bytes] | None = None
+ ) -> None:
+ if path is not None:
+ self.read_pkg_file(open(path))
+ else:
+ self.name: str | None = None
+ self.version: str | None = None
+ self.author: str | None = None
+ self.author_email: str | None = None
+ self.maintainer: str | None = None
+ self.maintainer_email: str | None = None
+ self.url: str | None = None
+ self.license: str | None = None
+ self.description: str | None = None
+ self.long_description: str | None = None
+ self.keywords: str | list[str] | None = None
+ self.platforms: str | list[str] | None = None
+ self.classifiers: str | list[str] | None = None
+ self.download_url: str | None = None
+ # PEP 314
+ self.provides: str | list[str] | None = None
+ self.requires: str | list[str] | None = None
+ self.obsoletes: str | list[str] | None = None
+
+ def read_pkg_file(self, file: IO[str]) -> None:
+ """Reads the metadata values from a file object."""
+ msg = message_from_file(file)
+
+ def _read_field(name: str) -> str | None:
+ value = msg[name]
+ if value and value != "UNKNOWN":
+ return value
+ return None
+
+ def _read_list(name):
+ values = msg.get_all(name, None)
+ if values == []:
+ return None
+ return values
+
+ metadata_version = msg['metadata-version']
+ self.name = _read_field('name')
+ self.version = _read_field('version')
+ self.description = _read_field('summary')
+ # we are filling author only.
+ self.author = _read_field('author')
+ self.maintainer = None
+ self.author_email = _read_field('author-email')
+ self.maintainer_email = None
+ self.url = _read_field('home-page')
+ self.license = _read_field('license')
+
+ if 'download-url' in msg:
+ self.download_url = _read_field('download-url')
+ else:
+ self.download_url = None
+
+ self.long_description = _read_field('description')
+ self.description = _read_field('summary')
+
+ if 'keywords' in msg:
+ self.keywords = _read_field('keywords').split(',')
+
+ self.platforms = _read_list('platform')
+ self.classifiers = _read_list('classifier')
+
+ # PEP 314 - these fields only exist in 1.1
+ if metadata_version == '1.1':
+ self.requires = _read_list('requires')
+ self.provides = _read_list('provides')
+ self.obsoletes = _read_list('obsoletes')
+ else:
+ self.requires = None
+ self.provides = None
+ self.obsoletes = None
+
+ def write_pkg_info(self, base_dir: str | os.PathLike[str]) -> None:
+ """Write the PKG-INFO file into the release tree."""
+ with open(
+ os.path.join(base_dir, 'PKG-INFO'), 'w', encoding='UTF-8'
+ ) as pkg_info:
+ self.write_pkg_file(pkg_info)
+
+ def write_pkg_file(self, file: SupportsWrite[str]) -> None:
+ """Write the PKG-INFO format data to a file object."""
+ version = '1.0'
+ if (
+ self.provides
+ or self.requires
+ or self.obsoletes
+ or self.classifiers
+ or self.download_url
+ ):
+ version = '1.1'
+
+ # required fields
+ file.write(f'Metadata-Version: {version}\n')
+ file.write(f'Name: {self.get_name()}\n')
+ file.write(f'Version: {self.get_version()}\n')
+
+ def maybe_write(header, val):
+ if val:
+ file.write(f"{header}: {val}\n")
+
+ # optional fields
+ maybe_write("Summary", self.get_description())
+ maybe_write("Home-page", self.get_url())
+ maybe_write("Author", self.get_contact())
+ maybe_write("Author-email", self.get_contact_email())
+ maybe_write("License", self.get_license())
+ maybe_write("Download-URL", self.download_url)
+ maybe_write("Description", rfc822_escape(self.get_long_description() or ""))
+ maybe_write("Keywords", ",".join(self.get_keywords()))
+
+ self._write_list(file, 'Platform', self.get_platforms())
+ self._write_list(file, 'Classifier', self.get_classifiers())
+
+ # PEP 314
+ self._write_list(file, 'Requires', self.get_requires())
+ self._write_list(file, 'Provides', self.get_provides())
+ self._write_list(file, 'Obsoletes', self.get_obsoletes())
+
+ def _write_list(self, file, name, values):
+ values = values or []
+ for value in values:
+ file.write(f'{name}: {value}\n')
+
+ # -- Metadata query methods ----------------------------------------
+
+ def get_name(self) -> str:
+ return self.name or "UNKNOWN"
+
+ def get_version(self) -> str:
+ return self.version or "0.0.0"
+
+ def get_fullname(self) -> str:
+ return self._fullname(self.get_name(), self.get_version())
+
+ @staticmethod
+ def _fullname(name: str, version: str) -> str:
+ """
+ >>> DistributionMetadata._fullname('setup.tools', '1.0-2')
+ 'setup_tools-1.0.post2'
+ >>> DistributionMetadata._fullname('setup-tools', '1.2post2')
+ 'setup_tools-1.2.post2'
+ >>> DistributionMetadata._fullname('setup-tools', '1.0-r2')
+ 'setup_tools-1.0.post2'
+ >>> DistributionMetadata._fullname('setup.tools', '1.0.post')
+ 'setup_tools-1.0.post0'
+ >>> DistributionMetadata._fullname('setup.tools', '1.0+ubuntu-1')
+ 'setup_tools-1.0+ubuntu.1'
+ """
+ return "{}-{}".format(
+ canonicalize_name(name).replace('-', '_'),
+ canonicalize_version(version, strip_trailing_zero=False),
+ )
+
+ def get_author(self) -> str | None:
+ return self.author
+
+ def get_author_email(self) -> str | None:
+ return self.author_email
+
+ def get_maintainer(self) -> str | None:
+ return self.maintainer
+
+ def get_maintainer_email(self) -> str | None:
+ return self.maintainer_email
+
+ def get_contact(self) -> str | None:
+ return self.maintainer or self.author
+
+ def get_contact_email(self) -> str | None:
+ return self.maintainer_email or self.author_email
+
+ def get_url(self) -> str | None:
+ return self.url
+
+ def get_license(self) -> str | None:
+ return self.license
+
+ get_licence = get_license
+
+ def get_description(self) -> str | None:
+ return self.description
+
+ def get_long_description(self) -> str | None:
+ return self.long_description
+
+ def get_keywords(self) -> str | list[str]:
+ return self.keywords or []
+
+ def set_keywords(self, value: str | Iterable[str]) -> None:
+ self.keywords = _ensure_list(value, 'keywords')
+
+ def get_platforms(self) -> str | list[str] | None:
+ return self.platforms
+
+ def set_platforms(self, value: str | Iterable[str]) -> None:
+ self.platforms = _ensure_list(value, 'platforms')
+
+ def get_classifiers(self) -> str | list[str]:
+ return self.classifiers or []
+
+ def set_classifiers(self, value: str | Iterable[str]) -> None:
+ self.classifiers = _ensure_list(value, 'classifiers')
+
+ def get_download_url(self) -> str | None:
+ return self.download_url
+
+ # PEP 314
+ def get_requires(self) -> str | list[str]:
+ return self.requires or []
+
+ def set_requires(self, value: Iterable[str]) -> None:
+ import distutils.versionpredicate
+
+ for v in value:
+ distutils.versionpredicate.VersionPredicate(v)
+ self.requires = list(value)
+
+ def get_provides(self) -> str | list[str]:
+ return self.provides or []
+
+ def set_provides(self, value: Iterable[str]) -> None:
+ value = [v.strip() for v in value]
+ for v in value:
+ import distutils.versionpredicate
+
+ distutils.versionpredicate.split_provision(v)
+ self.provides = value
+
+ def get_obsoletes(self) -> str | list[str]:
+ return self.obsoletes or []
+
+ def set_obsoletes(self, value: Iterable[str]) -> None:
+ import distutils.versionpredicate
+
+ for v in value:
+ distutils.versionpredicate.VersionPredicate(v)
+ self.obsoletes = list(value)
+
+
+def fix_help_options(options):
+ """Convert a 4-tuple 'help_options' list as found in various command
+ classes to the 3-tuple form required by FancyGetopt.
+ """
+ return [opt[0:3] for opt in options]
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/errors.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/errors.py
new file mode 100644
index 0000000..409d21f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/errors.py
@@ -0,0 +1,108 @@
+"""
+Exceptions used by the Distutils modules.
+
+Distutils modules may raise these or standard exceptions,
+including :exc:`SystemExit`.
+"""
+
+# compiler exceptions aliased for compatibility
+from .compilers.C.errors import CompileError as CompileError
+from .compilers.C.errors import Error as _Error
+from .compilers.C.errors import LibError as LibError
+from .compilers.C.errors import LinkError as LinkError
+from .compilers.C.errors import PreprocessError as PreprocessError
+from .compilers.C.errors import UnknownFileType as _UnknownFileType
+
+CCompilerError = _Error
+UnknownFileError = _UnknownFileType
+
+
+class DistutilsError(Exception):
+ """The root of all Distutils evil."""
+
+ pass
+
+
+class DistutilsModuleError(DistutilsError):
+ """Unable to load an expected module, or to find an expected class
+ within some module (in particular, command modules and classes)."""
+
+ pass
+
+
+class DistutilsClassError(DistutilsError):
+ """Some command class (or possibly distribution class, if anyone
+ feels a need to subclass Distribution) is found not to be holding
+ up its end of the bargain, ie. implementing some part of the
+ "command "interface."""
+
+ pass
+
+
+class DistutilsGetoptError(DistutilsError):
+ """The option table provided to 'fancy_getopt()' is bogus."""
+
+ pass
+
+
+class DistutilsArgError(DistutilsError):
+ """Raised by fancy_getopt in response to getopt.error -- ie. an
+ error in the command line usage."""
+
+ pass
+
+
+class DistutilsFileError(DistutilsError):
+ """Any problems in the filesystem: expected file not found, etc.
+ Typically this is for problems that we detect before OSError
+ could be raised."""
+
+ pass
+
+
+class DistutilsOptionError(DistutilsError):
+ """Syntactic/semantic errors in command options, such as use of
+ mutually conflicting options, or inconsistent options,
+ badly-spelled values, etc. No distinction is made between option
+ values originating in the setup script, the command line, config
+ files, or what-have-you -- but if we *know* something originated in
+ the setup script, we'll raise DistutilsSetupError instead."""
+
+ pass
+
+
+class DistutilsSetupError(DistutilsError):
+ """For errors that can be definitely blamed on the setup script,
+ such as invalid keyword arguments to 'setup()'."""
+
+ pass
+
+
+class DistutilsPlatformError(DistutilsError):
+ """We don't know how to do something on the current platform (but
+ we do know how to do it on some platform) -- eg. trying to compile
+ C files on a platform not supported by a CCompiler subclass."""
+
+ pass
+
+
+class DistutilsExecError(DistutilsError):
+ """Any problems executing an external program (such as the C
+ compiler, when compiling C files)."""
+
+ pass
+
+
+class DistutilsInternalError(DistutilsError):
+ """Internal inconsistencies or impossibilities (obviously, this
+ should never be seen if the code is working!)."""
+
+ pass
+
+
+class DistutilsTemplateError(DistutilsError):
+ """Syntax error in a file list template."""
+
+
+class DistutilsByteCompileError(DistutilsError):
+ """Byte compile error."""
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/extension.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/extension.py
new file mode 100644
index 0000000..f514112
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/extension.py
@@ -0,0 +1,258 @@
+"""distutils.extension
+
+Provides the Extension class, used to describe C/C++ extension
+modules in setup scripts."""
+
+from __future__ import annotations
+
+import os
+import warnings
+from collections.abc import Iterable
+
+# This class is really only used by the "build_ext" command, so it might
+# make sense to put it in distutils.command.build_ext. However, that
+# module is already big enough, and I want to make this class a bit more
+# complex to simplify some common cases ("foo" module in "foo.c") and do
+# better error-checking ("foo.c" actually exists).
+#
+# Also, putting this in build_ext.py means every setup script would have to
+# import that large-ish module (indirectly, through distutils.core) in
+# order to do anything.
+
+
+class Extension:
+ """Just a collection of attributes that describes an extension
+ module and everything needed to build it (hopefully in a portable
+ way, but there are hooks that let you be as unportable as you need).
+
+ Instance attributes:
+ name : string
+ the full name of the extension, including any packages -- ie.
+ *not* a filename or pathname, but Python dotted name
+ sources : Iterable[string | os.PathLike]
+ iterable of source filenames (except strings, which could be misinterpreted
+ as a single filename), relative to the distribution root (where the setup
+ script lives), in Unix form (slash-separated) for portability. Can be any
+ non-string iterable (list, tuple, set, etc.) containing strings or
+ PathLike objects. Source files may be C, C++, SWIG (.i), platform-specific
+ resource files, or whatever else is recognized by the "build_ext" command
+ as source for a Python extension.
+ include_dirs : [string]
+ list of directories to search for C/C++ header files (in Unix
+ form for portability)
+ define_macros : [(name : string, value : string|None)]
+ list of macros to define; each macro is defined using a 2-tuple,
+ where 'value' is either the string to define it to or None to
+ define it without a particular value (equivalent of "#define
+ FOO" in source or -DFOO on Unix C compiler command line)
+ undef_macros : [string]
+ list of macros to undefine explicitly
+ library_dirs : [string]
+ list of directories to search for C/C++ libraries at link time
+ libraries : [string]
+ list of library names (not filenames or paths) to link against
+ runtime_library_dirs : [string]
+ list of directories to search for C/C++ libraries at run time
+ (for shared extensions, this is when the extension is loaded)
+ extra_objects : [string]
+ list of extra files to link with (eg. object files not implied
+ by 'sources', static library that must be explicitly specified,
+ binary resource files, etc.)
+ extra_compile_args : [string]
+ any extra platform- and compiler-specific information to use
+ when compiling the source files in 'sources'. For platforms and
+ compilers where "command line" makes sense, this is typically a
+ list of command-line arguments, but for other platforms it could
+ be anything.
+ extra_link_args : [string]
+ any extra platform- and compiler-specific information to use
+ when linking object files together to create the extension (or
+ to create a new static Python interpreter). Similar
+ interpretation as for 'extra_compile_args'.
+ export_symbols : [string]
+ list of symbols to be exported from a shared extension. Not
+ used on all platforms, and not generally necessary for Python
+ extensions, which typically export exactly one symbol: "init" +
+ extension_name.
+ swig_opts : [string]
+ any extra options to pass to SWIG if a source file has the .i
+ extension.
+ depends : [string]
+ list of files that the extension depends on
+ language : string
+ extension language (i.e. "c", "c++", "objc"). Will be detected
+ from the source extensions if not provided.
+ optional : boolean
+ specifies that a build failure in the extension should not abort the
+ build process, but simply not install the failing extension.
+ """
+
+ # When adding arguments to this constructor, be sure to update
+ # setup_keywords in core.py.
+ def __init__(
+ self,
+ name: str,
+ sources: Iterable[str | os.PathLike[str]],
+ include_dirs: list[str] | None = None,
+ define_macros: list[tuple[str, str | None]] | None = None,
+ undef_macros: list[str] | None = None,
+ library_dirs: list[str] | None = None,
+ libraries: list[str] | None = None,
+ runtime_library_dirs: list[str] | None = None,
+ extra_objects: list[str] | None = None,
+ extra_compile_args: list[str] | None = None,
+ extra_link_args: list[str] | None = None,
+ export_symbols: list[str] | None = None,
+ swig_opts: list[str] | None = None,
+ depends: list[str] | None = None,
+ language: str | None = None,
+ optional: bool | None = None,
+ **kw, # To catch unknown keywords
+ ):
+ if not isinstance(name, str):
+ raise TypeError("'name' must be a string")
+
+ # handle the string case first; since strings are iterable, disallow them
+ if isinstance(sources, str):
+ raise TypeError(
+ "'sources' must be an iterable of strings or PathLike objects, not a string"
+ )
+
+ # now we check if it's iterable and contains valid types
+ try:
+ self.sources = list(map(os.fspath, sources))
+ except TypeError:
+ raise TypeError(
+ "'sources' must be an iterable of strings or PathLike objects"
+ )
+
+ self.name = name
+ self.include_dirs = include_dirs or []
+ self.define_macros = define_macros or []
+ self.undef_macros = undef_macros or []
+ self.library_dirs = library_dirs or []
+ self.libraries = libraries or []
+ self.runtime_library_dirs = runtime_library_dirs or []
+ self.extra_objects = extra_objects or []
+ self.extra_compile_args = extra_compile_args or []
+ self.extra_link_args = extra_link_args or []
+ self.export_symbols = export_symbols or []
+ self.swig_opts = swig_opts or []
+ self.depends = depends or []
+ self.language = language
+ self.optional = optional
+
+ # If there are unknown keyword options, warn about them
+ if len(kw) > 0:
+ options = [repr(option) for option in kw]
+ options = ', '.join(sorted(options))
+ msg = f"Unknown Extension options: {options}"
+ warnings.warn(msg)
+
+ def __repr__(self):
+ return f'<{self.__class__.__module__}.{self.__class__.__qualname__}({self.name!r}) at {id(self):#x}>'
+
+
+def read_setup_file(filename): # noqa: C901
+ """Reads a Setup file and returns Extension instances."""
+ from distutils.sysconfig import _variable_rx, expand_makefile_vars, parse_makefile
+ from distutils.text_file import TextFile
+ from distutils.util import split_quoted
+
+ # First pass over the file to gather "VAR = VALUE" assignments.
+ vars = parse_makefile(filename)
+
+ # Second pass to gobble up the real content: lines of the form
+ # ... [ ...] [ ...] [ ...]
+ file = TextFile(
+ filename,
+ strip_comments=True,
+ skip_blanks=True,
+ join_lines=True,
+ lstrip_ws=True,
+ rstrip_ws=True,
+ )
+ try:
+ extensions = []
+
+ while True:
+ line = file.readline()
+ if line is None: # eof
+ break
+ if _variable_rx.match(line): # VAR=VALUE, handled in first pass
+ continue
+
+ if line[0] == line[-1] == "*":
+ file.warn(f"'{line}' lines not handled yet")
+ continue
+
+ line = expand_makefile_vars(line, vars)
+ words = split_quoted(line)
+
+ # NB. this parses a slightly different syntax than the old
+ # makesetup script: here, there must be exactly one extension per
+ # line, and it must be the first word of the line. I have no idea
+ # why the old syntax supported multiple extensions per line, as
+ # they all wind up being the same.
+
+ module = words[0]
+ ext = Extension(module, [])
+ append_next_word = None
+
+ for word in words[1:]:
+ if append_next_word is not None:
+ append_next_word.append(word)
+ append_next_word = None
+ continue
+
+ suffix = os.path.splitext(word)[1]
+ switch = word[0:2]
+ value = word[2:]
+
+ if suffix in (".c", ".cc", ".cpp", ".cxx", ".c++", ".m", ".mm"):
+ # hmm, should we do something about C vs. C++ sources?
+ # or leave it up to the CCompiler implementation to
+ # worry about?
+ ext.sources.append(word)
+ elif switch == "-I":
+ ext.include_dirs.append(value)
+ elif switch == "-D":
+ equals = value.find("=")
+ if equals == -1: # bare "-DFOO" -- no value
+ ext.define_macros.append((value, None))
+ else: # "-DFOO=blah"
+ ext.define_macros.append((value[0:equals], value[equals + 2 :]))
+ elif switch == "-U":
+ ext.undef_macros.append(value)
+ elif switch == "-C": # only here 'cause makesetup has it!
+ ext.extra_compile_args.append(word)
+ elif switch == "-l":
+ ext.libraries.append(value)
+ elif switch == "-L":
+ ext.library_dirs.append(value)
+ elif switch == "-R":
+ ext.runtime_library_dirs.append(value)
+ elif word == "-rpath":
+ append_next_word = ext.runtime_library_dirs
+ elif word == "-Xlinker":
+ append_next_word = ext.extra_link_args
+ elif word == "-Xcompiler":
+ append_next_word = ext.extra_compile_args
+ elif switch == "-u":
+ ext.extra_link_args.append(word)
+ if not value:
+ append_next_word = ext.extra_link_args
+ elif suffix in (".a", ".so", ".sl", ".o", ".dylib"):
+ # NB. a really faithful emulation of makesetup would
+ # append a .o file to extra_objects only if it
+ # had a slash in it; otherwise, it would s/.o/.c/
+ # and append it to sources. Hmmmm.
+ ext.extra_objects.append(word)
+ else:
+ file.warn(f"unrecognized argument '{word}'")
+
+ extensions.append(ext)
+ finally:
+ file.close()
+
+ return extensions
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/fancy_getopt.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/fancy_getopt.py
new file mode 100644
index 0000000..1a1d3a0
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/fancy_getopt.py
@@ -0,0 +1,471 @@
+"""distutils.fancy_getopt
+
+Wrapper around the standard getopt module that provides the following
+additional features:
+ * short and long options are tied together
+ * options have help strings, so fancy_getopt could potentially
+ create a complete usage summary
+ * options set attributes of a passed-in object
+"""
+
+from __future__ import annotations
+
+import getopt
+import re
+import string
+import sys
+from collections.abc import Sequence
+from typing import Any
+
+from .errors import DistutilsArgError, DistutilsGetoptError
+
+# Much like command_re in distutils.core, this is close to but not quite
+# the same as a Python NAME -- except, in the spirit of most GNU
+# utilities, we use '-' in place of '_'. (The spirit of LISP lives on!)
+# The similarities to NAME are again not a coincidence...
+longopt_pat = r'[a-zA-Z](?:[a-zA-Z0-9-]*)'
+longopt_re = re.compile(rf'^{longopt_pat}$')
+
+# For recognizing "negative alias" options, eg. "quiet=!verbose"
+neg_alias_re = re.compile(f"^({longopt_pat})=!({longopt_pat})$")
+
+# This is used to translate long options to legitimate Python identifiers
+# (for use as attributes of some object).
+longopt_xlate = str.maketrans('-', '_')
+
+
+class FancyGetopt:
+ """Wrapper around the standard 'getopt()' module that provides some
+ handy extra functionality:
+ * short and long options are tied together
+ * options have help strings, and help text can be assembled
+ from them
+ * options set attributes of a passed-in object
+ * boolean options can have "negative aliases" -- eg. if
+ --quiet is the "negative alias" of --verbose, then "--quiet"
+ on the command line sets 'verbose' to false
+ """
+
+ def __init__(self, option_table=None):
+ # The option table is (currently) a list of tuples. The
+ # tuples may have 3 or four values:
+ # (long_option, short_option, help_string [, repeatable])
+ # if an option takes an argument, its long_option should have '='
+ # appended; short_option should just be a single character, no ':'
+ # in any case. If a long_option doesn't have a corresponding
+ # short_option, short_option should be None. All option tuples
+ # must have long options.
+ self.option_table = option_table
+
+ # 'option_index' maps long option names to entries in the option
+ # table (ie. those 3-tuples).
+ self.option_index = {}
+ if self.option_table:
+ self._build_index()
+
+ # 'alias' records (duh) alias options; {'foo': 'bar'} means
+ # --foo is an alias for --bar
+ self.alias = {}
+
+ # 'negative_alias' keeps track of options that are the boolean
+ # opposite of some other option
+ self.negative_alias = {}
+
+ # These keep track of the information in the option table. We
+ # don't actually populate these structures until we're ready to
+ # parse the command-line, since the 'option_table' passed in here
+ # isn't necessarily the final word.
+ self.short_opts = []
+ self.long_opts = []
+ self.short2long = {}
+ self.attr_name = {}
+ self.takes_arg = {}
+
+ # And 'option_order' is filled up in 'getopt()'; it records the
+ # original order of options (and their values) on the command-line,
+ # but expands short options, converts aliases, etc.
+ self.option_order = []
+
+ def _build_index(self):
+ self.option_index.clear()
+ for option in self.option_table:
+ self.option_index[option[0]] = option
+
+ def set_option_table(self, option_table):
+ self.option_table = option_table
+ self._build_index()
+
+ def add_option(self, long_option, short_option=None, help_string=None):
+ if long_option in self.option_index:
+ raise DistutilsGetoptError(
+ f"option conflict: already an option '{long_option}'"
+ )
+ else:
+ option = (long_option, short_option, help_string)
+ self.option_table.append(option)
+ self.option_index[long_option] = option
+
+ def has_option(self, long_option):
+ """Return true if the option table for this parser has an
+ option with long name 'long_option'."""
+ return long_option in self.option_index
+
+ def get_attr_name(self, long_option):
+ """Translate long option name 'long_option' to the form it
+ has as an attribute of some object: ie., translate hyphens
+ to underscores."""
+ return long_option.translate(longopt_xlate)
+
+ def _check_alias_dict(self, aliases, what):
+ assert isinstance(aliases, dict)
+ for alias, opt in aliases.items():
+ if alias not in self.option_index:
+ raise DistutilsGetoptError(
+ f"invalid {what} '{alias}': option '{alias}' not defined"
+ )
+ if opt not in self.option_index:
+ raise DistutilsGetoptError(
+ f"invalid {what} '{alias}': aliased option '{opt}' not defined"
+ )
+
+ def set_aliases(self, alias):
+ """Set the aliases for this option parser."""
+ self._check_alias_dict(alias, "alias")
+ self.alias = alias
+
+ def set_negative_aliases(self, negative_alias):
+ """Set the negative aliases for this option parser.
+ 'negative_alias' should be a dictionary mapping option names to
+ option names, both the key and value must already be defined
+ in the option table."""
+ self._check_alias_dict(negative_alias, "negative alias")
+ self.negative_alias = negative_alias
+
+ def _grok_option_table(self): # noqa: C901
+ """Populate the various data structures that keep tabs on the
+ option table. Called by 'getopt()' before it can do anything
+ worthwhile.
+ """
+ self.long_opts = []
+ self.short_opts = []
+ self.short2long.clear()
+ self.repeat = {}
+
+ for option in self.option_table:
+ if len(option) == 3:
+ long, short, help = option
+ repeat = 0
+ elif len(option) == 4:
+ long, short, help, repeat = option
+ else:
+ # the option table is part of the code, so simply
+ # assert that it is correct
+ raise ValueError(f"invalid option tuple: {option!r}")
+
+ # Type- and value-check the option names
+ if not isinstance(long, str) or len(long) < 2:
+ raise DistutilsGetoptError(
+ f"invalid long option '{long}': must be a string of length >= 2"
+ )
+
+ if not ((short is None) or (isinstance(short, str) and len(short) == 1)):
+ raise DistutilsGetoptError(
+ f"invalid short option '{short}': must a single character or None"
+ )
+
+ self.repeat[long] = repeat
+ self.long_opts.append(long)
+
+ if long[-1] == '=': # option takes an argument?
+ if short:
+ short = short + ':'
+ long = long[0:-1]
+ self.takes_arg[long] = True
+ else:
+ # Is option is a "negative alias" for some other option (eg.
+ # "quiet" == "!verbose")?
+ alias_to = self.negative_alias.get(long)
+ if alias_to is not None:
+ if self.takes_arg[alias_to]:
+ raise DistutilsGetoptError(
+ f"invalid negative alias '{long}': "
+ f"aliased option '{alias_to}' takes a value"
+ )
+
+ self.long_opts[-1] = long # XXX redundant?!
+ self.takes_arg[long] = False
+
+ # If this is an alias option, make sure its "takes arg" flag is
+ # the same as the option it's aliased to.
+ alias_to = self.alias.get(long)
+ if alias_to is not None:
+ if self.takes_arg[long] != self.takes_arg[alias_to]:
+ raise DistutilsGetoptError(
+ f"invalid alias '{long}': inconsistent with "
+ f"aliased option '{alias_to}' (one of them takes a value, "
+ "the other doesn't"
+ )
+
+ # Now enforce some bondage on the long option name, so we can
+ # later translate it to an attribute name on some object. Have
+ # to do this a bit late to make sure we've removed any trailing
+ # '='.
+ if not longopt_re.match(long):
+ raise DistutilsGetoptError(
+ f"invalid long option name '{long}' "
+ "(must be letters, numbers, hyphens only"
+ )
+
+ self.attr_name[long] = self.get_attr_name(long)
+ if short:
+ self.short_opts.append(short)
+ self.short2long[short[0]] = long
+
+ def getopt(self, args: Sequence[str] | None = None, object=None): # noqa: C901
+ """Parse command-line options in args. Store as attributes on object.
+
+ If 'args' is None or not supplied, uses 'sys.argv[1:]'. If
+ 'object' is None or not supplied, creates a new OptionDummy
+ object, stores option values there, and returns a tuple (args,
+ object). If 'object' is supplied, it is modified in place and
+ 'getopt()' just returns 'args'; in both cases, the returned
+ 'args' is a modified copy of the passed-in 'args' list, which
+ is left untouched.
+ """
+ if args is None:
+ args = sys.argv[1:]
+ if object is None:
+ object = OptionDummy()
+ created_object = True
+ else:
+ created_object = False
+
+ self._grok_option_table()
+
+ short_opts = ' '.join(self.short_opts)
+ try:
+ opts, args = getopt.getopt(args, short_opts, self.long_opts)
+ except getopt.error as msg:
+ raise DistutilsArgError(msg)
+
+ for opt, val in opts:
+ if len(opt) == 2 and opt[0] == '-': # it's a short option
+ opt = self.short2long[opt[1]]
+ else:
+ assert len(opt) > 2 and opt[:2] == '--'
+ opt = opt[2:]
+
+ alias = self.alias.get(opt)
+ if alias:
+ opt = alias
+
+ if not self.takes_arg[opt]: # boolean option?
+ assert val == '', "boolean option can't have value"
+ alias = self.negative_alias.get(opt)
+ if alias:
+ opt = alias
+ val = 0
+ else:
+ val = 1
+
+ attr = self.attr_name[opt]
+ # The only repeating option at the moment is 'verbose'.
+ # It has a negative option -q quiet, which should set verbose = False.
+ if val and self.repeat.get(attr) is not None:
+ val = getattr(object, attr, 0) + 1
+ setattr(object, attr, val)
+ self.option_order.append((opt, val))
+
+ # for opts
+ if created_object:
+ return args, object
+ else:
+ return args
+
+ def get_option_order(self):
+ """Returns the list of (option, value) tuples processed by the
+ previous run of 'getopt()'. Raises RuntimeError if
+ 'getopt()' hasn't been called yet.
+ """
+ if self.option_order is None:
+ raise RuntimeError("'getopt()' hasn't been called yet")
+ else:
+ return self.option_order
+
+ def generate_help(self, header=None): # noqa: C901
+ """Generate help text (a list of strings, one per suggested line of
+ output) from the option table for this FancyGetopt object.
+ """
+ # Blithely assume the option table is good: probably wouldn't call
+ # 'generate_help()' unless you've already called 'getopt()'.
+
+ # First pass: determine maximum length of long option names
+ max_opt = 0
+ for option in self.option_table:
+ long = option[0]
+ short = option[1]
+ ell = len(long)
+ if long[-1] == '=':
+ ell = ell - 1
+ if short is not None:
+ ell = ell + 5 # " (-x)" where short == 'x'
+ if ell > max_opt:
+ max_opt = ell
+
+ opt_width = max_opt + 2 + 2 + 2 # room for indent + dashes + gutter
+
+ # Typical help block looks like this:
+ # --foo controls foonabulation
+ # Help block for longest option looks like this:
+ # --flimflam set the flim-flam level
+ # and with wrapped text:
+ # --flimflam set the flim-flam level (must be between
+ # 0 and 100, except on Tuesdays)
+ # Options with short names will have the short name shown (but
+ # it doesn't contribute to max_opt):
+ # --foo (-f) controls foonabulation
+ # If adding the short option would make the left column too wide,
+ # we push the explanation off to the next line
+ # --flimflam (-l)
+ # set the flim-flam level
+ # Important parameters:
+ # - 2 spaces before option block start lines
+ # - 2 dashes for each long option name
+ # - min. 2 spaces between option and explanation (gutter)
+ # - 5 characters (incl. space) for short option name
+
+ # Now generate lines of help text. (If 80 columns were good enough
+ # for Jesus, then 78 columns are good enough for me!)
+ line_width = 78
+ text_width = line_width - opt_width
+ big_indent = ' ' * opt_width
+ if header:
+ lines = [header]
+ else:
+ lines = ['Option summary:']
+
+ for option in self.option_table:
+ long, short, help = option[:3]
+ text = wrap_text(help, text_width)
+ if long[-1] == '=':
+ long = long[0:-1]
+
+ # Case 1: no short option at all (makes life easy)
+ if short is None:
+ if text:
+ lines.append(f" --{long:<{max_opt}} {text[0]}")
+ else:
+ lines.append(f" --{long:<{max_opt}}")
+
+ # Case 2: we have a short option, so we have to include it
+ # just after the long option
+ else:
+ opt_names = f"{long} (-{short})"
+ if text:
+ lines.append(f" --{opt_names:<{max_opt}} {text[0]}")
+ else:
+ lines.append(f" --{opt_names:<{max_opt}}")
+
+ for ell in text[1:]:
+ lines.append(big_indent + ell)
+ return lines
+
+ def print_help(self, header=None, file=None):
+ if file is None:
+ file = sys.stdout
+ for line in self.generate_help(header):
+ file.write(line + "\n")
+
+
+def fancy_getopt(options, negative_opt, object, args: Sequence[str] | None):
+ parser = FancyGetopt(options)
+ parser.set_negative_aliases(negative_opt)
+ return parser.getopt(args, object)
+
+
+WS_TRANS = {ord(_wschar): ' ' for _wschar in string.whitespace}
+
+
+def wrap_text(text, width):
+ """wrap_text(text : string, width : int) -> [string]
+
+ Split 'text' into multiple lines of no more than 'width' characters
+ each, and return the list of strings that results.
+ """
+ if text is None:
+ return []
+ if len(text) <= width:
+ return [text]
+
+ text = text.expandtabs()
+ text = text.translate(WS_TRANS)
+ chunks = re.split(r'( +|-+)', text)
+ chunks = [ch for ch in chunks if ch] # ' - ' results in empty strings
+ lines = []
+
+ while chunks:
+ cur_line = [] # list of chunks (to-be-joined)
+ cur_len = 0 # length of current line
+
+ while chunks:
+ ell = len(chunks[0])
+ if cur_len + ell <= width: # can squeeze (at least) this chunk in
+ cur_line.append(chunks[0])
+ del chunks[0]
+ cur_len = cur_len + ell
+ else: # this line is full
+ # drop last chunk if all space
+ if cur_line and cur_line[-1][0] == ' ':
+ del cur_line[-1]
+ break
+
+ if chunks: # any chunks left to process?
+ # if the current line is still empty, then we had a single
+ # chunk that's too big too fit on a line -- so we break
+ # down and break it up at the line width
+ if cur_len == 0:
+ cur_line.append(chunks[0][0:width])
+ chunks[0] = chunks[0][width:]
+
+ # all-whitespace chunks at the end of a line can be discarded
+ # (and we know from the re.split above that if a chunk has
+ # *any* whitespace, it is *all* whitespace)
+ if chunks[0][0] == ' ':
+ del chunks[0]
+
+ # and store this line in the list-of-all-lines -- as a single
+ # string, of course!
+ lines.append(''.join(cur_line))
+
+ return lines
+
+
+def translate_longopt(opt):
+ """Convert a long option name to a valid Python identifier by
+ changing "-" to "_".
+ """
+ return opt.translate(longopt_xlate)
+
+
+class OptionDummy:
+ """Dummy class just used as a place to hold command-line option
+ values as instance attributes."""
+
+ def __init__(self, options: Sequence[Any] = []):
+ """Create a new OptionDummy instance. The attributes listed in
+ 'options' will be initialized to None."""
+ for opt in options:
+ setattr(self, opt, None)
+
+
+if __name__ == "__main__":
+ text = """\
+Tra-la-la, supercalifragilisticexpialidocious.
+How *do* you spell that odd word, anyways?
+(Someone ask Mary -- she'll know [or she'll
+say, "How should I know?"].)"""
+
+ for w in (10, 20, 30, 40):
+ print(f"width: {w}")
+ print("\n".join(wrap_text(text, w)))
+ print()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/file_util.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/file_util.py
new file mode 100644
index 0000000..0acc8cb
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/file_util.py
@@ -0,0 +1,236 @@
+"""distutils.file_util
+
+Utility functions for operating on single files.
+"""
+
+import os
+
+from ._log import log
+from .errors import DistutilsFileError
+
+# for generating verbose output in 'copy_file()'
+_copy_action = {None: 'copying', 'hard': 'hard linking', 'sym': 'symbolically linking'}
+
+
+def _copy_file_contents(src, dst, buffer_size=16 * 1024): # noqa: C901
+ """Copy the file 'src' to 'dst'; both must be filenames. Any error
+ opening either file, reading from 'src', or writing to 'dst', raises
+ DistutilsFileError. Data is read/written in chunks of 'buffer_size'
+ bytes (default 16k). No attempt is made to handle anything apart from
+ regular files.
+ """
+ # Stolen from shutil module in the standard library, but with
+ # custom error-handling added.
+ fsrc = None
+ fdst = None
+ try:
+ try:
+ fsrc = open(src, 'rb')
+ except OSError as e:
+ raise DistutilsFileError(f"could not open '{src}': {e.strerror}")
+
+ if os.path.exists(dst):
+ try:
+ os.unlink(dst)
+ except OSError as e:
+ raise DistutilsFileError(f"could not delete '{dst}': {e.strerror}")
+
+ try:
+ fdst = open(dst, 'wb')
+ except OSError as e:
+ raise DistutilsFileError(f"could not create '{dst}': {e.strerror}")
+
+ while True:
+ try:
+ buf = fsrc.read(buffer_size)
+ except OSError as e:
+ raise DistutilsFileError(f"could not read from '{src}': {e.strerror}")
+
+ if not buf:
+ break
+
+ try:
+ fdst.write(buf)
+ except OSError as e:
+ raise DistutilsFileError(f"could not write to '{dst}': {e.strerror}")
+ finally:
+ if fdst:
+ fdst.close()
+ if fsrc:
+ fsrc.close()
+
+
+def copy_file( # noqa: C901
+ src,
+ dst,
+ preserve_mode=True,
+ preserve_times=True,
+ update=False,
+ link=None,
+ verbose=True,
+ dry_run=False,
+):
+ """Copy a file 'src' to 'dst'. If 'dst' is a directory, then 'src' is
+ copied there with the same name; otherwise, it must be a filename. (If
+ the file exists, it will be ruthlessly clobbered.) If 'preserve_mode'
+ is true (the default), the file's mode (type and permission bits, or
+ whatever is analogous on the current platform) is copied. If
+ 'preserve_times' is true (the default), the last-modified and
+ last-access times are copied as well. If 'update' is true, 'src' will
+ only be copied if 'dst' does not exist, or if 'dst' does exist but is
+ older than 'src'.
+
+ 'link' allows you to make hard links (os.link) or symbolic links
+ (os.symlink) instead of copying: set it to "hard" or "sym"; if it is
+ None (the default), files are copied. Don't set 'link' on systems that
+ don't support it: 'copy_file()' doesn't check if hard or symbolic
+ linking is available. If hardlink fails, falls back to
+ _copy_file_contents().
+
+ Under Mac OS, uses the native file copy function in macostools; on
+ other systems, uses '_copy_file_contents()' to copy file contents.
+
+ Return a tuple (dest_name, copied): 'dest_name' is the actual name of
+ the output file, and 'copied' is true if the file was copied (or would
+ have been copied, if 'dry_run' true).
+ """
+ # XXX if the destination file already exists, we clobber it if
+ # copying, but blow up if linking. Hmmm. And I don't know what
+ # macostools.copyfile() does. Should definitely be consistent, and
+ # should probably blow up if destination exists and we would be
+ # changing it (ie. it's not already a hard/soft link to src OR
+ # (not update) and (src newer than dst).
+
+ from distutils._modified import newer
+ from stat import S_IMODE, ST_ATIME, ST_MODE, ST_MTIME
+
+ if not os.path.isfile(src):
+ raise DistutilsFileError(
+ f"can't copy '{src}': doesn't exist or not a regular file"
+ )
+
+ if os.path.isdir(dst):
+ dir = dst
+ dst = os.path.join(dst, os.path.basename(src))
+ else:
+ dir = os.path.dirname(dst)
+
+ if update and not newer(src, dst):
+ if verbose >= 1:
+ log.debug("not copying %s (output up-to-date)", src)
+ return (dst, False)
+
+ try:
+ action = _copy_action[link]
+ except KeyError:
+ raise ValueError(f"invalid value '{link}' for 'link' argument")
+
+ if verbose >= 1:
+ if os.path.basename(dst) == os.path.basename(src):
+ log.info("%s %s -> %s", action, src, dir)
+ else:
+ log.info("%s %s -> %s", action, src, dst)
+
+ if dry_run:
+ return (dst, True)
+
+ # If linking (hard or symbolic), use the appropriate system call
+ # (Unix only, of course, but that's the caller's responsibility)
+ elif link == 'hard':
+ if not (os.path.exists(dst) and os.path.samefile(src, dst)):
+ try:
+ os.link(src, dst)
+ except OSError:
+ # If hard linking fails, fall back on copying file
+ # (some special filesystems don't support hard linking
+ # even under Unix, see issue #8876).
+ pass
+ else:
+ return (dst, True)
+ elif link == 'sym':
+ if not (os.path.exists(dst) and os.path.samefile(src, dst)):
+ os.symlink(src, dst)
+ return (dst, True)
+
+ # Otherwise (non-Mac, not linking), copy the file contents and
+ # (optionally) copy the times and mode.
+ _copy_file_contents(src, dst)
+ if preserve_mode or preserve_times:
+ st = os.stat(src)
+
+ # According to David Ascher , utime() should be done
+ # before chmod() (at least under NT).
+ if preserve_times:
+ os.utime(dst, (st[ST_ATIME], st[ST_MTIME]))
+ if preserve_mode:
+ os.chmod(dst, S_IMODE(st[ST_MODE]))
+
+ return (dst, True)
+
+
+# XXX I suspect this is Unix-specific -- need porting help!
+def move_file(src, dst, verbose=True, dry_run=False): # noqa: C901
+ """Move a file 'src' to 'dst'. If 'dst' is a directory, the file will
+ be moved into it with the same name; otherwise, 'src' is just renamed
+ to 'dst'. Return the new full name of the file.
+
+ Handles cross-device moves on Unix using 'copy_file()'. What about
+ other systems???
+ """
+ import errno
+ from os.path import basename, dirname, exists, isdir, isfile
+
+ if verbose >= 1:
+ log.info("moving %s -> %s", src, dst)
+
+ if dry_run:
+ return dst
+
+ if not isfile(src):
+ raise DistutilsFileError(f"can't move '{src}': not a regular file")
+
+ if isdir(dst):
+ dst = os.path.join(dst, basename(src))
+ elif exists(dst):
+ raise DistutilsFileError(
+ f"can't move '{src}': destination '{dst}' already exists"
+ )
+
+ if not isdir(dirname(dst)):
+ raise DistutilsFileError(
+ f"can't move '{src}': destination '{dst}' not a valid path"
+ )
+
+ copy_it = False
+ try:
+ os.rename(src, dst)
+ except OSError as e:
+ (num, msg) = e.args
+ if num == errno.EXDEV:
+ copy_it = True
+ else:
+ raise DistutilsFileError(f"couldn't move '{src}' to '{dst}': {msg}")
+
+ if copy_it:
+ copy_file(src, dst, verbose=verbose)
+ try:
+ os.unlink(src)
+ except OSError as e:
+ (num, msg) = e.args
+ try:
+ os.unlink(dst)
+ except OSError:
+ pass
+ raise DistutilsFileError(
+ f"couldn't move '{src}' to '{dst}' by copy/delete: "
+ f"delete '{src}' failed: {msg}"
+ )
+ return dst
+
+
+def write_file(filename, contents):
+ """Create a file with the specified name and write 'contents' (a
+ sequence of strings without line terminators) to it.
+ """
+ with open(filename, 'w', encoding='utf-8') as f:
+ f.writelines(line + '\n' for line in contents)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/filelist.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/filelist.py
new file mode 100644
index 0000000..70dc0fd
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/filelist.py
@@ -0,0 +1,431 @@
+"""distutils.filelist
+
+Provides the FileList class, used for poking about the filesystem
+and building lists of files.
+"""
+
+from __future__ import annotations
+
+import fnmatch
+import functools
+import os
+import re
+from collections.abc import Iterable
+from typing import Literal, overload
+
+from ._log import log
+from .errors import DistutilsInternalError, DistutilsTemplateError
+from .util import convert_path
+
+
+class FileList:
+ """A list of files built by on exploring the filesystem and filtered by
+ applying various patterns to what we find there.
+
+ Instance attributes:
+ dir
+ directory from which files will be taken -- only used if
+ 'allfiles' not supplied to constructor
+ files
+ list of filenames currently being built/filtered/manipulated
+ allfiles
+ complete list of files under consideration (ie. without any
+ filtering applied)
+ """
+
+ def __init__(self, warn: object = None, debug_print: object = None) -> None:
+ # ignore argument to FileList, but keep them for backwards
+ # compatibility
+ self.allfiles: Iterable[str] | None = None
+ self.files: list[str] = []
+
+ def set_allfiles(self, allfiles: Iterable[str]) -> None:
+ self.allfiles = allfiles
+
+ def findall(self, dir: str | os.PathLike[str] = os.curdir) -> None:
+ self.allfiles = findall(dir)
+
+ def debug_print(self, msg: object) -> None:
+ """Print 'msg' to stdout if the global DEBUG (taken from the
+ DISTUTILS_DEBUG environment variable) flag is true.
+ """
+ from distutils.debug import DEBUG
+
+ if DEBUG:
+ print(msg)
+
+ # Collection methods
+
+ def append(self, item: str) -> None:
+ self.files.append(item)
+
+ def extend(self, items: Iterable[str]) -> None:
+ self.files.extend(items)
+
+ def sort(self) -> None:
+ # Not a strict lexical sort!
+ sortable_files = sorted(map(os.path.split, self.files))
+ self.files = []
+ for sort_tuple in sortable_files:
+ self.files.append(os.path.join(*sort_tuple))
+
+ # Other miscellaneous utility methods
+
+ def remove_duplicates(self) -> None:
+ # Assumes list has been sorted!
+ for i in range(len(self.files) - 1, 0, -1):
+ if self.files[i] == self.files[i - 1]:
+ del self.files[i]
+
+ # "File template" methods
+
+ def _parse_template_line(self, line):
+ words = line.split()
+ action = words[0]
+
+ patterns = dir = dir_pattern = None
+
+ if action in ('include', 'exclude', 'global-include', 'global-exclude'):
+ if len(words) < 2:
+ raise DistutilsTemplateError(
+ f"'{action}' expects ..."
+ )
+ patterns = [convert_path(w) for w in words[1:]]
+ elif action in ('recursive-include', 'recursive-exclude'):
+ if len(words) < 3:
+ raise DistutilsTemplateError(
+ f"'{action}' expects ..."
+ )
+ dir = convert_path(words[1])
+ patterns = [convert_path(w) for w in words[2:]]
+ elif action in ('graft', 'prune'):
+ if len(words) != 2:
+ raise DistutilsTemplateError(
+ f"'{action}' expects a single "
+ )
+ dir_pattern = convert_path(words[1])
+ else:
+ raise DistutilsTemplateError(f"unknown action '{action}'")
+
+ return (action, patterns, dir, dir_pattern)
+
+ def process_template_line(self, line: str) -> None: # noqa: C901
+ # Parse the line: split it up, make sure the right number of words
+ # is there, and return the relevant words. 'action' is always
+ # defined: it's the first word of the line. Which of the other
+ # three are defined depends on the action; it'll be either
+ # patterns, (dir and patterns), or (dir_pattern).
+ (action, patterns, dir, dir_pattern) = self._parse_template_line(line)
+
+ # OK, now we know that the action is valid and we have the
+ # right number of words on the line for that action -- so we
+ # can proceed with minimal error-checking.
+ if action == 'include':
+ self.debug_print("include " + ' '.join(patterns))
+ for pattern in patterns:
+ if not self.include_pattern(pattern, anchor=True):
+ log.warning("warning: no files found matching '%s'", pattern)
+
+ elif action == 'exclude':
+ self.debug_print("exclude " + ' '.join(patterns))
+ for pattern in patterns:
+ if not self.exclude_pattern(pattern, anchor=True):
+ log.warning(
+ "warning: no previously-included files found matching '%s'",
+ pattern,
+ )
+
+ elif action == 'global-include':
+ self.debug_print("global-include " + ' '.join(patterns))
+ for pattern in patterns:
+ if not self.include_pattern(pattern, anchor=False):
+ log.warning(
+ (
+ "warning: no files found matching '%s' "
+ "anywhere in distribution"
+ ),
+ pattern,
+ )
+
+ elif action == 'global-exclude':
+ self.debug_print("global-exclude " + ' '.join(patterns))
+ for pattern in patterns:
+ if not self.exclude_pattern(pattern, anchor=False):
+ log.warning(
+ (
+ "warning: no previously-included files matching "
+ "'%s' found anywhere in distribution"
+ ),
+ pattern,
+ )
+
+ elif action == 'recursive-include':
+ self.debug_print("recursive-include {} {}".format(dir, ' '.join(patterns)))
+ for pattern in patterns:
+ if not self.include_pattern(pattern, prefix=dir):
+ msg = "warning: no files found matching '%s' under directory '%s'"
+ log.warning(msg, pattern, dir)
+
+ elif action == 'recursive-exclude':
+ self.debug_print("recursive-exclude {} {}".format(dir, ' '.join(patterns)))
+ for pattern in patterns:
+ if not self.exclude_pattern(pattern, prefix=dir):
+ log.warning(
+ (
+ "warning: no previously-included files matching "
+ "'%s' found under directory '%s'"
+ ),
+ pattern,
+ dir,
+ )
+
+ elif action == 'graft':
+ self.debug_print("graft " + dir_pattern)
+ if not self.include_pattern(None, prefix=dir_pattern):
+ log.warning("warning: no directories found matching '%s'", dir_pattern)
+
+ elif action == 'prune':
+ self.debug_print("prune " + dir_pattern)
+ if not self.exclude_pattern(None, prefix=dir_pattern):
+ log.warning(
+ ("no previously-included directories found matching '%s'"),
+ dir_pattern,
+ )
+ else:
+ raise DistutilsInternalError(
+ f"this cannot happen: invalid action '{action}'"
+ )
+
+ # Filtering/selection methods
+ @overload
+ def include_pattern(
+ self,
+ pattern: str,
+ anchor: bool = True,
+ prefix: str | None = None,
+ is_regex: Literal[False] = False,
+ ) -> bool: ...
+ @overload
+ def include_pattern(
+ self,
+ pattern: str | re.Pattern[str],
+ anchor: bool = True,
+ prefix: str | None = None,
+ *,
+ is_regex: Literal[True],
+ ) -> bool: ...
+ @overload
+ def include_pattern(
+ self,
+ pattern: str | re.Pattern[str],
+ anchor: bool,
+ prefix: str | None,
+ is_regex: Literal[True],
+ ) -> bool: ...
+ def include_pattern(
+ self,
+ pattern: str | re.Pattern,
+ anchor: bool = True,
+ prefix: str | None = None,
+ is_regex: bool = False,
+ ) -> bool:
+ """Select strings (presumably filenames) from 'self.files' that
+ match 'pattern', a Unix-style wildcard (glob) pattern. Patterns
+ are not quite the same as implemented by the 'fnmatch' module: '*'
+ and '?' match non-special characters, where "special" is platform-
+ dependent: slash on Unix; colon, slash, and backslash on
+ DOS/Windows; and colon on Mac OS.
+
+ If 'anchor' is true (the default), then the pattern match is more
+ stringent: "*.py" will match "foo.py" but not "foo/bar.py". If
+ 'anchor' is false, both of these will match.
+
+ If 'prefix' is supplied, then only filenames starting with 'prefix'
+ (itself a pattern) and ending with 'pattern', with anything in between
+ them, will match. 'anchor' is ignored in this case.
+
+ If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and
+ 'pattern' is assumed to be either a string containing a regex or a
+ regex object -- no translation is done, the regex is just compiled
+ and used as-is.
+
+ Selected strings will be added to self.files.
+
+ Return True if files are found, False otherwise.
+ """
+ # XXX docstring lying about what the special chars are?
+ files_found = False
+ pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
+ self.debug_print(f"include_pattern: applying regex r'{pattern_re.pattern}'")
+
+ # delayed loading of allfiles list
+ if self.allfiles is None:
+ self.findall()
+
+ for name in self.allfiles:
+ if pattern_re.search(name):
+ self.debug_print(" adding " + name)
+ self.files.append(name)
+ files_found = True
+ return files_found
+
+ @overload
+ def exclude_pattern(
+ self,
+ pattern: str,
+ anchor: bool = True,
+ prefix: str | None = None,
+ is_regex: Literal[False] = False,
+ ) -> bool: ...
+ @overload
+ def exclude_pattern(
+ self,
+ pattern: str | re.Pattern[str],
+ anchor: bool = True,
+ prefix: str | None = None,
+ *,
+ is_regex: Literal[True],
+ ) -> bool: ...
+ @overload
+ def exclude_pattern(
+ self,
+ pattern: str | re.Pattern[str],
+ anchor: bool,
+ prefix: str | None,
+ is_regex: Literal[True],
+ ) -> bool: ...
+ def exclude_pattern(
+ self,
+ pattern: str | re.Pattern,
+ anchor: bool = True,
+ prefix: str | None = None,
+ is_regex: bool = False,
+ ) -> bool:
+ """Remove strings (presumably filenames) from 'files' that match
+ 'pattern'. Other parameters are the same as for
+ 'include_pattern()', above.
+ The list 'self.files' is modified in place.
+ Return True if files are found, False otherwise.
+ """
+ files_found = False
+ pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
+ self.debug_print(f"exclude_pattern: applying regex r'{pattern_re.pattern}'")
+ for i in range(len(self.files) - 1, -1, -1):
+ if pattern_re.search(self.files[i]):
+ self.debug_print(" removing " + self.files[i])
+ del self.files[i]
+ files_found = True
+ return files_found
+
+
+# Utility functions
+
+
+def _find_all_simple(path):
+ """
+ Find all files under 'path'
+ """
+ all_unique = _UniqueDirs.filter(os.walk(path, followlinks=True))
+ results = (
+ os.path.join(base, file) for base, dirs, files in all_unique for file in files
+ )
+ return filter(os.path.isfile, results)
+
+
+class _UniqueDirs(set):
+ """
+ Exclude previously-seen dirs from walk results,
+ avoiding infinite recursion.
+ Ref https://bugs.python.org/issue44497.
+ """
+
+ def __call__(self, walk_item):
+ """
+ Given an item from an os.walk result, determine
+ if the item represents a unique dir for this instance
+ and if not, prevent further traversal.
+ """
+ base, dirs, files = walk_item
+ stat = os.stat(base)
+ candidate = stat.st_dev, stat.st_ino
+ found = candidate in self
+ if found:
+ del dirs[:]
+ self.add(candidate)
+ return not found
+
+ @classmethod
+ def filter(cls, items):
+ return filter(cls(), items)
+
+
+def findall(dir: str | os.PathLike[str] = 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)
+
+
+def glob_to_re(pattern):
+ """Translate a shell-like glob pattern to a regular expression; return
+ a string containing the regex. Differs from 'fnmatch.translate()' in
+ that '*' does not match "special characters" (which are
+ platform-specific).
+ """
+ pattern_re = fnmatch.translate(pattern)
+
+ # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which
+ # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix,
+ # and by extension they shouldn't match such "special characters" under
+ # any OS. So change all non-escaped dots in the RE to match any
+ # character except the special characters (currently: just os.sep).
+ sep = os.sep
+ if os.sep == '\\':
+ # we're using a regex to manipulate a regex, so we need
+ # to escape the backslash twice
+ sep = r'\\\\'
+ escaped = rf'\1[^{sep}]'
+ pattern_re = re.sub(r'((?= 2:
+ set_threshold(logging.DEBUG)
+
+
+class Log(logging.Logger):
+ """distutils.log.Log is deprecated, please use an alternative from `logging`."""
+
+ def __init__(self, threshold=WARN):
+ warnings.warn(Log.__doc__) # avoid DeprecationWarning to ensure warn is shown
+ super().__init__(__name__, level=threshold)
+
+ @property
+ def threshold(self):
+ return self.level
+
+ @threshold.setter
+ def threshold(self, level):
+ self.setLevel(level)
+
+ warn = logging.Logger.warning
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/spawn.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/spawn.py
new file mode 100644
index 0000000..973668f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/spawn.py
@@ -0,0 +1,134 @@
+"""distutils.spawn
+
+Provides the 'spawn()' function, a front-end to various platform-
+specific functions for launching another program in a sub-process.
+"""
+
+from __future__ import annotations
+
+import os
+import platform
+import shutil
+import subprocess
+import sys
+import warnings
+from collections.abc import Mapping, MutableSequence
+from typing import TYPE_CHECKING, TypeVar, overload
+
+from ._log import log
+from .debug import DEBUG
+from .errors import DistutilsExecError
+
+if TYPE_CHECKING:
+ from subprocess import _ENV
+
+
+_MappingT = TypeVar("_MappingT", bound=Mapping)
+
+
+def _debug(cmd):
+ """
+ Render a subprocess command differently depending on DEBUG.
+ """
+ return cmd if DEBUG else cmd[0]
+
+
+def _inject_macos_ver(env: _MappingT | None) -> _MappingT | dict[str, str | int] | None:
+ if platform.system() != 'Darwin':
+ return env
+
+ from .util import MACOSX_VERSION_VAR, get_macosx_target_ver
+
+ target_ver = get_macosx_target_ver()
+ update = {MACOSX_VERSION_VAR: target_ver} if target_ver else {}
+ return {**_resolve(env), **update}
+
+
+@overload
+def _resolve(env: None) -> os._Environ[str]: ...
+@overload
+def _resolve(env: _MappingT) -> _MappingT: ...
+def _resolve(env: _MappingT | None) -> _MappingT | os._Environ[str]:
+ return os.environ if env is None else env
+
+
+def spawn(
+ cmd: MutableSequence[bytes | str | os.PathLike[str]],
+ search_path: bool = True,
+ verbose: bool = False,
+ dry_run: bool = False,
+ env: _ENV | None = None,
+) -> None:
+ """Run another program, specified as a command list 'cmd', in a new process.
+
+ 'cmd' is just the argument list for the new process, ie.
+ cmd[0] is the program to run and cmd[1:] are the rest of its arguments.
+ There is no way to run a program with a name different from that of its
+ executable.
+
+ If 'search_path' is true (the default), the system's executable
+ search path will be used to find the program; otherwise, cmd[0]
+ must be the exact path to the executable. If 'dry_run' is true,
+ the command will not actually be run.
+
+ Raise DistutilsExecError if running the program fails in any way; just
+ return on success.
+ """
+ log.info(subprocess.list2cmdline(cmd))
+ if dry_run:
+ return
+
+ if search_path:
+ executable = shutil.which(cmd[0])
+ if executable is not None:
+ cmd[0] = executable
+
+ try:
+ subprocess.check_call(cmd, env=_inject_macos_ver(env))
+ except OSError as exc:
+ raise DistutilsExecError(
+ f"command {_debug(cmd)!r} failed: {exc.args[-1]}"
+ ) from exc
+ except subprocess.CalledProcessError as err:
+ raise DistutilsExecError(
+ f"command {_debug(cmd)!r} failed with exit code {err.returncode}"
+ ) from err
+
+
+def find_executable(executable: str, path: str | None = None) -> str | None:
+ """Tries to find 'executable' in the directories listed in 'path'.
+
+ A string listing directories separated by 'os.pathsep'; defaults to
+ os.environ['PATH']. Returns the complete filename or None if not found.
+ """
+ warnings.warn(
+ 'Use shutil.which instead of find_executable', DeprecationWarning, stacklevel=2
+ )
+ _, ext = os.path.splitext(executable)
+ if (sys.platform == 'win32') and (ext != '.exe'):
+ executable = executable + '.exe'
+
+ if os.path.isfile(executable):
+ return executable
+
+ if path is None:
+ path = os.environ.get('PATH', None)
+ # bpo-35755: Don't fall through if PATH is the empty string
+ if path is None:
+ try:
+ path = os.confstr("CS_PATH")
+ except (AttributeError, ValueError):
+ # os.confstr() or CS_PATH is not available
+ path = os.defpath
+
+ # PATH='' doesn't match, whereas PATH=':' looks in the current directory
+ if not path:
+ return None
+
+ paths = path.split(os.pathsep)
+ for p in paths:
+ f = os.path.join(p, executable)
+ if os.path.isfile(f):
+ # the file exists, we have a shot at spawn working
+ return f
+ return None
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/sysconfig.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/sysconfig.py
new file mode 100644
index 0000000..7ddc869
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/sysconfig.py
@@ -0,0 +1,598 @@
+"""Provide access to Python's configuration information. The specific
+configuration variables available depend heavily on the platform and
+configuration. The values may be retrieved using
+get_config_var(name), and the list of variables is available via
+get_config_vars().keys(). Additional convenience functions are also
+available.
+
+Written by: Fred L. Drake, Jr.
+Email:
+"""
+
+from __future__ import annotations
+
+import functools
+import os
+import pathlib
+import re
+import sys
+import sysconfig
+from typing import TYPE_CHECKING, Literal, overload
+
+from jaraco.functools import pass_none
+
+from .ccompiler import CCompiler
+from .compat import py39
+from .errors import DistutilsPlatformError
+from .util import is_mingw
+
+if TYPE_CHECKING:
+ from typing_extensions import deprecated
+else:
+
+ def deprecated(message):
+ return lambda fn: fn
+
+
+IS_PYPY = '__pypy__' in sys.builtin_module_names
+
+# These are needed in a couple of spots, so just compute them once.
+PREFIX = os.path.normpath(sys.prefix)
+EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
+BASE_PREFIX = os.path.normpath(sys.base_prefix)
+BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
+
+# Path to the base directory of the project. On Windows the binary may
+# live in project/PCbuild/win32 or project/PCbuild/amd64.
+# set for cross builds
+if "_PYTHON_PROJECT_BASE" in os.environ:
+ project_base = os.path.abspath(os.environ["_PYTHON_PROJECT_BASE"])
+else:
+ if sys.executable:
+ project_base = os.path.dirname(os.path.abspath(sys.executable))
+ else:
+ # sys.executable can be empty if argv[0] has been changed and Python is
+ # unable to retrieve the real program name
+ project_base = os.getcwd()
+
+
+def _is_python_source_dir(d):
+ """
+ Return True if the target directory appears to point to an
+ un-installed Python.
+ """
+ modules = pathlib.Path(d).joinpath('Modules')
+ return any(modules.joinpath(fn).is_file() for fn in ('Setup', 'Setup.local'))
+
+
+_sys_home = getattr(sys, '_home', None)
+
+
+def _is_parent(dir_a, dir_b):
+ """
+ Return True if a is a parent of b.
+ """
+ return os.path.normcase(dir_a).startswith(os.path.normcase(dir_b))
+
+
+if os.name == 'nt':
+
+ @pass_none
+ def _fix_pcbuild(d):
+ # In a venv, sys._home will be inside BASE_PREFIX rather than PREFIX.
+ prefixes = PREFIX, BASE_PREFIX
+ matched = (
+ prefix
+ for prefix in prefixes
+ if _is_parent(d, os.path.join(prefix, "PCbuild"))
+ )
+ return next(matched, d)
+
+ project_base = _fix_pcbuild(project_base)
+ _sys_home = _fix_pcbuild(_sys_home)
+
+
+def _python_build():
+ if _sys_home:
+ return _is_python_source_dir(_sys_home)
+ return _is_python_source_dir(project_base)
+
+
+python_build = _python_build()
+
+
+# Calculate the build qualifier flags if they are defined. Adding the flags
+# to the include and lib directories only makes sense for an installation, not
+# an in-source build.
+build_flags = ''
+try:
+ if not python_build:
+ build_flags = sys.abiflags
+except AttributeError:
+ # It's not a configure-based build, so the sys module doesn't have
+ # this attribute, which is fine.
+ pass
+
+
+def get_python_version():
+ """Return a string containing the major and minor Python version,
+ leaving off the patchlevel. Sample return values could be '1.5'
+ or '2.2'.
+ """
+ return f'{sys.version_info.major}.{sys.version_info.minor}'
+
+
+def get_python_inc(plat_specific: bool = False, prefix: str | None = None) -> str:
+ """Return the directory containing installed Python header files.
+
+ If 'plat_specific' is false (the default), this is the path to the
+ non-platform-specific header files, i.e. Python.h and so on;
+ otherwise, this is the path to platform-specific header files
+ (namely pyconfig.h).
+
+ If 'prefix' is supplied, use it instead of sys.base_prefix or
+ sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
+ """
+ default_prefix = BASE_EXEC_PREFIX if plat_specific else BASE_PREFIX
+ resolved_prefix = prefix if prefix is not None else default_prefix
+ # MinGW imitates posix like layout, but os.name != posix
+ os_name = "posix" if is_mingw() else os.name
+ try:
+ getter = globals()[f'_get_python_inc_{os_name}']
+ except KeyError:
+ raise DistutilsPlatformError(
+ "I don't know where Python installs its C header files "
+ f"on platform '{os.name}'"
+ )
+ return getter(resolved_prefix, prefix, plat_specific)
+
+
+@pass_none
+def _extant(path):
+ """
+ Replace path with None if it doesn't exist.
+ """
+ return path if os.path.exists(path) else None
+
+
+def _get_python_inc_posix(prefix, spec_prefix, plat_specific):
+ return (
+ _get_python_inc_posix_python(plat_specific)
+ or _extant(_get_python_inc_from_config(plat_specific, spec_prefix))
+ or _get_python_inc_posix_prefix(prefix)
+ )
+
+
+def _get_python_inc_posix_python(plat_specific):
+ """
+ Assume the executable is in the build directory. The
+ pyconfig.h file should be in the same directory. Since
+ the build directory may not be the source directory,
+ use "srcdir" from the makefile to find the "Include"
+ directory.
+ """
+ if not python_build:
+ return
+ if plat_specific:
+ return _sys_home or project_base
+ incdir = os.path.join(get_config_var('srcdir'), 'Include')
+ return os.path.normpath(incdir)
+
+
+def _get_python_inc_from_config(plat_specific, spec_prefix):
+ """
+ If no prefix was explicitly specified, provide the include
+ directory from the config vars. Useful when
+ cross-compiling, since the config vars may come from
+ the host
+ platform Python installation, while the current Python
+ executable is from the build platform installation.
+
+ >>> monkeypatch = getfixture('monkeypatch')
+ >>> gpifc = _get_python_inc_from_config
+ >>> monkeypatch.setitem(gpifc.__globals__, 'get_config_var', str.lower)
+ >>> gpifc(False, '/usr/bin/')
+ >>> gpifc(False, '')
+ >>> gpifc(False, None)
+ 'includepy'
+ >>> gpifc(True, None)
+ 'confincludepy'
+ """
+ if spec_prefix is None:
+ return get_config_var('CONF' * plat_specific + 'INCLUDEPY')
+
+
+def _get_python_inc_posix_prefix(prefix):
+ implementation = 'pypy' if IS_PYPY else 'python'
+ python_dir = implementation + get_python_version() + build_flags
+ return os.path.join(prefix, "include", python_dir)
+
+
+def _get_python_inc_nt(prefix, spec_prefix, plat_specific):
+ if python_build:
+ # Include both include dirs to ensure we can find pyconfig.h
+ return (
+ os.path.join(prefix, "include")
+ + os.path.pathsep
+ + os.path.dirname(sysconfig.get_config_h_filename())
+ )
+ return os.path.join(prefix, "include")
+
+
+# allow this behavior to be monkey-patched. Ref pypa/distutils#2.
+def _posix_lib(standard_lib, libpython, early_prefix, prefix):
+ if standard_lib:
+ return libpython
+ else:
+ return os.path.join(libpython, "site-packages")
+
+
+def get_python_lib(
+ plat_specific: bool = False, standard_lib: bool = False, prefix: str | None = None
+) -> str:
+ """Return the directory containing the Python library (standard or
+ site additions).
+
+ If 'plat_specific' is true, return the directory containing
+ platform-specific modules, i.e. any module from a non-pure-Python
+ module distribution; otherwise, return the platform-shared library
+ directory. If 'standard_lib' is true, return the directory
+ containing standard Python library modules; otherwise, return the
+ directory for site-specific modules.
+
+ If 'prefix' is supplied, use it instead of sys.base_prefix or
+ sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
+ """
+
+ early_prefix = prefix
+
+ if prefix is None:
+ if standard_lib:
+ prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
+ else:
+ prefix = plat_specific and EXEC_PREFIX or PREFIX
+
+ if os.name == "posix" or is_mingw():
+ if plat_specific or standard_lib:
+ # Platform-specific modules (any module from a non-pure-Python
+ # module distribution) or standard Python library modules.
+ libdir = getattr(sys, "platlibdir", "lib")
+ else:
+ # Pure Python
+ libdir = "lib"
+ implementation = 'pypy' if IS_PYPY else 'python'
+ libpython = os.path.join(prefix, libdir, implementation + get_python_version())
+ return _posix_lib(standard_lib, libpython, early_prefix, prefix)
+ elif os.name == "nt":
+ if standard_lib:
+ return os.path.join(prefix, "Lib")
+ else:
+ return os.path.join(prefix, "Lib", "site-packages")
+ else:
+ raise DistutilsPlatformError(
+ f"I don't know where Python installs its library on platform '{os.name}'"
+ )
+
+
+@functools.lru_cache
+def _customize_macos():
+ """
+ Perform first-time customization of compiler-related
+ config vars on macOS. Use after a compiler is known
+ to be needed. This customization exists primarily to support Pythons
+ from binary installers. The kind and paths to build tools on
+ the user system may vary significantly from the system
+ that Python itself was built on. Also the user OS
+ version and build tools may not support the same set
+ of CPU architectures for universal builds.
+ """
+
+ sys.platform == "darwin" and __import__('_osx_support').customize_compiler(
+ get_config_vars()
+ )
+
+
+def customize_compiler(compiler: CCompiler) -> None:
+ """Do any platform-specific customization of a CCompiler instance.
+
+ Mainly needed on Unix, so we can plug in the information that
+ varies across Unices and is stored in Python's Makefile.
+ """
+ if compiler.compiler_type in ["unix", "cygwin"] or (
+ compiler.compiler_type == "mingw32" and is_mingw()
+ ):
+ _customize_macos()
+
+ (
+ cc,
+ cxx,
+ cflags,
+ ccshared,
+ ldshared,
+ ldcxxshared,
+ shlib_suffix,
+ ar,
+ ar_flags,
+ ) = get_config_vars(
+ 'CC',
+ 'CXX',
+ 'CFLAGS',
+ 'CCSHARED',
+ 'LDSHARED',
+ 'LDCXXSHARED',
+ 'SHLIB_SUFFIX',
+ 'AR',
+ 'ARFLAGS',
+ )
+
+ cxxflags = cflags
+
+ if 'CC' in os.environ:
+ newcc = os.environ['CC']
+ if 'LDSHARED' not in os.environ and ldshared.startswith(cc):
+ # If CC is overridden, use that as the default
+ # command for LDSHARED as well
+ ldshared = newcc + ldshared[len(cc) :]
+ cc = newcc
+ cxx = os.environ.get('CXX', cxx)
+ ldshared = os.environ.get('LDSHARED', ldshared)
+ ldcxxshared = os.environ.get('LDCXXSHARED', ldcxxshared)
+ cpp = os.environ.get(
+ 'CPP',
+ cc + " -E", # not always
+ )
+
+ ldshared = _add_flags(ldshared, 'LD')
+ ldcxxshared = _add_flags(ldcxxshared, 'LD')
+ cflags = os.environ.get('CFLAGS', cflags)
+ ldshared = _add_flags(ldshared, 'C')
+ cxxflags = os.environ.get('CXXFLAGS', cxxflags)
+ ldcxxshared = _add_flags(ldcxxshared, 'CXX')
+ cpp = _add_flags(cpp, 'CPP')
+ cflags = _add_flags(cflags, 'CPP')
+ cxxflags = _add_flags(cxxflags, 'CPP')
+ ldshared = _add_flags(ldshared, 'CPP')
+ ldcxxshared = _add_flags(ldcxxshared, 'CPP')
+
+ ar = os.environ.get('AR', ar)
+
+ archiver = ar + ' ' + os.environ.get('ARFLAGS', ar_flags)
+ cc_cmd = cc + ' ' + cflags
+ cxx_cmd = cxx + ' ' + cxxflags
+
+ compiler.set_executables(
+ preprocessor=cpp,
+ compiler=cc_cmd,
+ compiler_so=cc_cmd + ' ' + ccshared,
+ compiler_cxx=cxx_cmd,
+ compiler_so_cxx=cxx_cmd + ' ' + ccshared,
+ linker_so=ldshared,
+ linker_so_cxx=ldcxxshared,
+ linker_exe=cc,
+ linker_exe_cxx=cxx,
+ archiver=archiver,
+ )
+
+ if 'RANLIB' in os.environ and compiler.executables.get('ranlib', None):
+ compiler.set_executables(ranlib=os.environ['RANLIB'])
+
+ compiler.shared_lib_extension = shlib_suffix
+
+
+def get_config_h_filename() -> str:
+ """Return full pathname of installed pyconfig.h file."""
+ return sysconfig.get_config_h_filename()
+
+
+def get_makefile_filename() -> str:
+ """Return full pathname of installed Makefile from the Python build."""
+ return sysconfig.get_makefile_filename()
+
+
+def parse_config_h(fp, g=None):
+ """Parse a config.h-style file.
+
+ A dictionary containing name/value pairs is returned. If an
+ optional dictionary is passed in as the second argument, it is
+ used instead of a new dictionary.
+ """
+ return sysconfig.parse_config_h(fp, vars=g)
+
+
+# Regexes needed for parsing Makefile (and similar syntaxes,
+# like old-style Setup files).
+_variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
+_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
+_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
+
+
+def parse_makefile(fn, g=None): # noqa: C901
+ """Parse a Makefile-style file.
+
+ A dictionary containing name/value pairs is returned. If an
+ optional dictionary is passed in as the second argument, it is
+ used instead of a new dictionary.
+ """
+ from distutils.text_file import TextFile
+
+ fp = TextFile(
+ fn,
+ strip_comments=True,
+ skip_blanks=True,
+ join_lines=True,
+ errors="surrogateescape",
+ )
+
+ if g is None:
+ g = {}
+ done = {}
+ notdone = {}
+
+ while True:
+ line = fp.readline()
+ if line is None: # eof
+ break
+ m = _variable_rx.match(line)
+ if m:
+ n, v = m.group(1, 2)
+ v = v.strip()
+ # `$$' is a literal `$' in make
+ tmpv = v.replace('$$', '')
+
+ if "$" in tmpv:
+ notdone[n] = v
+ else:
+ try:
+ v = int(v)
+ except ValueError:
+ # insert literal `$'
+ done[n] = v.replace('$$', '$')
+ else:
+ done[n] = v
+
+ # Variables with a 'PY_' prefix in the makefile. These need to
+ # be made available without that prefix through sysconfig.
+ # Special care is needed to ensure that variable expansion works, even
+ # if the expansion uses the name without a prefix.
+ renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
+
+ # do variable interpolation here
+ while notdone:
+ for name in list(notdone):
+ value = notdone[name]
+ m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
+ if m:
+ n = m.group(1)
+ found = True
+ if n in done:
+ item = str(done[n])
+ elif n in notdone:
+ # get it on a subsequent round
+ found = False
+ elif n in os.environ:
+ # do it like make: fall back to environment
+ item = os.environ[n]
+
+ elif n in renamed_variables:
+ if name.startswith('PY_') and name[3:] in renamed_variables:
+ item = ""
+
+ elif 'PY_' + n in notdone:
+ found = False
+
+ else:
+ item = str(done['PY_' + n])
+ else:
+ done[n] = item = ""
+ if found:
+ after = value[m.end() :]
+ value = value[: m.start()] + item + after
+ if "$" in after:
+ notdone[name] = value
+ else:
+ try:
+ value = int(value)
+ except ValueError:
+ done[name] = value.strip()
+ else:
+ done[name] = value
+ del notdone[name]
+
+ if name.startswith('PY_') and name[3:] in renamed_variables:
+ name = name[3:]
+ if name not in done:
+ done[name] = value
+ else:
+ # bogus variable reference; just drop it since we can't deal
+ del notdone[name]
+
+ fp.close()
+
+ # strip spurious spaces
+ for k, v in done.items():
+ if isinstance(v, str):
+ done[k] = v.strip()
+
+ # save the results in the global dictionary
+ g.update(done)
+ return g
+
+
+def expand_makefile_vars(s, vars):
+ """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
+ 'string' according to 'vars' (a dictionary mapping variable names to
+ values). Variables not present in 'vars' are silently expanded to the
+ empty string. The variable values in 'vars' should not contain further
+ variable expansions; if 'vars' is the output of 'parse_makefile()',
+ you're fine. Returns a variable-expanded version of 's'.
+ """
+
+ # This algorithm does multiple expansion, so if vars['foo'] contains
+ # "${bar}", it will expand ${foo} to ${bar}, and then expand
+ # ${bar}... and so forth. This is fine as long as 'vars' comes from
+ # 'parse_makefile()', which takes care of such expansions eagerly,
+ # according to make's variable expansion semantics.
+
+ while True:
+ m = _findvar1_rx.search(s) or _findvar2_rx.search(s)
+ if m:
+ (beg, end) = m.span()
+ s = s[0:beg] + vars.get(m.group(1)) + s[end:]
+ else:
+ break
+ return s
+
+
+_config_vars = None
+
+
+@overload
+def get_config_vars() -> dict[str, str | int]: ...
+@overload
+def get_config_vars(arg: str, /, *args: str) -> list[str | int]: ...
+def get_config_vars(*args: str) -> list[str | int] | dict[str, str | int]:
+ """With no arguments, return a dictionary of all configuration
+ variables relevant for the current platform. Generally this includes
+ everything needed to build extensions and install both pure modules and
+ extensions. On Unix, this means every variable defined in Python's
+ installed Makefile; on Windows it's a much smaller set.
+
+ With arguments, return a list of values that result from looking up
+ each argument in the configuration variable dictionary.
+ """
+ global _config_vars
+ if _config_vars is None:
+ _config_vars = sysconfig.get_config_vars().copy()
+ py39.add_ext_suffix(_config_vars)
+
+ return [_config_vars.get(name) for name in args] if args else _config_vars
+
+
+@overload
+@deprecated(
+ "SO is deprecated, use EXT_SUFFIX. Support will be removed when this module is synchronized with stdlib Python 3.11"
+)
+def get_config_var(name: Literal["SO"]) -> int | str | None: ...
+@overload
+def get_config_var(name: str) -> int | str | None: ...
+def get_config_var(name: str) -> int | str | None:
+ """Return the value of a single variable using the dictionary
+ returned by 'get_config_vars()'. Equivalent to
+ get_config_vars().get(name)
+ """
+ if name == 'SO':
+ import warnings
+
+ warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
+ return get_config_vars().get(name)
+
+
+@pass_none
+def _add_flags(value: str, type: str) -> str:
+ """
+ Add any flags from the environment for the given type.
+
+ type is the prefix to FLAGS in the environment key (e.g. "C" for "CFLAGS").
+ """
+ flags = os.environ.get(f'{type}FLAGS')
+ return f'{value} {flags}' if flags else value
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__init__.py
new file mode 100644
index 0000000..5a8ab06
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__init__.py
@@ -0,0 +1,42 @@
+"""
+Test suite for distutils.
+
+Tests for the command classes in the distutils.command package are
+included in distutils.tests as well, instead of using a separate
+distutils.command.tests package, since command identification is done
+by import rather than matching pre-defined names.
+"""
+
+import shutil
+from collections.abc import Sequence
+
+
+def missing_compiler_executable(cmd_names: Sequence[str] = []): # pragma: no cover
+ """Check if the compiler components used to build the interpreter exist.
+
+ Check for the existence of the compiler executables whose names are listed
+ in 'cmd_names' or all the compiler executables when 'cmd_names' is empty
+ and return the first missing executable or None when none is found
+ missing.
+
+ """
+ from distutils import ccompiler, errors, sysconfig
+
+ compiler = ccompiler.new_compiler()
+ sysconfig.customize_compiler(compiler)
+ if compiler.compiler_type == "msvc":
+ # MSVC has no executables, so check whether initialization succeeds
+ try:
+ compiler.initialize()
+ except errors.DistutilsPlatformError:
+ return "msvc"
+ for name in compiler.executables:
+ if cmd_names and name not in cmd_names:
+ continue
+ cmd = getattr(compiler, name)
+ if cmd_names:
+ assert cmd is not None, f"the '{name}' executable is not configured"
+ elif not cmd:
+ continue
+ if shutil.which(cmd[0]) is None:
+ return cmd[0]
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..c3413b9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/support.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/support.cpython-312.pyc
new file mode 100644
index 0000000..a2062c7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/support.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_archive_util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_archive_util.cpython-312.pyc
new file mode 100644
index 0000000..3d2af4e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_archive_util.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_bdist.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_bdist.cpython-312.pyc
new file mode 100644
index 0000000..b10be53
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_bdist.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_bdist_dumb.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_bdist_dumb.cpython-312.pyc
new file mode 100644
index 0000000..785d780
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_bdist_dumb.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_bdist_rpm.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_bdist_rpm.cpython-312.pyc
new file mode 100644
index 0000000..88acc76
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_bdist_rpm.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build.cpython-312.pyc
new file mode 100644
index 0000000..bca0a8d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_clib.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_clib.cpython-312.pyc
new file mode 100644
index 0000000..f910a98
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_clib.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_ext.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_ext.cpython-312.pyc
new file mode 100644
index 0000000..42c0d55
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_ext.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_py.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_py.cpython-312.pyc
new file mode 100644
index 0000000..b7cd0c0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_py.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_scripts.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_scripts.cpython-312.pyc
new file mode 100644
index 0000000..d05879f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_build_scripts.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_check.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_check.cpython-312.pyc
new file mode 100644
index 0000000..4abbe11
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_check.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_clean.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_clean.cpython-312.pyc
new file mode 100644
index 0000000..eb75c26
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_clean.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_cmd.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_cmd.cpython-312.pyc
new file mode 100644
index 0000000..c8551f8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_cmd.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_config_cmd.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_config_cmd.cpython-312.pyc
new file mode 100644
index 0000000..31f1f22
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_config_cmd.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_core.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_core.cpython-312.pyc
new file mode 100644
index 0000000..9dae7d9
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_core.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_dir_util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_dir_util.cpython-312.pyc
new file mode 100644
index 0000000..80e7996
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_dir_util.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_dist.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_dist.cpython-312.pyc
new file mode 100644
index 0000000..8a7789b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_dist.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_extension.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_extension.cpython-312.pyc
new file mode 100644
index 0000000..922586e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_extension.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_file_util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_file_util.cpython-312.pyc
new file mode 100644
index 0000000..50b6c26
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_file_util.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_filelist.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_filelist.cpython-312.pyc
new file mode 100644
index 0000000..6f4f68c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_filelist.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install.cpython-312.pyc
new file mode 100644
index 0000000..f95f445
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_data.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_data.cpython-312.pyc
new file mode 100644
index 0000000..8c43aeb
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_data.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_headers.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_headers.cpython-312.pyc
new file mode 100644
index 0000000..1818d05
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_headers.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_lib.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_lib.cpython-312.pyc
new file mode 100644
index 0000000..bc8f55b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_lib.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_scripts.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_scripts.cpython-312.pyc
new file mode 100644
index 0000000..0dfef38
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_install_scripts.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_log.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_log.cpython-312.pyc
new file mode 100644
index 0000000..2ba671f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_log.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_modified.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_modified.cpython-312.pyc
new file mode 100644
index 0000000..3841a43
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_modified.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_sdist.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_sdist.cpython-312.pyc
new file mode 100644
index 0000000..fb8a787
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_sdist.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_spawn.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_spawn.cpython-312.pyc
new file mode 100644
index 0000000..ca3305e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_spawn.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_sysconfig.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_sysconfig.cpython-312.pyc
new file mode 100644
index 0000000..483dea4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_sysconfig.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_text_file.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_text_file.cpython-312.pyc
new file mode 100644
index 0000000..7e3d481
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_text_file.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_util.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_util.cpython-312.pyc
new file mode 100644
index 0000000..09fd76b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_util.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_version.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_version.cpython-312.pyc
new file mode 100644
index 0000000..56358f4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_version.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_versionpredicate.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_versionpredicate.cpython-312.pyc
new file mode 100644
index 0000000..12986da
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/test_versionpredicate.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/unix_compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/unix_compat.cpython-312.pyc
new file mode 100644
index 0000000..1915fc2
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/__pycache__/unix_compat.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/compat/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/compat/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/compat/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/compat/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..562e703
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/compat/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/compat/__pycache__/py39.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/compat/__pycache__/py39.cpython-312.pyc
new file mode 100644
index 0000000..3bf299d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/compat/__pycache__/py39.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/compat/py39.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/compat/py39.py
new file mode 100644
index 0000000..aca3939
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/compat/py39.py
@@ -0,0 +1,40 @@
+import sys
+
+if sys.version_info >= (3, 10):
+ from test.support.import_helper import (
+ CleanImport as CleanImport,
+ )
+ from test.support.import_helper import (
+ DirsOnSysPath as DirsOnSysPath,
+ )
+ from test.support.os_helper import (
+ EnvironmentVarGuard as EnvironmentVarGuard,
+ )
+ from test.support.os_helper import (
+ rmtree as rmtree,
+ )
+ from test.support.os_helper import (
+ skip_unless_symlink as skip_unless_symlink,
+ )
+ from test.support.os_helper import (
+ unlink as unlink,
+ )
+else:
+ from test.support import (
+ CleanImport as CleanImport,
+ )
+ from test.support import (
+ DirsOnSysPath as DirsOnSysPath,
+ )
+ from test.support import (
+ EnvironmentVarGuard as EnvironmentVarGuard,
+ )
+ from test.support import (
+ rmtree as rmtree,
+ )
+ from test.support import (
+ skip_unless_symlink as skip_unless_symlink,
+ )
+ from test.support import (
+ unlink as unlink,
+ )
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/support.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/support.py
new file mode 100644
index 0000000..9cd2b8a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/support.py
@@ -0,0 +1,134 @@
+"""Support code for distutils test cases."""
+
+import itertools
+import os
+import pathlib
+import shutil
+import sys
+import sysconfig
+import tempfile
+from distutils.core import Distribution
+
+import pytest
+from more_itertools import always_iterable
+
+
+@pytest.mark.usefixtures('distutils_managed_tempdir')
+class TempdirManager:
+ """
+ Mix-in class that handles temporary directories for test cases.
+ """
+
+ def mkdtemp(self):
+ """Create a temporary directory that will be cleaned up.
+
+ Returns the path of the directory.
+ """
+ d = tempfile.mkdtemp()
+ self.tempdirs.append(d)
+ return d
+
+ def write_file(self, path, content='xxx'):
+ """Writes a file in the given path.
+
+ path can be a string or a sequence.
+ """
+ pathlib.Path(*always_iterable(path)).write_text(content, encoding='utf-8')
+
+ def create_dist(self, pkg_name='foo', **kw):
+ """Will generate a test environment.
+
+ This function creates:
+ - a Distribution instance using keywords
+ - a temporary directory with a package structure
+
+ It returns the package directory and the distribution
+ instance.
+ """
+ tmp_dir = self.mkdtemp()
+ pkg_dir = os.path.join(tmp_dir, pkg_name)
+ os.mkdir(pkg_dir)
+ dist = Distribution(attrs=kw)
+
+ return pkg_dir, dist
+
+
+class DummyCommand:
+ """Class to store options for retrieval via set_undefined_options()."""
+
+ def __init__(self, **kwargs):
+ vars(self).update(kwargs)
+
+ def ensure_finalized(self):
+ pass
+
+
+def copy_xxmodule_c(directory):
+ """Helper for tests that need the xxmodule.c source file.
+
+ Example use:
+
+ def test_compile(self):
+ copy_xxmodule_c(self.tmpdir)
+ self.assertIn('xxmodule.c', os.listdir(self.tmpdir))
+
+ If the source file can be found, it will be copied to *directory*. If not,
+ the test will be skipped. Errors during copy are not caught.
+ """
+ shutil.copy(_get_xxmodule_path(), os.path.join(directory, 'xxmodule.c'))
+
+
+def _get_xxmodule_path():
+ source_name = 'xxmodule.c' if sys.version_info > (3, 9) else 'xxmodule-3.8.c'
+ return os.path.join(os.path.dirname(__file__), source_name)
+
+
+def fixup_build_ext(cmd):
+ """Function needed to make build_ext tests pass.
+
+ When Python was built with --enable-shared on Unix, -L. is not enough to
+ find libpython.so, because regrtest runs in a tempdir, not in the
+ source directory where the .so lives.
+
+ When Python was built with in debug mode on Windows, build_ext commands
+ need their debug attribute set, and it is not done automatically for
+ some reason.
+
+ This function handles both of these things. Example use:
+
+ cmd = build_ext(dist)
+ support.fixup_build_ext(cmd)
+ cmd.ensure_finalized()
+
+ Unlike most other Unix platforms, Mac OS X embeds absolute paths
+ to shared libraries into executables, so the fixup is not needed there.
+ """
+ if os.name == 'nt':
+ cmd.debug = sys.executable.endswith('_d.exe')
+ elif sysconfig.get_config_var('Py_ENABLE_SHARED'):
+ # To further add to the shared builds fun on Unix, we can't just add
+ # library_dirs to the Extension() instance because that doesn't get
+ # plumbed through to the final compiler command.
+ runshared = sysconfig.get_config_var('RUNSHARED')
+ if runshared is None:
+ cmd.library_dirs = ['.']
+ else:
+ if sys.platform == 'darwin':
+ cmd.library_dirs = []
+ else:
+ name, equals, value = runshared.partition('=')
+ cmd.library_dirs = [d for d in value.split(os.pathsep) if d]
+
+
+def combine_markers(cls):
+ """
+ pytest will honor markers as found on the class, but when
+ markers are on multiple subclasses, only one appears. Use
+ this decorator to combine those markers.
+ """
+ cls.pytestmark = [
+ mark
+ for base in itertools.chain([cls], cls.__bases__)
+ for mark in getattr(base, 'pytestmark', [])
+ ]
+ return cls
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_archive_util.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_archive_util.py
new file mode 100644
index 0000000..3e4ed75
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_archive_util.py
@@ -0,0 +1,353 @@
+"""Tests for distutils.archive_util."""
+
+import functools
+import operator
+import os
+import pathlib
+import sys
+import tarfile
+from distutils import archive_util
+from distutils.archive_util import (
+ ARCHIVE_FORMATS,
+ check_archive_formats,
+ make_archive,
+ make_tarball,
+ make_zipfile,
+)
+from distutils.spawn import spawn
+from distutils.tests import support
+from os.path import splitdrive
+
+import path
+import pytest
+from test.support import patch
+
+from .unix_compat import UID_0_SUPPORT, grp, pwd, require_uid_0, require_unix_id
+
+
+def can_fs_encode(filename):
+ """
+ Return True if the filename can be saved in the file system.
+ """
+ if os.path.supports_unicode_filenames:
+ return True
+ try:
+ filename.encode(sys.getfilesystemencoding())
+ except UnicodeEncodeError:
+ return False
+ return True
+
+
+def all_equal(values):
+ return functools.reduce(operator.eq, values)
+
+
+def same_drive(*paths):
+ return all_equal(pathlib.Path(path).drive for path in paths)
+
+
+class ArchiveUtilTestCase(support.TempdirManager):
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_make_tarball(self, name='archive'):
+ # creating something to tar
+ tmpdir = self._create_files()
+ self._make_tarball(tmpdir, name, '.tar.gz')
+ # trying an uncompressed one
+ self._make_tarball(tmpdir, name, '.tar', compress=None)
+
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_make_tarball_gzip(self):
+ tmpdir = self._create_files()
+ self._make_tarball(tmpdir, 'archive', '.tar.gz', compress='gzip')
+
+ def test_make_tarball_bzip2(self):
+ pytest.importorskip('bz2')
+ tmpdir = self._create_files()
+ self._make_tarball(tmpdir, 'archive', '.tar.bz2', compress='bzip2')
+
+ def test_make_tarball_xz(self):
+ pytest.importorskip('lzma')
+ tmpdir = self._create_files()
+ self._make_tarball(tmpdir, 'archive', '.tar.xz', compress='xz')
+
+ @pytest.mark.skipif("not can_fs_encode('årchiv')")
+ def test_make_tarball_latin1(self):
+ """
+ Mirror test_make_tarball, except filename contains latin characters.
+ """
+ self.test_make_tarball('årchiv') # note this isn't a real word
+
+ @pytest.mark.skipif("not can_fs_encode('のアーカイブ')")
+ def test_make_tarball_extended(self):
+ """
+ Mirror test_make_tarball, except filename contains extended
+ characters outside the latin charset.
+ """
+ self.test_make_tarball('のアーカイブ') # japanese for archive
+
+ def _make_tarball(self, tmpdir, target_name, suffix, **kwargs):
+ tmpdir2 = self.mkdtemp()
+ if same_drive(tmpdir, tmpdir2):
+ pytest.skip("source and target should be on same drive")
+
+ base_name = os.path.join(tmpdir2, target_name)
+
+ # working with relative paths to avoid tar warnings
+ with path.Path(tmpdir):
+ make_tarball(splitdrive(base_name)[1], 'dist', **kwargs)
+
+ # check if the compressed tarball was created
+ tarball = base_name + suffix
+ assert os.path.exists(tarball)
+ assert self._tarinfo(tarball) == self._created_files
+
+ def _tarinfo(self, path):
+ tar = tarfile.open(path)
+ try:
+ names = tar.getnames()
+ names.sort()
+ return names
+ finally:
+ tar.close()
+
+ _zip_created_files = [
+ 'dist/',
+ 'dist/file1',
+ 'dist/file2',
+ 'dist/sub/',
+ 'dist/sub/file3',
+ 'dist/sub2/',
+ ]
+ _created_files = [p.rstrip('/') for p in _zip_created_files]
+
+ def _create_files(self):
+ # creating something to tar
+ tmpdir = self.mkdtemp()
+ dist = os.path.join(tmpdir, 'dist')
+ os.mkdir(dist)
+ self.write_file([dist, 'file1'], 'xxx')
+ self.write_file([dist, 'file2'], 'xxx')
+ os.mkdir(os.path.join(dist, 'sub'))
+ self.write_file([dist, 'sub', 'file3'], 'xxx')
+ os.mkdir(os.path.join(dist, 'sub2'))
+ return tmpdir
+
+ @pytest.mark.usefixtures('needs_zlib')
+ @pytest.mark.skipif("not (shutil.which('tar') and shutil.which('gzip'))")
+ def test_tarfile_vs_tar(self):
+ tmpdir = self._create_files()
+ tmpdir2 = self.mkdtemp()
+ base_name = os.path.join(tmpdir2, 'archive')
+ old_dir = os.getcwd()
+ os.chdir(tmpdir)
+ try:
+ make_tarball(base_name, 'dist')
+ finally:
+ os.chdir(old_dir)
+
+ # check if the compressed tarball was created
+ tarball = base_name + '.tar.gz'
+ assert os.path.exists(tarball)
+
+ # now create another tarball using `tar`
+ tarball2 = os.path.join(tmpdir, 'archive2.tar.gz')
+ tar_cmd = ['tar', '-cf', 'archive2.tar', 'dist']
+ gzip_cmd = ['gzip', '-f', '-9', 'archive2.tar']
+ old_dir = os.getcwd()
+ os.chdir(tmpdir)
+ try:
+ spawn(tar_cmd)
+ spawn(gzip_cmd)
+ finally:
+ os.chdir(old_dir)
+
+ assert os.path.exists(tarball2)
+ # let's compare both tarballs
+ assert self._tarinfo(tarball) == self._created_files
+ assert self._tarinfo(tarball2) == self._created_files
+
+ # trying an uncompressed one
+ base_name = os.path.join(tmpdir2, 'archive')
+ old_dir = os.getcwd()
+ os.chdir(tmpdir)
+ try:
+ make_tarball(base_name, 'dist', compress=None)
+ finally:
+ os.chdir(old_dir)
+ tarball = base_name + '.tar'
+ assert os.path.exists(tarball)
+
+ # now for a dry_run
+ base_name = os.path.join(tmpdir2, 'archive')
+ old_dir = os.getcwd()
+ os.chdir(tmpdir)
+ try:
+ make_tarball(base_name, 'dist', compress=None, dry_run=True)
+ finally:
+ os.chdir(old_dir)
+ tarball = base_name + '.tar'
+ assert os.path.exists(tarball)
+
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_make_zipfile(self):
+ zipfile = pytest.importorskip('zipfile')
+ # creating something to tar
+ tmpdir = self._create_files()
+ base_name = os.path.join(self.mkdtemp(), 'archive')
+ with path.Path(tmpdir):
+ make_zipfile(base_name, 'dist')
+
+ # check if the compressed tarball was created
+ tarball = base_name + '.zip'
+ assert os.path.exists(tarball)
+ with zipfile.ZipFile(tarball) as zf:
+ assert sorted(zf.namelist()) == self._zip_created_files
+
+ def test_make_zipfile_no_zlib(self):
+ zipfile = pytest.importorskip('zipfile')
+ patch(self, archive_util.zipfile, 'zlib', None) # force zlib ImportError
+
+ called = []
+ zipfile_class = zipfile.ZipFile
+
+ def fake_zipfile(*a, **kw):
+ if kw.get('compression', None) == zipfile.ZIP_STORED:
+ called.append((a, kw))
+ return zipfile_class(*a, **kw)
+
+ patch(self, archive_util.zipfile, 'ZipFile', fake_zipfile)
+
+ # create something to tar and compress
+ tmpdir = self._create_files()
+ base_name = os.path.join(self.mkdtemp(), 'archive')
+ with path.Path(tmpdir):
+ make_zipfile(base_name, 'dist')
+
+ tarball = base_name + '.zip'
+ assert called == [((tarball, "w"), {'compression': zipfile.ZIP_STORED})]
+ assert os.path.exists(tarball)
+ with zipfile.ZipFile(tarball) as zf:
+ assert sorted(zf.namelist()) == self._zip_created_files
+
+ def test_check_archive_formats(self):
+ assert check_archive_formats(['gztar', 'xxx', 'zip']) == 'xxx'
+ assert (
+ check_archive_formats(['gztar', 'bztar', 'xztar', 'ztar', 'tar', 'zip'])
+ is None
+ )
+
+ def test_make_archive(self):
+ tmpdir = self.mkdtemp()
+ base_name = os.path.join(tmpdir, 'archive')
+ with pytest.raises(ValueError):
+ make_archive(base_name, 'xxx')
+
+ def test_make_archive_cwd(self):
+ current_dir = os.getcwd()
+
+ def _breaks(*args, **kw):
+ raise RuntimeError()
+
+ ARCHIVE_FORMATS['xxx'] = (_breaks, [], 'xxx file')
+ try:
+ try:
+ make_archive('xxx', 'xxx', root_dir=self.mkdtemp())
+ except Exception:
+ pass
+ assert os.getcwd() == current_dir
+ finally:
+ ARCHIVE_FORMATS.pop('xxx')
+
+ def test_make_archive_tar(self):
+ base_dir = self._create_files()
+ base_name = os.path.join(self.mkdtemp(), 'archive')
+ res = make_archive(base_name, 'tar', base_dir, 'dist')
+ assert os.path.exists(res)
+ assert os.path.basename(res) == 'archive.tar'
+ assert self._tarinfo(res) == self._created_files
+
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_make_archive_gztar(self):
+ base_dir = self._create_files()
+ base_name = os.path.join(self.mkdtemp(), 'archive')
+ res = make_archive(base_name, 'gztar', base_dir, 'dist')
+ assert os.path.exists(res)
+ assert os.path.basename(res) == 'archive.tar.gz'
+ assert self._tarinfo(res) == self._created_files
+
+ def test_make_archive_bztar(self):
+ pytest.importorskip('bz2')
+ base_dir = self._create_files()
+ base_name = os.path.join(self.mkdtemp(), 'archive')
+ res = make_archive(base_name, 'bztar', base_dir, 'dist')
+ assert os.path.exists(res)
+ assert os.path.basename(res) == 'archive.tar.bz2'
+ assert self._tarinfo(res) == self._created_files
+
+ def test_make_archive_xztar(self):
+ pytest.importorskip('lzma')
+ base_dir = self._create_files()
+ base_name = os.path.join(self.mkdtemp(), 'archive')
+ res = make_archive(base_name, 'xztar', base_dir, 'dist')
+ assert os.path.exists(res)
+ assert os.path.basename(res) == 'archive.tar.xz'
+ assert self._tarinfo(res) == self._created_files
+
+ def test_make_archive_owner_group(self):
+ # testing make_archive with owner and group, with various combinations
+ # this works even if there's not gid/uid support
+ if UID_0_SUPPORT:
+ group = grp.getgrgid(0)[0]
+ owner = pwd.getpwuid(0)[0]
+ else:
+ group = owner = 'root'
+
+ base_dir = self._create_files()
+ root_dir = self.mkdtemp()
+ base_name = os.path.join(self.mkdtemp(), 'archive')
+ res = make_archive(
+ base_name, 'zip', root_dir, base_dir, owner=owner, group=group
+ )
+ assert os.path.exists(res)
+
+ res = make_archive(base_name, 'zip', root_dir, base_dir)
+ assert os.path.exists(res)
+
+ res = make_archive(
+ base_name, 'tar', root_dir, base_dir, owner=owner, group=group
+ )
+ assert os.path.exists(res)
+
+ res = make_archive(
+ base_name, 'tar', root_dir, base_dir, owner='kjhkjhkjg', group='oihohoh'
+ )
+ assert os.path.exists(res)
+
+ @pytest.mark.usefixtures('needs_zlib')
+ @require_unix_id
+ @require_uid_0
+ def test_tarfile_root_owner(self):
+ tmpdir = self._create_files()
+ base_name = os.path.join(self.mkdtemp(), 'archive')
+ old_dir = os.getcwd()
+ os.chdir(tmpdir)
+ group = grp.getgrgid(0)[0]
+ owner = pwd.getpwuid(0)[0]
+ try:
+ archive_name = make_tarball(
+ base_name, 'dist', compress=None, owner=owner, group=group
+ )
+ finally:
+ os.chdir(old_dir)
+
+ # check if the compressed tarball was created
+ assert os.path.exists(archive_name)
+
+ # now checks the rights
+ archive = tarfile.open(archive_name)
+ try:
+ for member in archive.getmembers():
+ assert member.uid == 0
+ assert member.gid == 0
+ finally:
+ archive.close()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_bdist.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_bdist.py
new file mode 100644
index 0000000..d5696fc
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_bdist.py
@@ -0,0 +1,47 @@
+"""Tests for distutils.command.bdist."""
+
+from distutils.command.bdist import bdist
+from distutils.tests import support
+
+
+class TestBuild(support.TempdirManager):
+ def test_formats(self):
+ # let's create a command and make sure
+ # we can set the format
+ dist = self.create_dist()[1]
+ cmd = bdist(dist)
+ cmd.formats = ['gztar']
+ cmd.ensure_finalized()
+ assert cmd.formats == ['gztar']
+
+ # what formats does bdist offer?
+ formats = [
+ 'bztar',
+ 'gztar',
+ 'rpm',
+ 'tar',
+ 'xztar',
+ 'zip',
+ 'ztar',
+ ]
+ found = sorted(cmd.format_commands)
+ assert found == formats
+
+ def test_skip_build(self):
+ # bug #10946: bdist --skip-build should trickle down to subcommands
+ dist = self.create_dist()[1]
+ cmd = bdist(dist)
+ cmd.skip_build = True
+ cmd.ensure_finalized()
+ dist.command_obj['bdist'] = cmd
+
+ names = [
+ 'bdist_dumb',
+ ] # bdist_rpm does not support --skip-build
+
+ for name in names:
+ subcmd = cmd.get_finalized_command(name)
+ if getattr(subcmd, '_unsupported', False):
+ # command is not supported on this build
+ continue
+ assert subcmd.skip_build, f'{name} should take --skip-build from bdist'
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_bdist_dumb.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_bdist_dumb.py
new file mode 100644
index 0000000..1fc51d2
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_bdist_dumb.py
@@ -0,0 +1,78 @@
+"""Tests for distutils.command.bdist_dumb."""
+
+import os
+import sys
+import zipfile
+from distutils.command.bdist_dumb import bdist_dumb
+from distutils.core import Distribution
+from distutils.tests import support
+
+import pytest
+
+SETUP_PY = """\
+from distutils.core import setup
+import foo
+
+setup(name='foo', version='0.1', py_modules=['foo'],
+ url='xxx', author='xxx', author_email='xxx')
+
+"""
+
+
+@support.combine_markers
+@pytest.mark.usefixtures('save_env')
+@pytest.mark.usefixtures('save_argv')
+@pytest.mark.usefixtures('save_cwd')
+class TestBuildDumb(
+ support.TempdirManager,
+):
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_simple_built(self):
+ # let's create a simple package
+ tmp_dir = self.mkdtemp()
+ pkg_dir = os.path.join(tmp_dir, 'foo')
+ os.mkdir(pkg_dir)
+ self.write_file((pkg_dir, 'setup.py'), SETUP_PY)
+ self.write_file((pkg_dir, 'foo.py'), '#')
+ self.write_file((pkg_dir, 'MANIFEST.in'), 'include foo.py')
+ self.write_file((pkg_dir, 'README'), '')
+
+ dist = Distribution({
+ 'name': 'foo',
+ 'version': '0.1',
+ 'py_modules': ['foo'],
+ 'url': 'xxx',
+ 'author': 'xxx',
+ 'author_email': 'xxx',
+ })
+ dist.script_name = 'setup.py'
+ os.chdir(pkg_dir)
+
+ sys.argv = ['setup.py']
+ cmd = bdist_dumb(dist)
+
+ # so the output is the same no matter
+ # what is the platform
+ cmd.format = 'zip'
+
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # see what we have
+ dist_created = os.listdir(os.path.join(pkg_dir, 'dist'))
+ base = f"{dist.get_fullname()}.{cmd.plat_name}.zip"
+
+ assert dist_created == [base]
+
+ # now let's check what we have in the zip file
+ fp = zipfile.ZipFile(os.path.join('dist', base))
+ try:
+ contents = fp.namelist()
+ finally:
+ fp.close()
+
+ contents = sorted(filter(None, map(os.path.basename, contents)))
+ wanted = ['foo-0.1-py{}.{}.egg-info'.format(*sys.version_info[:2]), 'foo.py']
+ if not sys.dont_write_bytecode:
+ wanted.append(f'foo.{sys.implementation.cache_tag}.pyc')
+ assert contents == sorted(wanted)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_bdist_rpm.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_bdist_rpm.py
new file mode 100644
index 0000000..7505143
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_bdist_rpm.py
@@ -0,0 +1,127 @@
+"""Tests for distutils.command.bdist_rpm."""
+
+import os
+import shutil # noqa: F401
+import sys
+from distutils.command.bdist_rpm import bdist_rpm
+from distutils.core import Distribution
+from distutils.tests import support
+
+import pytest
+from test.support import requires_zlib
+
+SETUP_PY = """\
+from distutils.core import setup
+import foo
+
+setup(name='foo', version='0.1', py_modules=['foo'],
+ url='xxx', author='xxx', author_email='xxx')
+
+"""
+
+
+@pytest.fixture(autouse=True)
+def sys_executable_encodable():
+ try:
+ sys.executable.encode('UTF-8')
+ except UnicodeEncodeError:
+ pytest.skip("sys.executable is not encodable to UTF-8")
+
+
+mac_woes = pytest.mark.skipif(
+ "not sys.platform.startswith('linux')",
+ reason='spurious sdtout/stderr output under macOS',
+)
+
+
+@pytest.mark.usefixtures('save_env')
+@pytest.mark.usefixtures('save_argv')
+@pytest.mark.usefixtures('save_cwd')
+class TestBuildRpm(
+ support.TempdirManager,
+):
+ @mac_woes
+ @requires_zlib()
+ @pytest.mark.skipif("not shutil.which('rpm')")
+ @pytest.mark.skipif("not shutil.which('rpmbuild')")
+ def test_quiet(self):
+ # let's create a package
+ tmp_dir = self.mkdtemp()
+ os.environ['HOME'] = tmp_dir # to confine dir '.rpmdb' creation
+ pkg_dir = os.path.join(tmp_dir, 'foo')
+ os.mkdir(pkg_dir)
+ self.write_file((pkg_dir, 'setup.py'), SETUP_PY)
+ self.write_file((pkg_dir, 'foo.py'), '#')
+ self.write_file((pkg_dir, 'MANIFEST.in'), 'include foo.py')
+ self.write_file((pkg_dir, 'README'), '')
+
+ dist = Distribution({
+ 'name': 'foo',
+ 'version': '0.1',
+ 'py_modules': ['foo'],
+ 'url': 'xxx',
+ 'author': 'xxx',
+ 'author_email': 'xxx',
+ })
+ dist.script_name = 'setup.py'
+ os.chdir(pkg_dir)
+
+ sys.argv = ['setup.py']
+ cmd = bdist_rpm(dist)
+ cmd.fix_python = True
+
+ # running in quiet mode
+ cmd.quiet = True
+ cmd.ensure_finalized()
+ cmd.run()
+
+ dist_created = os.listdir(os.path.join(pkg_dir, 'dist'))
+ assert 'foo-0.1-1.noarch.rpm' in dist_created
+
+ # bug #2945: upload ignores bdist_rpm files
+ assert ('bdist_rpm', 'any', 'dist/foo-0.1-1.src.rpm') in dist.dist_files
+ assert ('bdist_rpm', 'any', 'dist/foo-0.1-1.noarch.rpm') in dist.dist_files
+
+ @mac_woes
+ @requires_zlib()
+ # https://bugs.python.org/issue1533164
+ @pytest.mark.skipif("not shutil.which('rpm')")
+ @pytest.mark.skipif("not shutil.which('rpmbuild')")
+ def test_no_optimize_flag(self):
+ # let's create a package that breaks bdist_rpm
+ tmp_dir = self.mkdtemp()
+ os.environ['HOME'] = tmp_dir # to confine dir '.rpmdb' creation
+ pkg_dir = os.path.join(tmp_dir, 'foo')
+ os.mkdir(pkg_dir)
+ self.write_file((pkg_dir, 'setup.py'), SETUP_PY)
+ self.write_file((pkg_dir, 'foo.py'), '#')
+ self.write_file((pkg_dir, 'MANIFEST.in'), 'include foo.py')
+ self.write_file((pkg_dir, 'README'), '')
+
+ dist = Distribution({
+ 'name': 'foo',
+ 'version': '0.1',
+ 'py_modules': ['foo'],
+ 'url': 'xxx',
+ 'author': 'xxx',
+ 'author_email': 'xxx',
+ })
+ dist.script_name = 'setup.py'
+ os.chdir(pkg_dir)
+
+ sys.argv = ['setup.py']
+ cmd = bdist_rpm(dist)
+ cmd.fix_python = True
+
+ cmd.quiet = True
+ cmd.ensure_finalized()
+ cmd.run()
+
+ dist_created = os.listdir(os.path.join(pkg_dir, 'dist'))
+ assert 'foo-0.1-1.noarch.rpm' in dist_created
+
+ # bug #2945: upload ignores bdist_rpm files
+ assert ('bdist_rpm', 'any', 'dist/foo-0.1-1.src.rpm') in dist.dist_files
+ assert ('bdist_rpm', 'any', 'dist/foo-0.1-1.noarch.rpm') in dist.dist_files
+
+ os.remove(os.path.join(pkg_dir, 'dist', 'foo-0.1-1.noarch.rpm'))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build.py
new file mode 100644
index 0000000..f7fe69a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build.py
@@ -0,0 +1,49 @@
+"""Tests for distutils.command.build."""
+
+import os
+import sys
+from distutils.command.build import build
+from distutils.tests import support
+from sysconfig import get_config_var, get_platform
+
+
+class TestBuild(support.TempdirManager):
+ def test_finalize_options(self):
+ pkg_dir, dist = self.create_dist()
+ cmd = build(dist)
+ cmd.finalize_options()
+
+ # if not specified, plat_name gets the current platform
+ assert cmd.plat_name == get_platform()
+
+ # build_purelib is build + lib
+ wanted = os.path.join(cmd.build_base, 'lib')
+ assert cmd.build_purelib == wanted
+
+ # build_platlib is 'build/lib.platform-cache_tag[-pydebug]'
+ # examples:
+ # build/lib.macosx-10.3-i386-cpython39
+ plat_spec = f'.{cmd.plat_name}-{sys.implementation.cache_tag}'
+ if get_config_var('Py_GIL_DISABLED'):
+ plat_spec += 't'
+ if hasattr(sys, 'gettotalrefcount'):
+ assert cmd.build_platlib.endswith('-pydebug')
+ plat_spec += '-pydebug'
+ wanted = os.path.join(cmd.build_base, 'lib' + plat_spec)
+ assert cmd.build_platlib == wanted
+
+ # by default, build_lib = build_purelib
+ assert cmd.build_lib == cmd.build_purelib
+
+ # build_temp is build/temp.
+ wanted = os.path.join(cmd.build_base, 'temp' + plat_spec)
+ assert cmd.build_temp == wanted
+
+ # build_scripts is build/scripts-x.x
+ wanted = os.path.join(
+ cmd.build_base, f'scripts-{sys.version_info.major}.{sys.version_info.minor}'
+ )
+ assert cmd.build_scripts == wanted
+
+ # executable is os.path.normpath(sys.executable)
+ assert cmd.executable == os.path.normpath(sys.executable)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_clib.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_clib.py
new file mode 100644
index 0000000..f76f26b
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_clib.py
@@ -0,0 +1,134 @@
+"""Tests for distutils.command.build_clib."""
+
+import os
+from distutils.command.build_clib import build_clib
+from distutils.errors import DistutilsSetupError
+from distutils.tests import missing_compiler_executable, support
+
+import pytest
+
+
+class TestBuildCLib(support.TempdirManager):
+ def test_check_library_dist(self):
+ pkg_dir, dist = self.create_dist()
+ cmd = build_clib(dist)
+
+ # 'libraries' option must be a list
+ with pytest.raises(DistutilsSetupError):
+ cmd.check_library_list('foo')
+
+ # each element of 'libraries' must a 2-tuple
+ with pytest.raises(DistutilsSetupError):
+ cmd.check_library_list(['foo1', 'foo2'])
+
+ # first element of each tuple in 'libraries'
+ # must be a string (the library name)
+ with pytest.raises(DistutilsSetupError):
+ cmd.check_library_list([(1, 'foo1'), ('name', 'foo2')])
+
+ # library name may not contain directory separators
+ with pytest.raises(DistutilsSetupError):
+ cmd.check_library_list(
+ [('name', 'foo1'), ('another/name', 'foo2')],
+ )
+
+ # second element of each tuple must be a dictionary (build info)
+ with pytest.raises(DistutilsSetupError):
+ cmd.check_library_list(
+ [('name', {}), ('another', 'foo2')],
+ )
+
+ # those work
+ libs = [('name', {}), ('name', {'ok': 'good'})]
+ cmd.check_library_list(libs)
+
+ def test_get_source_files(self):
+ pkg_dir, dist = self.create_dist()
+ cmd = build_clib(dist)
+
+ # "in 'libraries' option 'sources' must be present and must be
+ # a list of source filenames
+ cmd.libraries = [('name', {})]
+ with pytest.raises(DistutilsSetupError):
+ cmd.get_source_files()
+
+ cmd.libraries = [('name', {'sources': 1})]
+ with pytest.raises(DistutilsSetupError):
+ cmd.get_source_files()
+
+ cmd.libraries = [('name', {'sources': ['a', 'b']})]
+ assert cmd.get_source_files() == ['a', 'b']
+
+ cmd.libraries = [('name', {'sources': ('a', 'b')})]
+ assert cmd.get_source_files() == ['a', 'b']
+
+ cmd.libraries = [
+ ('name', {'sources': ('a', 'b')}),
+ ('name2', {'sources': ['c', 'd']}),
+ ]
+ assert cmd.get_source_files() == ['a', 'b', 'c', 'd']
+
+ def test_build_libraries(self):
+ pkg_dir, dist = self.create_dist()
+ cmd = build_clib(dist)
+
+ class FakeCompiler:
+ def compile(*args, **kw):
+ pass
+
+ create_static_lib = compile
+
+ cmd.compiler = FakeCompiler()
+
+ # build_libraries is also doing a bit of typo checking
+ lib = [('name', {'sources': 'notvalid'})]
+ with pytest.raises(DistutilsSetupError):
+ cmd.build_libraries(lib)
+
+ lib = [('name', {'sources': list()})]
+ cmd.build_libraries(lib)
+
+ lib = [('name', {'sources': tuple()})]
+ cmd.build_libraries(lib)
+
+ def test_finalize_options(self):
+ pkg_dir, dist = self.create_dist()
+ cmd = build_clib(dist)
+
+ cmd.include_dirs = 'one-dir'
+ cmd.finalize_options()
+ assert cmd.include_dirs == ['one-dir']
+
+ cmd.include_dirs = None
+ cmd.finalize_options()
+ assert cmd.include_dirs == []
+
+ cmd.distribution.libraries = 'WONTWORK'
+ with pytest.raises(DistutilsSetupError):
+ cmd.finalize_options()
+
+ @pytest.mark.skipif('platform.system() == "Windows"')
+ def test_run(self):
+ pkg_dir, dist = self.create_dist()
+ cmd = build_clib(dist)
+
+ foo_c = os.path.join(pkg_dir, 'foo.c')
+ self.write_file(foo_c, 'int main(void) { return 1;}\n')
+ cmd.libraries = [('foo', {'sources': [foo_c]})]
+
+ build_temp = os.path.join(pkg_dir, 'build')
+ os.mkdir(build_temp)
+ cmd.build_temp = build_temp
+ cmd.build_clib = build_temp
+
+ # Before we run the command, we want to make sure
+ # all commands are present on the system.
+ ccmd = missing_compiler_executable()
+ if ccmd is not None:
+ self.skipTest(f'The {ccmd!r} command is not found')
+
+ # this should work
+ cmd.run()
+
+ # let's check the result
+ assert 'libfoo.a' in os.listdir(build_temp)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_ext.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_ext.py
new file mode 100644
index 0000000..dab0507
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_ext.py
@@ -0,0 +1,628 @@
+import contextlib
+import glob
+import importlib
+import os.path
+import platform
+import re
+import shutil
+import site
+import subprocess
+import sys
+import tempfile
+import textwrap
+import time
+from distutils import sysconfig
+from distutils.command.build_ext import build_ext
+from distutils.core import Distribution
+from distutils.errors import (
+ CompileError,
+ DistutilsPlatformError,
+ DistutilsSetupError,
+ UnknownFileError,
+)
+from distutils.extension import Extension
+from distutils.tests import missing_compiler_executable
+from distutils.tests.support import TempdirManager, copy_xxmodule_c, fixup_build_ext
+from io import StringIO
+
+import jaraco.path
+import path
+import pytest
+from test import support
+
+from .compat import py39 as import_helper
+
+
+@pytest.fixture()
+def user_site_dir(request):
+ self = request.instance
+ self.tmp_dir = self.mkdtemp()
+ self.tmp_path = path.Path(self.tmp_dir)
+ from distutils.command import build_ext
+
+ orig_user_base = site.USER_BASE
+
+ site.USER_BASE = self.mkdtemp()
+ build_ext.USER_BASE = site.USER_BASE
+
+ # bpo-30132: On Windows, a .pdb file may be created in the current
+ # working directory. Create a temporary working directory to cleanup
+ # everything at the end of the test.
+ with self.tmp_path:
+ yield
+
+ site.USER_BASE = orig_user_base
+ build_ext.USER_BASE = orig_user_base
+
+ if sys.platform == 'cygwin':
+ time.sleep(1)
+
+
+@contextlib.contextmanager
+def safe_extension_import(name, path):
+ with import_helper.CleanImport(name):
+ with extension_redirect(name, path) as new_path:
+ with import_helper.DirsOnSysPath(new_path):
+ yield
+
+
+@contextlib.contextmanager
+def extension_redirect(mod, path):
+ """
+ Tests will fail to tear down an extension module if it's been imported.
+
+ Before importing, copy the file to a temporary directory that won't
+ be cleaned up. Yield the new path.
+ """
+ if platform.system() != "Windows" and sys.platform != "cygwin":
+ yield path
+ return
+ with import_helper.DirsOnSysPath(path):
+ spec = importlib.util.find_spec(mod)
+ filename = os.path.basename(spec.origin)
+ trash_dir = tempfile.mkdtemp(prefix='deleteme')
+ dest = os.path.join(trash_dir, os.path.basename(filename))
+ shutil.copy(spec.origin, dest)
+ yield trash_dir
+ # TODO: can the file be scheduled for deletion?
+
+
+@pytest.mark.usefixtures('user_site_dir')
+class TestBuildExt(TempdirManager):
+ def build_ext(self, *args, **kwargs):
+ return build_ext(*args, **kwargs)
+
+ @pytest.mark.parametrize("copy_so", [False])
+ def test_build_ext(self, copy_so):
+ missing_compiler_executable()
+ copy_xxmodule_c(self.tmp_dir)
+ xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
+ xx_ext = Extension('xx', [xx_c])
+ if sys.platform != "win32":
+ if not copy_so:
+ xx_ext = Extension(
+ 'xx',
+ [xx_c],
+ library_dirs=['/usr/lib'],
+ libraries=['z'],
+ runtime_library_dirs=['/usr/lib'],
+ )
+ elif sys.platform == 'linux':
+ libz_so = {
+ os.path.realpath(name) for name in glob.iglob('/usr/lib*/libz.so*')
+ }
+ libz_so = sorted(libz_so, key=lambda lib_path: len(lib_path))
+ shutil.copyfile(libz_so[-1], '/tmp/libxx_z.so')
+
+ xx_ext = Extension(
+ 'xx',
+ [xx_c],
+ library_dirs=['/tmp'],
+ libraries=['xx_z'],
+ runtime_library_dirs=['/tmp'],
+ )
+ dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
+ dist.package_dir = self.tmp_dir
+ cmd = self.build_ext(dist)
+ fixup_build_ext(cmd)
+ cmd.build_lib = self.tmp_dir
+ cmd.build_temp = self.tmp_dir
+
+ old_stdout = sys.stdout
+ if not support.verbose:
+ # silence compiler output
+ sys.stdout = StringIO()
+ try:
+ cmd.ensure_finalized()
+ cmd.run()
+ finally:
+ sys.stdout = old_stdout
+
+ with safe_extension_import('xx', self.tmp_dir):
+ self._test_xx(copy_so)
+
+ if sys.platform == 'linux' and copy_so:
+ os.unlink('/tmp/libxx_z.so')
+
+ @staticmethod
+ def _test_xx(copy_so):
+ import xx # type: ignore[import-not-found] # Module generated for tests
+
+ for attr in ('error', 'foo', 'new', 'roj'):
+ assert hasattr(xx, attr)
+
+ assert xx.foo(2, 5) == 7
+ assert xx.foo(13, 15) == 28
+ assert xx.new().demo() is None
+ if support.HAVE_DOCSTRINGS:
+ doc = 'This is a template module just for instruction.'
+ assert xx.__doc__ == doc
+ assert isinstance(xx.Null(), xx.Null)
+ assert isinstance(xx.Str(), xx.Str)
+
+ if sys.platform == 'linux':
+ so_headers = subprocess.check_output(
+ ["readelf", "-d", xx.__file__], universal_newlines=True
+ )
+ import pprint
+
+ pprint.pprint(so_headers)
+ rpaths = [
+ rpath
+ for line in so_headers.split("\n")
+ if "RPATH" in line or "RUNPATH" in line
+ for rpath in line.split()[2][1:-1].split(":")
+ ]
+ if not copy_so:
+ pprint.pprint(rpaths)
+ # Linked against a library in /usr/lib{,64}
+ assert "/usr/lib" not in rpaths and "/usr/lib64" not in rpaths
+ else:
+ # Linked against a library in /tmp
+ assert "/tmp" in rpaths
+ # The import is the real test here
+
+ def test_solaris_enable_shared(self):
+ dist = Distribution({'name': 'xx'})
+ cmd = self.build_ext(dist)
+ old = sys.platform
+
+ sys.platform = 'sunos' # fooling finalize_options
+ from distutils.sysconfig import _config_vars
+
+ old_var = _config_vars.get('Py_ENABLE_SHARED')
+ _config_vars['Py_ENABLE_SHARED'] = True
+ try:
+ cmd.ensure_finalized()
+ finally:
+ sys.platform = old
+ if old_var is None:
+ del _config_vars['Py_ENABLE_SHARED']
+ else:
+ _config_vars['Py_ENABLE_SHARED'] = old_var
+
+ # make sure we get some library dirs under solaris
+ assert len(cmd.library_dirs) > 0
+
+ def test_user_site(self):
+ import site
+
+ dist = Distribution({'name': 'xx'})
+ cmd = self.build_ext(dist)
+
+ # making sure the user option is there
+ options = [name for name, short, label in cmd.user_options]
+ assert 'user' in options
+
+ # setting a value
+ cmd.user = True
+
+ # setting user based lib and include
+ lib = os.path.join(site.USER_BASE, 'lib')
+ incl = os.path.join(site.USER_BASE, 'include')
+ os.mkdir(lib)
+ os.mkdir(incl)
+
+ # let's run finalize
+ cmd.ensure_finalized()
+
+ # see if include_dirs and library_dirs
+ # were set
+ assert lib in cmd.library_dirs
+ assert lib in cmd.rpath
+ assert incl in cmd.include_dirs
+
+ def test_optional_extension(self):
+ # this extension will fail, but let's ignore this failure
+ # with the optional argument.
+ modules = [Extension('foo', ['xxx'], optional=False)]
+ dist = Distribution({'name': 'xx', 'ext_modules': modules})
+ cmd = self.build_ext(dist)
+ cmd.ensure_finalized()
+ with pytest.raises((UnknownFileError, CompileError)):
+ cmd.run() # should raise an error
+
+ modules = [Extension('foo', ['xxx'], optional=True)]
+ dist = Distribution({'name': 'xx', 'ext_modules': modules})
+ cmd = self.build_ext(dist)
+ cmd.ensure_finalized()
+ cmd.run() # should pass
+
+ def test_finalize_options(self):
+ # Make sure Python's include directories (for Python.h, pyconfig.h,
+ # etc.) are in the include search path.
+ modules = [Extension('foo', ['xxx'], optional=False)]
+ dist = Distribution({'name': 'xx', 'ext_modules': modules})
+ cmd = self.build_ext(dist)
+ cmd.finalize_options()
+
+ py_include = sysconfig.get_python_inc()
+ for p in py_include.split(os.path.pathsep):
+ assert p in cmd.include_dirs
+
+ plat_py_include = sysconfig.get_python_inc(plat_specific=True)
+ for p in plat_py_include.split(os.path.pathsep):
+ assert p in cmd.include_dirs
+
+ # make sure cmd.libraries is turned into a list
+ # if it's a string
+ cmd = self.build_ext(dist)
+ cmd.libraries = 'my_lib, other_lib lastlib'
+ cmd.finalize_options()
+ assert cmd.libraries == ['my_lib', 'other_lib', 'lastlib']
+
+ # make sure cmd.library_dirs is turned into a list
+ # if it's a string
+ cmd = self.build_ext(dist)
+ cmd.library_dirs = f'my_lib_dir{os.pathsep}other_lib_dir'
+ cmd.finalize_options()
+ assert 'my_lib_dir' in cmd.library_dirs
+ assert 'other_lib_dir' in cmd.library_dirs
+
+ # make sure rpath is turned into a list
+ # if it's a string
+ cmd = self.build_ext(dist)
+ cmd.rpath = f'one{os.pathsep}two'
+ cmd.finalize_options()
+ assert cmd.rpath == ['one', 'two']
+
+ # make sure cmd.link_objects is turned into a list
+ # if it's a string
+ cmd = build_ext(dist)
+ cmd.link_objects = 'one two,three'
+ cmd.finalize_options()
+ assert cmd.link_objects == ['one', 'two', 'three']
+
+ # XXX more tests to perform for win32
+
+ # make sure define is turned into 2-tuples
+ # strings if they are ','-separated strings
+ cmd = self.build_ext(dist)
+ cmd.define = 'one,two'
+ cmd.finalize_options()
+ assert cmd.define == [('one', '1'), ('two', '1')]
+
+ # make sure undef is turned into a list of
+ # strings if they are ','-separated strings
+ cmd = self.build_ext(dist)
+ cmd.undef = 'one,two'
+ cmd.finalize_options()
+ assert cmd.undef == ['one', 'two']
+
+ # make sure swig_opts is turned into a list
+ cmd = self.build_ext(dist)
+ cmd.swig_opts = None
+ cmd.finalize_options()
+ assert cmd.swig_opts == []
+
+ cmd = self.build_ext(dist)
+ cmd.swig_opts = '1 2'
+ cmd.finalize_options()
+ assert cmd.swig_opts == ['1', '2']
+
+ def test_check_extensions_list(self):
+ dist = Distribution()
+ cmd = self.build_ext(dist)
+ cmd.finalize_options()
+
+ # 'extensions' option must be a list of Extension instances
+ with pytest.raises(DistutilsSetupError):
+ cmd.check_extensions_list('foo')
+
+ # each element of 'ext_modules' option must be an
+ # Extension instance or 2-tuple
+ exts = [('bar', 'foo', 'bar'), 'foo']
+ with pytest.raises(DistutilsSetupError):
+ cmd.check_extensions_list(exts)
+
+ # first element of each tuple in 'ext_modules'
+ # must be the extension name (a string) and match
+ # a python dotted-separated name
+ exts = [('foo-bar', '')]
+ with pytest.raises(DistutilsSetupError):
+ cmd.check_extensions_list(exts)
+
+ # second element of each tuple in 'ext_modules'
+ # must be a dictionary (build info)
+ exts = [('foo.bar', '')]
+ with pytest.raises(DistutilsSetupError):
+ cmd.check_extensions_list(exts)
+
+ # ok this one should pass
+ exts = [('foo.bar', {'sources': [''], 'libraries': 'foo', 'some': 'bar'})]
+ cmd.check_extensions_list(exts)
+ ext = exts[0]
+ assert isinstance(ext, Extension)
+
+ # check_extensions_list adds in ext the values passed
+ # when they are in ('include_dirs', 'library_dirs', 'libraries'
+ # 'extra_objects', 'extra_compile_args', 'extra_link_args')
+ assert ext.libraries == 'foo'
+ assert not hasattr(ext, 'some')
+
+ # 'macros' element of build info dict must be 1- or 2-tuple
+ exts = [
+ (
+ 'foo.bar',
+ {
+ 'sources': [''],
+ 'libraries': 'foo',
+ 'some': 'bar',
+ 'macros': [('1', '2', '3'), 'foo'],
+ },
+ )
+ ]
+ with pytest.raises(DistutilsSetupError):
+ cmd.check_extensions_list(exts)
+
+ exts[0][1]['macros'] = [('1', '2'), ('3',)]
+ cmd.check_extensions_list(exts)
+ assert exts[0].undef_macros == ['3']
+ assert exts[0].define_macros == [('1', '2')]
+
+ def test_get_source_files(self):
+ modules = [Extension('foo', ['xxx'], optional=False)]
+ dist = Distribution({'name': 'xx', 'ext_modules': modules})
+ cmd = self.build_ext(dist)
+ cmd.ensure_finalized()
+ assert cmd.get_source_files() == ['xxx']
+
+ def test_unicode_module_names(self):
+ modules = [
+ Extension('foo', ['aaa'], optional=False),
+ Extension('föö', ['uuu'], optional=False),
+ ]
+ dist = Distribution({'name': 'xx', 'ext_modules': modules})
+ cmd = self.build_ext(dist)
+ cmd.ensure_finalized()
+ assert re.search(r'foo(_d)?\..*', cmd.get_ext_filename(modules[0].name))
+ assert re.search(r'föö(_d)?\..*', cmd.get_ext_filename(modules[1].name))
+ assert cmd.get_export_symbols(modules[0]) == ['PyInit_foo']
+ assert cmd.get_export_symbols(modules[1]) == ['PyInitU_f_1gaa']
+
+ def test_export_symbols__init__(self):
+ # https://github.com/python/cpython/issues/80074
+ # https://github.com/pypa/setuptools/issues/4826
+ modules = [
+ Extension('foo.__init__', ['aaa']),
+ Extension('föö.__init__', ['uuu']),
+ ]
+ dist = Distribution({'name': 'xx', 'ext_modules': modules})
+ cmd = self.build_ext(dist)
+ cmd.ensure_finalized()
+ assert cmd.get_export_symbols(modules[0]) == ['PyInit_foo']
+ assert cmd.get_export_symbols(modules[1]) == ['PyInitU_f_1gaa']
+
+ def test_compiler_option(self):
+ # cmd.compiler is an option and
+ # should not be overridden by a compiler instance
+ # when the command is run
+ dist = Distribution()
+ cmd = self.build_ext(dist)
+ cmd.compiler = 'unix'
+ cmd.ensure_finalized()
+ cmd.run()
+ assert cmd.compiler == 'unix'
+
+ def test_get_outputs(self):
+ missing_compiler_executable()
+ tmp_dir = self.mkdtemp()
+ c_file = os.path.join(tmp_dir, 'foo.c')
+ self.write_file(c_file, 'void PyInit_foo(void) {}\n')
+ ext = Extension('foo', [c_file], optional=False)
+ dist = Distribution({'name': 'xx', 'ext_modules': [ext]})
+ cmd = self.build_ext(dist)
+ fixup_build_ext(cmd)
+ cmd.ensure_finalized()
+ assert len(cmd.get_outputs()) == 1
+
+ cmd.build_lib = os.path.join(self.tmp_dir, 'build')
+ cmd.build_temp = os.path.join(self.tmp_dir, 'tempt')
+
+ # issue #5977 : distutils build_ext.get_outputs
+ # returns wrong result with --inplace
+ other_tmp_dir = os.path.realpath(self.mkdtemp())
+ old_wd = os.getcwd()
+ os.chdir(other_tmp_dir)
+ try:
+ cmd.inplace = True
+ cmd.run()
+ so_file = cmd.get_outputs()[0]
+ finally:
+ os.chdir(old_wd)
+ assert os.path.exists(so_file)
+ ext_suffix = sysconfig.get_config_var('EXT_SUFFIX')
+ assert so_file.endswith(ext_suffix)
+ so_dir = os.path.dirname(so_file)
+ assert so_dir == other_tmp_dir
+
+ cmd.inplace = False
+ cmd.compiler = None
+ cmd.run()
+ so_file = cmd.get_outputs()[0]
+ assert os.path.exists(so_file)
+ assert so_file.endswith(ext_suffix)
+ so_dir = os.path.dirname(so_file)
+ assert so_dir == cmd.build_lib
+
+ # inplace = False, cmd.package = 'bar'
+ build_py = cmd.get_finalized_command('build_py')
+ build_py.package_dir = {'': 'bar'}
+ path = cmd.get_ext_fullpath('foo')
+ # checking that the last directory is the build_dir
+ path = os.path.split(path)[0]
+ assert path == cmd.build_lib
+
+ # inplace = True, cmd.package = 'bar'
+ cmd.inplace = True
+ other_tmp_dir = os.path.realpath(self.mkdtemp())
+ old_wd = os.getcwd()
+ os.chdir(other_tmp_dir)
+ try:
+ path = cmd.get_ext_fullpath('foo')
+ finally:
+ os.chdir(old_wd)
+ # checking that the last directory is bar
+ path = os.path.split(path)[0]
+ lastdir = os.path.split(path)[-1]
+ assert lastdir == 'bar'
+
+ def test_ext_fullpath(self):
+ ext = sysconfig.get_config_var('EXT_SUFFIX')
+ # building lxml.etree inplace
+ # etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c')
+ # etree_ext = Extension('lxml.etree', [etree_c])
+ # dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]})
+ dist = Distribution()
+ cmd = self.build_ext(dist)
+ cmd.inplace = True
+ cmd.distribution.package_dir = {'': 'src'}
+ cmd.distribution.packages = ['lxml', 'lxml.html']
+ curdir = os.getcwd()
+ wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
+ path = cmd.get_ext_fullpath('lxml.etree')
+ assert wanted == path
+
+ # building lxml.etree not inplace
+ cmd.inplace = False
+ cmd.build_lib = os.path.join(curdir, 'tmpdir')
+ wanted = os.path.join(curdir, 'tmpdir', 'lxml', 'etree' + ext)
+ path = cmd.get_ext_fullpath('lxml.etree')
+ assert wanted == path
+
+ # building twisted.runner.portmap not inplace
+ build_py = cmd.get_finalized_command('build_py')
+ build_py.package_dir = {}
+ cmd.distribution.packages = ['twisted', 'twisted.runner.portmap']
+ path = cmd.get_ext_fullpath('twisted.runner.portmap')
+ wanted = os.path.join(curdir, 'tmpdir', 'twisted', 'runner', 'portmap' + ext)
+ assert wanted == path
+
+ # building twisted.runner.portmap inplace
+ cmd.inplace = True
+ path = cmd.get_ext_fullpath('twisted.runner.portmap')
+ wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + ext)
+ assert wanted == path
+
+ @pytest.mark.skipif('platform.system() != "Darwin"')
+ @pytest.mark.usefixtures('save_env')
+ def test_deployment_target_default(self):
+ # Issue 9516: Test that, in the absence of the environment variable,
+ # an extension module is compiled with the same deployment target as
+ # the interpreter.
+ self._try_compile_deployment_target('==', None)
+
+ @pytest.mark.skipif('platform.system() != "Darwin"')
+ @pytest.mark.usefixtures('save_env')
+ def test_deployment_target_too_low(self):
+ # Issue 9516: Test that an extension module is not allowed to be
+ # compiled with a deployment target less than that of the interpreter.
+ with pytest.raises(DistutilsPlatformError):
+ self._try_compile_deployment_target('>', '10.1')
+
+ @pytest.mark.skipif('platform.system() != "Darwin"')
+ @pytest.mark.usefixtures('save_env')
+ def test_deployment_target_higher_ok(self): # pragma: no cover
+ # Issue 9516: Test that an extension module can be compiled with a
+ # deployment target higher than that of the interpreter: the ext
+ # module may depend on some newer OS feature.
+ deptarget = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
+ if deptarget:
+ # increment the minor version number (i.e. 10.6 -> 10.7)
+ deptarget = [int(x) for x in deptarget.split('.')]
+ deptarget[-1] += 1
+ deptarget = '.'.join(str(i) for i in deptarget)
+ self._try_compile_deployment_target('<', deptarget)
+
+ def _try_compile_deployment_target(self, operator, target): # pragma: no cover
+ if target is None:
+ if os.environ.get('MACOSX_DEPLOYMENT_TARGET'):
+ del os.environ['MACOSX_DEPLOYMENT_TARGET']
+ else:
+ os.environ['MACOSX_DEPLOYMENT_TARGET'] = target
+
+ jaraco.path.build(
+ {
+ 'deptargetmodule.c': textwrap.dedent(f"""\
+ #include
+
+ int dummy;
+
+ #if TARGET {operator} MAC_OS_X_VERSION_MIN_REQUIRED
+ #else
+ #error "Unexpected target"
+ #endif
+
+ """),
+ },
+ self.tmp_path,
+ )
+
+ # get the deployment target that the interpreter was built with
+ target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
+ target = tuple(map(int, target.split('.')[0:2]))
+ # format the target value as defined in the Apple
+ # Availability Macros. We can't use the macro names since
+ # at least one value we test with will not exist yet.
+ if target[:2] < (10, 10):
+ # for 10.1 through 10.9.x -> "10n0"
+ tmpl = '{:02}{:01}0'
+ else:
+ # for 10.10 and beyond -> "10nn00"
+ if len(target) >= 2:
+ tmpl = '{:02}{:02}00'
+ else:
+ # 11 and later can have no minor version (11 instead of 11.0)
+ tmpl = '{:02}0000'
+ target = tmpl.format(*target)
+ deptarget_ext = Extension(
+ 'deptarget',
+ [self.tmp_path / 'deptargetmodule.c'],
+ extra_compile_args=[f'-DTARGET={target}'],
+ )
+ dist = Distribution({'name': 'deptarget', 'ext_modules': [deptarget_ext]})
+ dist.package_dir = self.tmp_dir
+ cmd = self.build_ext(dist)
+ cmd.build_lib = self.tmp_dir
+ cmd.build_temp = self.tmp_dir
+
+ try:
+ old_stdout = sys.stdout
+ if not support.verbose:
+ # silence compiler output
+ sys.stdout = StringIO()
+ try:
+ cmd.ensure_finalized()
+ cmd.run()
+ finally:
+ sys.stdout = old_stdout
+
+ except CompileError:
+ self.fail("Wrong deployment target during compilation")
+
+
+class TestParallelBuildExt(TestBuildExt):
+ def build_ext(self, *args, **kwargs):
+ build_ext = super().build_ext(*args, **kwargs)
+ build_ext.parallel = True
+ return build_ext
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_py.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_py.py
new file mode 100644
index 0000000..b316ed4
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_py.py
@@ -0,0 +1,196 @@
+"""Tests for distutils.command.build_py."""
+
+import os
+import sys
+from distutils.command.build_py import build_py
+from distutils.core import Distribution
+from distutils.errors import DistutilsFileError
+from distutils.tests import support
+
+import jaraco.path
+import pytest
+
+
+@support.combine_markers
+class TestBuildPy(support.TempdirManager):
+ def test_package_data(self):
+ sources = self.mkdtemp()
+ jaraco.path.build(
+ {
+ '__init__.py': "# Pretend this is a package.",
+ 'README.txt': 'Info about this package',
+ },
+ sources,
+ )
+
+ destination = self.mkdtemp()
+
+ dist = Distribution({"packages": ["pkg"], "package_dir": {"pkg": sources}})
+ # script_name need not exist, it just need to be initialized
+ dist.script_name = os.path.join(sources, "setup.py")
+ dist.command_obj["build"] = support.DummyCommand(
+ force=False, build_lib=destination
+ )
+ dist.packages = ["pkg"]
+ dist.package_data = {"pkg": ["README.txt"]}
+ dist.package_dir = {"pkg": sources}
+
+ cmd = build_py(dist)
+ cmd.compile = True
+ cmd.ensure_finalized()
+ assert cmd.package_data == dist.package_data
+
+ cmd.run()
+
+ # This makes sure the list of outputs includes byte-compiled
+ # files for Python modules but not for package data files
+ # (there shouldn't *be* byte-code files for those!).
+ assert len(cmd.get_outputs()) == 3
+ pkgdest = os.path.join(destination, "pkg")
+ files = os.listdir(pkgdest)
+ pycache_dir = os.path.join(pkgdest, "__pycache__")
+ assert "__init__.py" in files
+ assert "README.txt" in files
+ if sys.dont_write_bytecode:
+ assert not os.path.exists(pycache_dir)
+ else:
+ pyc_files = os.listdir(pycache_dir)
+ assert f"__init__.{sys.implementation.cache_tag}.pyc" in pyc_files
+
+ def test_empty_package_dir(self):
+ # See bugs #1668596/#1720897
+ sources = self.mkdtemp()
+ jaraco.path.build({'__init__.py': '', 'doc': {'testfile': ''}}, sources)
+
+ os.chdir(sources)
+ dist = Distribution({
+ "packages": ["pkg"],
+ "package_dir": {"pkg": ""},
+ "package_data": {"pkg": ["doc/*"]},
+ })
+ # script_name need not exist, it just need to be initialized
+ dist.script_name = os.path.join(sources, "setup.py")
+ dist.script_args = ["build"]
+ dist.parse_command_line()
+
+ try:
+ dist.run_commands()
+ except DistutilsFileError:
+ self.fail("failed package_data test when package_dir is ''")
+
+ @pytest.mark.skipif('sys.dont_write_bytecode')
+ def test_byte_compile(self):
+ project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
+ os.chdir(project_dir)
+ self.write_file('boiledeggs.py', 'import antigravity')
+ cmd = build_py(dist)
+ cmd.compile = True
+ cmd.build_lib = 'here'
+ cmd.finalize_options()
+ cmd.run()
+
+ found = os.listdir(cmd.build_lib)
+ assert sorted(found) == ['__pycache__', 'boiledeggs.py']
+ found = os.listdir(os.path.join(cmd.build_lib, '__pycache__'))
+ assert found == [f'boiledeggs.{sys.implementation.cache_tag}.pyc']
+
+ @pytest.mark.skipif('sys.dont_write_bytecode')
+ def test_byte_compile_optimized(self):
+ project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
+ os.chdir(project_dir)
+ self.write_file('boiledeggs.py', 'import antigravity')
+ cmd = build_py(dist)
+ cmd.compile = False
+ cmd.optimize = 1
+ cmd.build_lib = 'here'
+ cmd.finalize_options()
+ cmd.run()
+
+ found = os.listdir(cmd.build_lib)
+ assert sorted(found) == ['__pycache__', 'boiledeggs.py']
+ found = os.listdir(os.path.join(cmd.build_lib, '__pycache__'))
+ expect = f'boiledeggs.{sys.implementation.cache_tag}.opt-1.pyc'
+ assert sorted(found) == [expect]
+
+ def test_dir_in_package_data(self):
+ """
+ A directory in package_data should not be added to the filelist.
+ """
+ # See bug 19286
+ sources = self.mkdtemp()
+ jaraco.path.build(
+ {
+ 'pkg': {
+ '__init__.py': '',
+ 'doc': {
+ 'testfile': '',
+ # create a directory that could be incorrectly detected as a file
+ 'otherdir': {},
+ },
+ }
+ },
+ sources,
+ )
+
+ os.chdir(sources)
+ dist = Distribution({"packages": ["pkg"], "package_data": {"pkg": ["doc/*"]}})
+ # script_name need not exist, it just need to be initialized
+ dist.script_name = os.path.join(sources, "setup.py")
+ dist.script_args = ["build"]
+ dist.parse_command_line()
+
+ try:
+ dist.run_commands()
+ except DistutilsFileError:
+ self.fail("failed package_data when data dir includes a dir")
+
+ def test_dont_write_bytecode(self, caplog):
+ # makes sure byte_compile is not used
+ dist = self.create_dist()[1]
+ cmd = build_py(dist)
+ cmd.compile = True
+ cmd.optimize = 1
+
+ old_dont_write_bytecode = sys.dont_write_bytecode
+ sys.dont_write_bytecode = True
+ try:
+ cmd.byte_compile([])
+ finally:
+ sys.dont_write_bytecode = old_dont_write_bytecode
+
+ assert 'byte-compiling is disabled' in caplog.records[0].message
+
+ def test_namespace_package_does_not_warn(self, caplog):
+ """
+ Originally distutils implementation did not account for PEP 420
+ and included warns for package directories that did not contain
+ ``__init__.py`` files.
+ After the acceptance of PEP 420, these warnings don't make more sense
+ so we want to ensure there are not displayed to not confuse the users.
+ """
+ # Create a fake project structure with a package namespace:
+ tmp = self.mkdtemp()
+ jaraco.path.build({'ns': {'pkg': {'module.py': ''}}}, tmp)
+ os.chdir(tmp)
+
+ # Configure the package:
+ attrs = {
+ "name": "ns.pkg",
+ "packages": ["ns", "ns.pkg"],
+ "script_name": "setup.py",
+ }
+ dist = Distribution(attrs)
+
+ # Run code paths that would trigger the trap:
+ cmd = dist.get_command_obj("build_py")
+ cmd.finalize_options()
+ modules = cmd.find_all_modules()
+ assert len(modules) == 1
+ module_path = modules[0][-1]
+ assert module_path.replace(os.sep, "/") == "ns/pkg/module.py"
+
+ cmd.run()
+
+ assert not any(
+ "package init file" in msg and "not found" in msg for msg in caplog.messages
+ )
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_scripts.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_scripts.py
new file mode 100644
index 0000000..3582f69
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_build_scripts.py
@@ -0,0 +1,96 @@
+"""Tests for distutils.command.build_scripts."""
+
+import os
+import textwrap
+from distutils import sysconfig
+from distutils.command.build_scripts import build_scripts
+from distutils.core import Distribution
+from distutils.tests import support
+
+import jaraco.path
+
+
+class TestBuildScripts(support.TempdirManager):
+ def test_default_settings(self):
+ cmd = self.get_build_scripts_cmd("/foo/bar", [])
+ assert not cmd.force
+ assert cmd.build_dir is None
+
+ cmd.finalize_options()
+
+ assert cmd.force
+ assert cmd.build_dir == "/foo/bar"
+
+ def test_build(self):
+ source = self.mkdtemp()
+ target = self.mkdtemp()
+ expected = self.write_sample_scripts(source)
+
+ cmd = self.get_build_scripts_cmd(
+ target, [os.path.join(source, fn) for fn in expected]
+ )
+ cmd.finalize_options()
+ cmd.run()
+
+ built = os.listdir(target)
+ for name in expected:
+ assert name in built
+
+ def get_build_scripts_cmd(self, target, scripts):
+ import sys
+
+ dist = Distribution()
+ dist.scripts = scripts
+ dist.command_obj["build"] = support.DummyCommand(
+ build_scripts=target, force=True, executable=sys.executable
+ )
+ return build_scripts(dist)
+
+ @staticmethod
+ def write_sample_scripts(dir):
+ spec = {
+ 'script1.py': textwrap.dedent("""
+ #! /usr/bin/env python2.3
+ # bogus script w/ Python sh-bang
+ pass
+ """).lstrip(),
+ 'script2.py': textwrap.dedent("""
+ #!/usr/bin/python
+ # bogus script w/ Python sh-bang
+ pass
+ """).lstrip(),
+ 'shell.sh': textwrap.dedent("""
+ #!/bin/sh
+ # bogus shell script w/ sh-bang
+ exit 0
+ """).lstrip(),
+ }
+ jaraco.path.build(spec, dir)
+ return list(spec)
+
+ def test_version_int(self):
+ source = self.mkdtemp()
+ target = self.mkdtemp()
+ expected = self.write_sample_scripts(source)
+
+ cmd = self.get_build_scripts_cmd(
+ target, [os.path.join(source, fn) for fn in expected]
+ )
+ cmd.finalize_options()
+
+ # https://bugs.python.org/issue4524
+ #
+ # On linux-g++-32 with command line `./configure --enable-ipv6
+ # --with-suffix=3`, python is compiled okay but the build scripts
+ # failed when writing the name of the executable
+ old = sysconfig.get_config_vars().get('VERSION')
+ sysconfig._config_vars['VERSION'] = 4
+ try:
+ cmd.run()
+ finally:
+ if old is not None:
+ sysconfig._config_vars['VERSION'] = old
+
+ built = os.listdir(target)
+ for name in expected:
+ assert name in built
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_check.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_check.py
new file mode 100644
index 0000000..b672b1f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_check.py
@@ -0,0 +1,194 @@
+"""Tests for distutils.command.check."""
+
+import os
+import textwrap
+from distutils.command.check import check
+from distutils.errors import DistutilsSetupError
+from distutils.tests import support
+
+import pytest
+
+try:
+ import pygments
+except ImportError:
+ pygments = None
+
+
+HERE = os.path.dirname(__file__)
+
+
+@support.combine_markers
+class TestCheck(support.TempdirManager):
+ def _run(self, metadata=None, cwd=None, **options):
+ if metadata is None:
+ metadata = {}
+ if cwd is not None:
+ old_dir = os.getcwd()
+ os.chdir(cwd)
+ pkg_info, dist = self.create_dist(**metadata)
+ cmd = check(dist)
+ cmd.initialize_options()
+ for name, value in options.items():
+ setattr(cmd, name, value)
+ cmd.ensure_finalized()
+ cmd.run()
+ if cwd is not None:
+ os.chdir(old_dir)
+ return cmd
+
+ def test_check_metadata(self):
+ # let's run the command with no metadata at all
+ # by default, check is checking the metadata
+ # should have some warnings
+ cmd = self._run()
+ assert cmd._warnings == 1
+
+ # now let's add the required fields
+ # and run it again, to make sure we don't get
+ # any warning anymore
+ metadata = {
+ 'url': 'xxx',
+ 'author': 'xxx',
+ 'author_email': 'xxx',
+ 'name': 'xxx',
+ 'version': 'xxx',
+ }
+ cmd = self._run(metadata)
+ assert cmd._warnings == 0
+
+ # now with the strict mode, we should
+ # get an error if there are missing metadata
+ with pytest.raises(DistutilsSetupError):
+ self._run({}, **{'strict': 1})
+
+ # and of course, no error when all metadata are present
+ cmd = self._run(metadata, strict=True)
+ assert cmd._warnings == 0
+
+ # now a test with non-ASCII characters
+ metadata = {
+ 'url': 'xxx',
+ 'author': '\u00c9ric',
+ 'author_email': 'xxx',
+ 'name': 'xxx',
+ 'version': 'xxx',
+ 'description': 'Something about esszet \u00df',
+ 'long_description': 'More things about esszet \u00df',
+ }
+ cmd = self._run(metadata)
+ assert cmd._warnings == 0
+
+ def test_check_author_maintainer(self):
+ for kind in ("author", "maintainer"):
+ # ensure no warning when author_email or maintainer_email is given
+ # (the spec allows these fields to take the form "Name ")
+ metadata = {
+ 'url': 'xxx',
+ kind + '_email': 'Name ',
+ 'name': 'xxx',
+ 'version': 'xxx',
+ }
+ cmd = self._run(metadata)
+ assert cmd._warnings == 0
+
+ # the check should not warn if only email is given
+ metadata[kind + '_email'] = 'name@email.com'
+ cmd = self._run(metadata)
+ assert cmd._warnings == 0
+
+ # the check should not warn if only the name is given
+ metadata[kind] = "Name"
+ del metadata[kind + '_email']
+ cmd = self._run(metadata)
+ assert cmd._warnings == 0
+
+ def test_check_document(self):
+ pytest.importorskip('docutils')
+ pkg_info, dist = self.create_dist()
+ cmd = check(dist)
+
+ # let's see if it detects broken rest
+ broken_rest = 'title\n===\n\ntest'
+ msgs = cmd._check_rst_data(broken_rest)
+ assert len(msgs) == 1
+
+ # and non-broken rest
+ rest = 'title\n=====\n\ntest'
+ msgs = cmd._check_rst_data(rest)
+ assert len(msgs) == 0
+
+ def test_check_restructuredtext(self):
+ pytest.importorskip('docutils')
+ # let's see if it detects broken rest in long_description
+ broken_rest = 'title\n===\n\ntest'
+ pkg_info, dist = self.create_dist(long_description=broken_rest)
+ cmd = check(dist)
+ cmd.check_restructuredtext()
+ assert cmd._warnings == 1
+
+ # let's see if we have an error with strict=True
+ metadata = {
+ 'url': 'xxx',
+ 'author': 'xxx',
+ 'author_email': 'xxx',
+ 'name': 'xxx',
+ 'version': 'xxx',
+ 'long_description': broken_rest,
+ }
+ with pytest.raises(DistutilsSetupError):
+ self._run(metadata, **{'strict': 1, 'restructuredtext': 1})
+
+ # and non-broken rest, including a non-ASCII character to test #12114
+ metadata['long_description'] = 'title\n=====\n\ntest \u00df'
+ cmd = self._run(metadata, strict=True, restructuredtext=True)
+ assert cmd._warnings == 0
+
+ # check that includes work to test #31292
+ metadata['long_description'] = 'title\n=====\n\n.. include:: includetest.rst'
+ cmd = self._run(metadata, cwd=HERE, strict=True, restructuredtext=True)
+ assert cmd._warnings == 0
+
+ def test_check_restructuredtext_with_syntax_highlight(self):
+ pytest.importorskip('docutils')
+ # Don't fail if there is a `code` or `code-block` directive
+
+ example_rst_docs = [
+ textwrap.dedent(
+ """\
+ Here's some code:
+
+ .. code:: python
+
+ def foo():
+ pass
+ """
+ ),
+ textwrap.dedent(
+ """\
+ Here's some code:
+
+ .. code-block:: python
+
+ def foo():
+ pass
+ """
+ ),
+ ]
+
+ for rest_with_code in example_rst_docs:
+ pkg_info, dist = self.create_dist(long_description=rest_with_code)
+ cmd = check(dist)
+ cmd.check_restructuredtext()
+ msgs = cmd._check_rst_data(rest_with_code)
+ if pygments is not None:
+ assert len(msgs) == 0
+ else:
+ assert len(msgs) == 1
+ assert (
+ str(msgs[0][1])
+ == 'Cannot analyze code. Pygments package not found.'
+ )
+
+ def test_check_all(self):
+ with pytest.raises(DistutilsSetupError):
+ self._run({}, **{'strict': 1, 'restructuredtext': 1})
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_clean.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_clean.py
new file mode 100644
index 0000000..cc78f30
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_clean.py
@@ -0,0 +1,45 @@
+"""Tests for distutils.command.clean."""
+
+import os
+from distutils.command.clean import clean
+from distutils.tests import support
+
+
+class TestClean(support.TempdirManager):
+ def test_simple_run(self):
+ pkg_dir, dist = self.create_dist()
+ cmd = clean(dist)
+
+ # let's add some elements clean should remove
+ dirs = [
+ (d, os.path.join(pkg_dir, d))
+ for d in (
+ 'build_temp',
+ 'build_lib',
+ 'bdist_base',
+ 'build_scripts',
+ 'build_base',
+ )
+ ]
+
+ for name, path in dirs:
+ os.mkdir(path)
+ setattr(cmd, name, path)
+ if name == 'build_base':
+ continue
+ for f in ('one', 'two', 'three'):
+ self.write_file(os.path.join(path, f))
+
+ # let's run the command
+ cmd.all = 1
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # make sure the files where removed
+ for _name, path in dirs:
+ assert not os.path.exists(path), f'{path} was not removed'
+
+ # let's run the command again (should spit warnings but succeed)
+ cmd.all = 1
+ cmd.ensure_finalized()
+ cmd.run()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_cmd.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_cmd.py
new file mode 100644
index 0000000..76e8f59
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_cmd.py
@@ -0,0 +1,107 @@
+"""Tests for distutils.cmd."""
+
+import os
+from distutils import debug
+from distutils.cmd import Command
+from distutils.dist import Distribution
+from distutils.errors import DistutilsOptionError
+
+import pytest
+
+
+class MyCmd(Command):
+ def initialize_options(self):
+ pass
+
+
+@pytest.fixture
+def cmd(request):
+ return MyCmd(Distribution())
+
+
+class TestCommand:
+ def test_ensure_string_list(self, cmd):
+ cmd.not_string_list = ['one', 2, 'three']
+ cmd.yes_string_list = ['one', 'two', 'three']
+ cmd.not_string_list2 = object()
+ cmd.yes_string_list2 = 'ok'
+ cmd.ensure_string_list('yes_string_list')
+ cmd.ensure_string_list('yes_string_list2')
+
+ with pytest.raises(DistutilsOptionError):
+ cmd.ensure_string_list('not_string_list')
+
+ with pytest.raises(DistutilsOptionError):
+ cmd.ensure_string_list('not_string_list2')
+
+ cmd.option1 = 'ok,dok'
+ cmd.ensure_string_list('option1')
+ assert cmd.option1 == ['ok', 'dok']
+
+ cmd.option2 = ['xxx', 'www']
+ cmd.ensure_string_list('option2')
+
+ cmd.option3 = ['ok', 2]
+ with pytest.raises(DistutilsOptionError):
+ cmd.ensure_string_list('option3')
+
+ def test_make_file(self, cmd):
+ # making sure it raises when infiles is not a string or a list/tuple
+ with pytest.raises(TypeError):
+ cmd.make_file(infiles=True, outfile='', func='func', args=())
+
+ # making sure execute gets called properly
+ def _execute(func, args, exec_msg, level):
+ assert exec_msg == 'generating out from in'
+
+ cmd.force = True
+ cmd.execute = _execute
+ cmd.make_file(infiles='in', outfile='out', func='func', args=())
+
+ def test_dump_options(self, cmd):
+ msgs = []
+
+ def _announce(msg, level):
+ msgs.append(msg)
+
+ cmd.announce = _announce
+ cmd.option1 = 1
+ cmd.option2 = 1
+ cmd.user_options = [('option1', '', ''), ('option2', '', '')]
+ cmd.dump_options()
+
+ wanted = ["command options for 'MyCmd':", ' option1 = 1', ' option2 = 1']
+ assert msgs == wanted
+
+ def test_ensure_string(self, cmd):
+ cmd.option1 = 'ok'
+ cmd.ensure_string('option1')
+
+ cmd.option2 = None
+ cmd.ensure_string('option2', 'xxx')
+ assert hasattr(cmd, 'option2')
+
+ cmd.option3 = 1
+ with pytest.raises(DistutilsOptionError):
+ cmd.ensure_string('option3')
+
+ def test_ensure_filename(self, cmd):
+ cmd.option1 = __file__
+ cmd.ensure_filename('option1')
+ cmd.option2 = 'xxx'
+ with pytest.raises(DistutilsOptionError):
+ cmd.ensure_filename('option2')
+
+ def test_ensure_dirname(self, cmd):
+ cmd.option1 = os.path.dirname(__file__) or os.curdir
+ cmd.ensure_dirname('option1')
+ cmd.option2 = 'xxx'
+ with pytest.raises(DistutilsOptionError):
+ cmd.ensure_dirname('option2')
+
+ def test_debug_print(self, cmd, capsys, monkeypatch):
+ cmd.debug_print('xxx')
+ assert capsys.readouterr().out == ''
+ monkeypatch.setattr(debug, 'DEBUG', True)
+ cmd.debug_print('xxx')
+ assert capsys.readouterr().out == 'xxx\n'
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_config_cmd.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_config_cmd.py
new file mode 100644
index 0000000..ebee2ef
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_config_cmd.py
@@ -0,0 +1,87 @@
+"""Tests for distutils.command.config."""
+
+import os
+import sys
+from distutils._log import log
+from distutils.command.config import config, dump_file
+from distutils.tests import missing_compiler_executable, support
+
+import more_itertools
+import path
+import pytest
+
+
+@pytest.fixture(autouse=True)
+def info_log(request, monkeypatch):
+ self = request.instance
+ self._logs = []
+ monkeypatch.setattr(log, 'info', self._info)
+
+
+@support.combine_markers
+class TestConfig(support.TempdirManager):
+ def _info(self, msg, *args):
+ for line in msg.splitlines():
+ self._logs.append(line)
+
+ def test_dump_file(self):
+ this_file = path.Path(__file__).with_suffix('.py')
+ with this_file.open(encoding='utf-8') as f:
+ numlines = more_itertools.ilen(f)
+
+ dump_file(this_file, 'I am the header')
+ assert len(self._logs) == numlines + 1
+
+ @pytest.mark.skipif('platform.system() == "Windows"')
+ def test_search_cpp(self):
+ cmd = missing_compiler_executable(['preprocessor'])
+ if cmd is not None:
+ self.skipTest(f'The {cmd!r} command is not found')
+ pkg_dir, dist = self.create_dist()
+ cmd = config(dist)
+ cmd._check_compiler()
+ compiler = cmd.compiler
+ if sys.platform[:3] == "aix" and "xlc" in compiler.preprocessor[0].lower():
+ self.skipTest(
+ 'xlc: The -E option overrides the -P, -o, and -qsyntaxonly options'
+ )
+
+ # simple pattern searches
+ match = cmd.search_cpp(pattern='xxx', body='/* xxx */')
+ assert match == 0
+
+ match = cmd.search_cpp(pattern='_configtest', body='/* xxx */')
+ assert match == 1
+
+ def test_finalize_options(self):
+ # finalize_options does a bit of transformation
+ # on options
+ pkg_dir, dist = self.create_dist()
+ cmd = config(dist)
+ cmd.include_dirs = f'one{os.pathsep}two'
+ cmd.libraries = 'one'
+ cmd.library_dirs = f'three{os.pathsep}four'
+ cmd.ensure_finalized()
+
+ assert cmd.include_dirs == ['one', 'two']
+ assert cmd.libraries == ['one']
+ assert cmd.library_dirs == ['three', 'four']
+
+ def test_clean(self):
+ # _clean removes files
+ tmp_dir = self.mkdtemp()
+ f1 = os.path.join(tmp_dir, 'one')
+ f2 = os.path.join(tmp_dir, 'two')
+
+ self.write_file(f1, 'xxx')
+ self.write_file(f2, 'xxx')
+
+ for f in (f1, f2):
+ assert os.path.exists(f)
+
+ pkg_dir, dist = self.create_dist()
+ cmd = config(dist)
+ cmd._clean(f1, f2)
+
+ for f in (f1, f2):
+ assert not os.path.exists(f)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_core.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_core.py
new file mode 100644
index 0000000..bad3fb7
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_core.py
@@ -0,0 +1,130 @@
+"""Tests for distutils.core."""
+
+import distutils.core
+import io
+import os
+import sys
+from distutils.dist import Distribution
+
+import pytest
+
+# setup script that uses __file__
+setup_using___file__ = """\
+
+__file__
+
+from distutils.core import setup
+setup()
+"""
+
+setup_prints_cwd = """\
+
+import os
+print(os.getcwd())
+
+from distutils.core import setup
+setup()
+"""
+
+setup_does_nothing = """\
+from distutils.core import setup
+setup()
+"""
+
+
+setup_defines_subclass = """\
+from distutils.core import setup
+from distutils.command.install import install as _install
+
+class install(_install):
+ sub_commands = _install.sub_commands + ['cmd']
+
+setup(cmdclass={'install': install})
+"""
+
+setup_within_if_main = """\
+from distutils.core import setup
+
+def main():
+ return setup(name="setup_within_if_main")
+
+if __name__ == "__main__":
+ main()
+"""
+
+
+@pytest.fixture(autouse=True)
+def save_stdout(monkeypatch):
+ monkeypatch.setattr(sys, 'stdout', sys.stdout)
+
+
+@pytest.fixture
+def temp_file(tmp_path):
+ return tmp_path / 'file'
+
+
+@pytest.mark.usefixtures('save_env')
+@pytest.mark.usefixtures('save_argv')
+class TestCore:
+ def test_run_setup_provides_file(self, temp_file):
+ # Make sure the script can use __file__; if that's missing, the test
+ # setup.py script will raise NameError.
+ temp_file.write_text(setup_using___file__, encoding='utf-8')
+ distutils.core.run_setup(temp_file)
+
+ def test_run_setup_preserves_sys_argv(self, temp_file):
+ # Make sure run_setup does not clobber sys.argv
+ argv_copy = sys.argv.copy()
+ temp_file.write_text(setup_does_nothing, encoding='utf-8')
+ distutils.core.run_setup(temp_file)
+ assert sys.argv == argv_copy
+
+ def test_run_setup_defines_subclass(self, temp_file):
+ # Make sure the script can use __file__; if that's missing, the test
+ # setup.py script will raise NameError.
+ temp_file.write_text(setup_defines_subclass, encoding='utf-8')
+ dist = distutils.core.run_setup(temp_file)
+ install = dist.get_command_obj('install')
+ assert 'cmd' in install.sub_commands
+
+ def test_run_setup_uses_current_dir(self, tmp_path):
+ """
+ Test that the setup script is run with the current directory
+ as its own current directory.
+ """
+ sys.stdout = io.StringIO()
+ cwd = os.getcwd()
+
+ # Create a directory and write the setup.py file there:
+ setup_py = tmp_path / 'setup.py'
+ setup_py.write_text(setup_prints_cwd, encoding='utf-8')
+ distutils.core.run_setup(setup_py)
+
+ output = sys.stdout.getvalue()
+ if output.endswith("\n"):
+ output = output[:-1]
+ assert cwd == output
+
+ def test_run_setup_within_if_main(self, temp_file):
+ temp_file.write_text(setup_within_if_main, encoding='utf-8')
+ dist = distutils.core.run_setup(temp_file, stop_after="config")
+ assert isinstance(dist, Distribution)
+ assert dist.get_name() == "setup_within_if_main"
+
+ def test_run_commands(self, temp_file):
+ sys.argv = ['setup.py', 'build']
+ temp_file.write_text(setup_within_if_main, encoding='utf-8')
+ dist = distutils.core.run_setup(temp_file, stop_after="commandline")
+ assert 'build' not in dist.have_run
+ distutils.core.run_commands(dist)
+ assert 'build' in dist.have_run
+
+ def test_debug_mode(self, capsys, monkeypatch):
+ # this covers the code called when DEBUG is set
+ sys.argv = ['setup.py', '--name']
+ distutils.core.setup(name='bar')
+ assert capsys.readouterr().out == 'bar\n'
+ monkeypatch.setattr(distutils.core, 'DEBUG', True)
+ distutils.core.setup(name='bar')
+ wanted = "options (after parsing config files):\n"
+ assert capsys.readouterr().out.startswith(wanted)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_dir_util.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_dir_util.py
new file mode 100644
index 0000000..326cb34
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_dir_util.py
@@ -0,0 +1,139 @@
+"""Tests for distutils.dir_util."""
+
+import os
+import pathlib
+import stat
+import sys
+import unittest.mock as mock
+from distutils import dir_util, errors
+from distutils.dir_util import (
+ copy_tree,
+ create_tree,
+ ensure_relative,
+ mkpath,
+ remove_tree,
+)
+from distutils.tests import support
+
+import jaraco.path
+import path
+import pytest
+
+
+@pytest.fixture(autouse=True)
+def stuff(request, monkeypatch, distutils_managed_tempdir):
+ self = request.instance
+ tmp_dir = self.mkdtemp()
+ self.root_target = os.path.join(tmp_dir, 'deep')
+ self.target = os.path.join(self.root_target, 'here')
+ self.target2 = os.path.join(tmp_dir, 'deep2')
+
+
+class TestDirUtil(support.TempdirManager):
+ def test_mkpath_remove_tree_verbosity(self, caplog):
+ mkpath(self.target, verbose=False)
+ assert not caplog.records
+ remove_tree(self.root_target, verbose=False)
+
+ mkpath(self.target, verbose=True)
+ wanted = [f'creating {self.target}']
+ assert caplog.messages == wanted
+ caplog.clear()
+
+ remove_tree(self.root_target, verbose=True)
+ wanted = [f"removing '{self.root_target}' (and everything under it)"]
+ assert caplog.messages == wanted
+
+ @pytest.mark.skipif("platform.system() == 'Windows'")
+ def test_mkpath_with_custom_mode(self):
+ # Get and set the current umask value for testing mode bits.
+ umask = os.umask(0o002)
+ os.umask(umask)
+ mkpath(self.target, 0o700)
+ assert stat.S_IMODE(os.stat(self.target).st_mode) == 0o700 & ~umask
+ mkpath(self.target2, 0o555)
+ assert stat.S_IMODE(os.stat(self.target2).st_mode) == 0o555 & ~umask
+
+ def test_create_tree_verbosity(self, caplog):
+ create_tree(self.root_target, ['one', 'two', 'three'], verbose=False)
+ assert caplog.messages == []
+ remove_tree(self.root_target, verbose=False)
+
+ wanted = [f'creating {self.root_target}']
+ create_tree(self.root_target, ['one', 'two', 'three'], verbose=True)
+ assert caplog.messages == wanted
+
+ remove_tree(self.root_target, verbose=False)
+
+ def test_copy_tree_verbosity(self, caplog):
+ mkpath(self.target, verbose=False)
+
+ copy_tree(self.target, self.target2, verbose=False)
+ assert caplog.messages == []
+
+ remove_tree(self.root_target, verbose=False)
+
+ mkpath(self.target, verbose=False)
+ a_file = path.Path(self.target) / 'ok.txt'
+ jaraco.path.build({'ok.txt': 'some content'}, self.target)
+
+ wanted = [f'copying {a_file} -> {self.target2}']
+ copy_tree(self.target, self.target2, verbose=True)
+ assert caplog.messages == wanted
+
+ remove_tree(self.root_target, verbose=False)
+ remove_tree(self.target2, verbose=False)
+
+ def test_copy_tree_skips_nfs_temp_files(self):
+ mkpath(self.target, verbose=False)
+
+ jaraco.path.build({'ok.txt': 'some content', '.nfs123abc': ''}, self.target)
+
+ copy_tree(self.target, self.target2)
+ assert os.listdir(self.target2) == ['ok.txt']
+
+ remove_tree(self.root_target, verbose=False)
+ remove_tree(self.target2, verbose=False)
+
+ def test_ensure_relative(self):
+ if os.sep == '/':
+ assert ensure_relative('/home/foo') == 'home/foo'
+ assert ensure_relative('some/path') == 'some/path'
+ else: # \\
+ assert ensure_relative('c:\\home\\foo') == 'c:home\\foo'
+ assert ensure_relative('home\\foo') == 'home\\foo'
+
+ def test_copy_tree_exception_in_listdir(self):
+ """
+ An exception in listdir should raise a DistutilsFileError
+ """
+ with (
+ mock.patch("os.listdir", side_effect=OSError()),
+ pytest.raises(errors.DistutilsFileError),
+ ):
+ src = self.tempdirs[-1]
+ dir_util.copy_tree(src, None)
+
+ def test_mkpath_exception_uncached(self, monkeypatch, tmp_path):
+ """
+ Caching should not remember failed attempts.
+
+ pypa/distutils#304
+ """
+
+ class FailPath(pathlib.Path):
+ def mkdir(self, *args, **kwargs):
+ raise OSError("Failed to create directory")
+
+ if sys.version_info < (3, 12):
+ _flavour = pathlib.Path()._flavour
+
+ target = tmp_path / 'foodir'
+
+ with pytest.raises(errors.DistutilsFileError):
+ mkpath(FailPath(target))
+
+ assert not target.exists()
+
+ mkpath(target)
+ assert target.exists()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_dist.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_dist.py
new file mode 100644
index 0000000..2c5beeb
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_dist.py
@@ -0,0 +1,552 @@
+"""Tests for distutils.dist."""
+
+import email
+import email.generator
+import email.policy
+import functools
+import io
+import os
+import sys
+import textwrap
+import unittest.mock as mock
+import warnings
+from distutils.cmd import Command
+from distutils.dist import Distribution, fix_help_options
+from distutils.tests import support
+from typing import ClassVar
+
+import jaraco.path
+import pytest
+
+pydistutils_cfg = '.' * (os.name == 'posix') + 'pydistutils.cfg'
+
+
+class test_dist(Command):
+ """Sample distutils extension command."""
+
+ user_options: ClassVar[list[tuple[str, str, str]]] = [
+ ("sample-option=", "S", "help text"),
+ ]
+
+ def initialize_options(self):
+ self.sample_option = None
+
+
+class TestDistribution(Distribution):
+ """Distribution subclasses that avoids the default search for
+ configuration files.
+
+ The ._config_files attribute must be set before
+ .parse_config_files() is called.
+ """
+
+ def find_config_files(self):
+ return self._config_files
+
+
+@pytest.fixture
+def clear_argv():
+ del sys.argv[1:]
+
+
+@support.combine_markers
+@pytest.mark.usefixtures('save_env')
+@pytest.mark.usefixtures('save_argv')
+class TestDistributionBehavior(support.TempdirManager):
+ def create_distribution(self, configfiles=()):
+ d = TestDistribution()
+ d._config_files = configfiles
+ d.parse_config_files()
+ d.parse_command_line()
+ return d
+
+ def test_command_packages_unspecified(self, clear_argv):
+ sys.argv.append("build")
+ d = self.create_distribution()
+ assert d.get_command_packages() == ["distutils.command"]
+
+ def test_command_packages_cmdline(self, clear_argv):
+ from distutils.tests.test_dist import test_dist
+
+ sys.argv.extend([
+ "--command-packages",
+ "foo.bar,distutils.tests",
+ "test_dist",
+ "-Ssometext",
+ ])
+ d = self.create_distribution()
+ # let's actually try to load our test command:
+ assert d.get_command_packages() == [
+ "distutils.command",
+ "foo.bar",
+ "distutils.tests",
+ ]
+ cmd = d.get_command_obj("test_dist")
+ assert isinstance(cmd, test_dist)
+ assert cmd.sample_option == "sometext"
+
+ @pytest.mark.skipif(
+ 'distutils' not in Distribution.parse_config_files.__module__,
+ reason='Cannot test when virtualenv has monkey-patched Distribution',
+ )
+ def test_venv_install_options(self, tmp_path, clear_argv):
+ sys.argv.append("install")
+ file = str(tmp_path / 'file')
+
+ fakepath = '/somedir'
+
+ jaraco.path.build({
+ file: f"""
+ [install]
+ install-base = {fakepath}
+ install-platbase = {fakepath}
+ install-lib = {fakepath}
+ install-platlib = {fakepath}
+ install-purelib = {fakepath}
+ install-headers = {fakepath}
+ install-scripts = {fakepath}
+ install-data = {fakepath}
+ prefix = {fakepath}
+ exec-prefix = {fakepath}
+ home = {fakepath}
+ user = {fakepath}
+ root = {fakepath}
+ """,
+ })
+
+ # Base case: Not in a Virtual Environment
+ with mock.patch.multiple(sys, prefix='/a', base_prefix='/a'):
+ d = self.create_distribution([file])
+
+ option_tuple = (file, fakepath)
+
+ result_dict = {
+ 'install_base': option_tuple,
+ 'install_platbase': option_tuple,
+ 'install_lib': option_tuple,
+ 'install_platlib': option_tuple,
+ 'install_purelib': option_tuple,
+ 'install_headers': option_tuple,
+ 'install_scripts': option_tuple,
+ 'install_data': option_tuple,
+ 'prefix': option_tuple,
+ 'exec_prefix': option_tuple,
+ 'home': option_tuple,
+ 'user': option_tuple,
+ 'root': option_tuple,
+ }
+
+ assert sorted(d.command_options.get('install').keys()) == sorted(
+ result_dict.keys()
+ )
+
+ for key, value in d.command_options.get('install').items():
+ assert value == result_dict[key]
+
+ # Test case: In a Virtual Environment
+ with mock.patch.multiple(sys, prefix='/a', base_prefix='/b'):
+ d = self.create_distribution([file])
+
+ for key in result_dict.keys():
+ assert key not in d.command_options.get('install', {})
+
+ def test_command_packages_configfile(self, tmp_path, clear_argv):
+ sys.argv.append("build")
+ file = str(tmp_path / "file")
+ jaraco.path.build({
+ file: """
+ [global]
+ command_packages = foo.bar, splat
+ """,
+ })
+
+ d = self.create_distribution([file])
+ assert d.get_command_packages() == ["distutils.command", "foo.bar", "splat"]
+
+ # ensure command line overrides config:
+ sys.argv[1:] = ["--command-packages", "spork", "build"]
+ d = self.create_distribution([file])
+ assert d.get_command_packages() == ["distutils.command", "spork"]
+
+ # Setting --command-packages to '' should cause the default to
+ # be used even if a config file specified something else:
+ sys.argv[1:] = ["--command-packages", "", "build"]
+ d = self.create_distribution([file])
+ assert d.get_command_packages() == ["distutils.command"]
+
+ def test_empty_options(self, request):
+ # an empty options dictionary should not stay in the
+ # list of attributes
+
+ # catching warnings
+ warns = []
+
+ def _warn(msg):
+ warns.append(msg)
+
+ request.addfinalizer(
+ functools.partial(setattr, warnings, 'warn', warnings.warn)
+ )
+ warnings.warn = _warn
+ dist = Distribution(
+ attrs={
+ 'author': 'xxx',
+ 'name': 'xxx',
+ 'version': 'xxx',
+ 'url': 'xxxx',
+ 'options': {},
+ }
+ )
+
+ assert len(warns) == 0
+ assert 'options' not in dir(dist)
+
+ def test_finalize_options(self):
+ attrs = {'keywords': 'one,two', 'platforms': 'one,two'}
+
+ dist = Distribution(attrs=attrs)
+ dist.finalize_options()
+
+ # finalize_option splits platforms and keywords
+ assert dist.metadata.platforms == ['one', 'two']
+ assert dist.metadata.keywords == ['one', 'two']
+
+ attrs = {'keywords': 'foo bar', 'platforms': 'foo bar'}
+ dist = Distribution(attrs=attrs)
+ dist.finalize_options()
+ assert dist.metadata.platforms == ['foo bar']
+ assert dist.metadata.keywords == ['foo bar']
+
+ def test_get_command_packages(self):
+ dist = Distribution()
+ assert dist.command_packages is None
+ cmds = dist.get_command_packages()
+ assert cmds == ['distutils.command']
+ assert dist.command_packages == ['distutils.command']
+
+ dist.command_packages = 'one,two'
+ cmds = dist.get_command_packages()
+ assert cmds == ['distutils.command', 'one', 'two']
+
+ def test_announce(self):
+ # make sure the level is known
+ dist = Distribution()
+ with pytest.raises(TypeError):
+ dist.announce('ok', level='ok2')
+
+ def test_find_config_files_disable(self, temp_home):
+ # Ticket #1180: Allow user to disable their home config file.
+ jaraco.path.build({pydistutils_cfg: '[distutils]\n'}, temp_home)
+
+ d = Distribution()
+ all_files = d.find_config_files()
+
+ d = Distribution(attrs={'script_args': ['--no-user-cfg']})
+ files = d.find_config_files()
+
+ # make sure --no-user-cfg disables the user cfg file
+ assert len(all_files) - 1 == len(files)
+
+ def test_script_args_list_coercion(self):
+ d = Distribution(attrs={'script_args': ('build', '--no-user-cfg')})
+
+ # make sure script_args is a list even if it started as a different iterable
+ assert d.script_args == ['build', '--no-user-cfg']
+
+ @pytest.mark.skipif(
+ 'platform.system() == "Windows"',
+ reason='Windows does not honor chmod 000',
+ )
+ def test_find_config_files_permission_error(self, fake_home):
+ """
+ Finding config files should not fail when directory is inaccessible.
+ """
+ fake_home.joinpath(pydistutils_cfg).write_text('', encoding='utf-8')
+ fake_home.chmod(0o000)
+ Distribution().find_config_files()
+
+
+@pytest.mark.usefixtures('save_env')
+@pytest.mark.usefixtures('save_argv')
+class TestMetadata(support.TempdirManager):
+ def format_metadata(self, dist):
+ sio = io.StringIO()
+ dist.metadata.write_pkg_file(sio)
+ return sio.getvalue()
+
+ def test_simple_metadata(self):
+ attrs = {"name": "package", "version": "1.0"}
+ dist = Distribution(attrs)
+ meta = self.format_metadata(dist)
+ assert "Metadata-Version: 1.0" in meta
+ assert "provides:" not in meta.lower()
+ assert "requires:" not in meta.lower()
+ assert "obsoletes:" not in meta.lower()
+
+ def test_provides(self):
+ attrs = {
+ "name": "package",
+ "version": "1.0",
+ "provides": ["package", "package.sub"],
+ }
+ dist = Distribution(attrs)
+ assert dist.metadata.get_provides() == ["package", "package.sub"]
+ assert dist.get_provides() == ["package", "package.sub"]
+ meta = self.format_metadata(dist)
+ assert "Metadata-Version: 1.1" in meta
+ assert "requires:" not in meta.lower()
+ assert "obsoletes:" not in meta.lower()
+
+ def test_provides_illegal(self):
+ with pytest.raises(ValueError):
+ Distribution(
+ {"name": "package", "version": "1.0", "provides": ["my.pkg (splat)"]},
+ )
+
+ def test_requires(self):
+ attrs = {
+ "name": "package",
+ "version": "1.0",
+ "requires": ["other", "another (==1.0)"],
+ }
+ dist = Distribution(attrs)
+ assert dist.metadata.get_requires() == ["other", "another (==1.0)"]
+ assert dist.get_requires() == ["other", "another (==1.0)"]
+ meta = self.format_metadata(dist)
+ assert "Metadata-Version: 1.1" in meta
+ assert "provides:" not in meta.lower()
+ assert "Requires: other" in meta
+ assert "Requires: another (==1.0)" in meta
+ assert "obsoletes:" not in meta.lower()
+
+ def test_requires_illegal(self):
+ with pytest.raises(ValueError):
+ Distribution(
+ {"name": "package", "version": "1.0", "requires": ["my.pkg (splat)"]},
+ )
+
+ def test_requires_to_list(self):
+ attrs = {"name": "package", "requires": iter(["other"])}
+ dist = Distribution(attrs)
+ assert isinstance(dist.metadata.requires, list)
+
+ def test_obsoletes(self):
+ attrs = {
+ "name": "package",
+ "version": "1.0",
+ "obsoletes": ["other", "another (<1.0)"],
+ }
+ dist = Distribution(attrs)
+ assert dist.metadata.get_obsoletes() == ["other", "another (<1.0)"]
+ assert dist.get_obsoletes() == ["other", "another (<1.0)"]
+ meta = self.format_metadata(dist)
+ assert "Metadata-Version: 1.1" in meta
+ assert "provides:" not in meta.lower()
+ assert "requires:" not in meta.lower()
+ assert "Obsoletes: other" in meta
+ assert "Obsoletes: another (<1.0)" in meta
+
+ def test_obsoletes_illegal(self):
+ with pytest.raises(ValueError):
+ Distribution(
+ {"name": "package", "version": "1.0", "obsoletes": ["my.pkg (splat)"]},
+ )
+
+ def test_obsoletes_to_list(self):
+ attrs = {"name": "package", "obsoletes": iter(["other"])}
+ dist = Distribution(attrs)
+ assert isinstance(dist.metadata.obsoletes, list)
+
+ def test_classifier(self):
+ attrs = {
+ 'name': 'Boa',
+ 'version': '3.0',
+ 'classifiers': ['Programming Language :: Python :: 3'],
+ }
+ dist = Distribution(attrs)
+ assert dist.get_classifiers() == ['Programming Language :: Python :: 3']
+ meta = self.format_metadata(dist)
+ assert 'Metadata-Version: 1.1' in meta
+
+ def test_classifier_invalid_type(self, caplog):
+ attrs = {
+ 'name': 'Boa',
+ 'version': '3.0',
+ 'classifiers': ('Programming Language :: Python :: 3',),
+ }
+ d = Distribution(attrs)
+ # should have warning about passing a non-list
+ assert 'should be a list' in caplog.messages[0]
+ # should be converted to a list
+ assert isinstance(d.metadata.classifiers, list)
+ assert d.metadata.classifiers == list(attrs['classifiers'])
+
+ def test_keywords(self):
+ attrs = {
+ 'name': 'Monty',
+ 'version': '1.0',
+ 'keywords': ['spam', 'eggs', 'life of brian'],
+ }
+ dist = Distribution(attrs)
+ assert dist.get_keywords() == ['spam', 'eggs', 'life of brian']
+
+ def test_keywords_invalid_type(self, caplog):
+ attrs = {
+ 'name': 'Monty',
+ 'version': '1.0',
+ 'keywords': ('spam', 'eggs', 'life of brian'),
+ }
+ d = Distribution(attrs)
+ # should have warning about passing a non-list
+ assert 'should be a list' in caplog.messages[0]
+ # should be converted to a list
+ assert isinstance(d.metadata.keywords, list)
+ assert d.metadata.keywords == list(attrs['keywords'])
+
+ def test_platforms(self):
+ attrs = {
+ 'name': 'Monty',
+ 'version': '1.0',
+ 'platforms': ['GNU/Linux', 'Some Evil Platform'],
+ }
+ dist = Distribution(attrs)
+ assert dist.get_platforms() == ['GNU/Linux', 'Some Evil Platform']
+
+ def test_platforms_invalid_types(self, caplog):
+ attrs = {
+ 'name': 'Monty',
+ 'version': '1.0',
+ 'platforms': ('GNU/Linux', 'Some Evil Platform'),
+ }
+ d = Distribution(attrs)
+ # should have warning about passing a non-list
+ assert 'should be a list' in caplog.messages[0]
+ # should be converted to a list
+ assert isinstance(d.metadata.platforms, list)
+ assert d.metadata.platforms == list(attrs['platforms'])
+
+ def test_download_url(self):
+ attrs = {
+ 'name': 'Boa',
+ 'version': '3.0',
+ 'download_url': 'http://example.org/boa',
+ }
+ dist = Distribution(attrs)
+ meta = self.format_metadata(dist)
+ assert 'Metadata-Version: 1.1' in meta
+
+ def test_long_description(self):
+ long_desc = textwrap.dedent(
+ """\
+ example::
+ We start here
+ and continue here
+ and end here."""
+ )
+ attrs = {"name": "package", "version": "1.0", "long_description": long_desc}
+
+ dist = Distribution(attrs)
+ meta = self.format_metadata(dist)
+ meta = meta.replace('\n' + 8 * ' ', '\n')
+ assert long_desc in meta
+
+ def test_custom_pydistutils(self, temp_home):
+ """
+ pydistutils.cfg is found
+ """
+ jaraco.path.build({pydistutils_cfg: ''}, temp_home)
+ config_path = temp_home / pydistutils_cfg
+
+ assert str(config_path) in Distribution().find_config_files()
+
+ def test_extra_pydistutils(self, monkeypatch, tmp_path):
+ jaraco.path.build({'overrides.cfg': ''}, tmp_path)
+ filename = tmp_path / 'overrides.cfg'
+ monkeypatch.setenv('DIST_EXTRA_CONFIG', str(filename))
+ assert str(filename) in Distribution().find_config_files()
+
+ def test_fix_help_options(self):
+ help_tuples = [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
+ fancy_options = fix_help_options(help_tuples)
+ assert fancy_options[0] == ('a', 'b', 'c')
+ assert fancy_options[1] == (1, 2, 3)
+
+ def test_show_help(self, request, capsys):
+ # smoke test, just makes sure some help is displayed
+ dist = Distribution()
+ sys.argv = []
+ dist.help = True
+ dist.script_name = 'setup.py'
+ dist.parse_command_line()
+
+ output = [
+ line for line in capsys.readouterr().out.split('\n') if line.strip() != ''
+ ]
+ assert output
+
+ def test_read_metadata(self):
+ attrs = {
+ "name": "package",
+ "version": "1.0",
+ "long_description": "desc",
+ "description": "xxx",
+ "download_url": "http://example.com",
+ "keywords": ['one', 'two'],
+ "requires": ['foo'],
+ }
+
+ dist = Distribution(attrs)
+ metadata = dist.metadata
+
+ # write it then reloads it
+ PKG_INFO = io.StringIO()
+ metadata.write_pkg_file(PKG_INFO)
+ PKG_INFO.seek(0)
+ metadata.read_pkg_file(PKG_INFO)
+
+ assert metadata.name == "package"
+ assert metadata.version == "1.0"
+ assert metadata.description == "xxx"
+ assert metadata.download_url == 'http://example.com'
+ assert metadata.keywords == ['one', 'two']
+ assert metadata.platforms is None
+ assert metadata.obsoletes is None
+ assert metadata.requires == ['foo']
+
+ def test_round_trip_through_email_generator(self):
+ """
+ In pypa/setuptools#4033, it was shown that once PKG-INFO is
+ re-generated using ``email.generator.Generator``, some control
+ characters might cause problems.
+ """
+ # Given a PKG-INFO file ...
+ attrs = {
+ "name": "package",
+ "version": "1.0",
+ "long_description": "hello\x0b\nworld\n",
+ }
+ dist = Distribution(attrs)
+ metadata = dist.metadata
+
+ with io.StringIO() as buffer:
+ metadata.write_pkg_file(buffer)
+ msg = buffer.getvalue()
+
+ # ... when it is read and re-written using stdlib's email library,
+ orig = email.message_from_string(msg)
+ policy = email.policy.EmailPolicy(
+ utf8=True,
+ mangle_from_=False,
+ max_line_length=0,
+ )
+ with io.StringIO() as buffer:
+ email.generator.Generator(buffer, policy=policy).flatten(orig)
+
+ buffer.seek(0)
+ regen = email.message_from_file(buffer)
+
+ # ... then it should be the same as the original
+ # (except for the specific line break characters)
+ orig_desc = set(orig["Description"].splitlines())
+ regen_desc = set(regen["Description"].splitlines())
+ assert regen_desc == orig_desc
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_extension.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_extension.py
new file mode 100644
index 0000000..5e8e768
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_extension.py
@@ -0,0 +1,117 @@
+"""Tests for distutils.extension."""
+
+import os
+import pathlib
+import warnings
+from distutils.extension import Extension, read_setup_file
+
+import pytest
+from test.support.warnings_helper import check_warnings
+
+
+class TestExtension:
+ def test_read_setup_file(self):
+ # trying to read a Setup file
+ # (sample extracted from the PyGame project)
+ setup = os.path.join(os.path.dirname(__file__), 'Setup.sample')
+
+ exts = read_setup_file(setup)
+ names = [ext.name for ext in exts]
+ names.sort()
+
+ # here are the extensions read_setup_file should have created
+ # out of the file
+ wanted = [
+ '_arraysurfarray',
+ '_camera',
+ '_numericsndarray',
+ '_numericsurfarray',
+ 'base',
+ 'bufferproxy',
+ 'cdrom',
+ 'color',
+ 'constants',
+ 'display',
+ 'draw',
+ 'event',
+ 'fastevent',
+ 'font',
+ 'gfxdraw',
+ 'image',
+ 'imageext',
+ 'joystick',
+ 'key',
+ 'mask',
+ 'mixer',
+ 'mixer_music',
+ 'mouse',
+ 'movie',
+ 'overlay',
+ 'pixelarray',
+ 'pypm',
+ 'rect',
+ 'rwobject',
+ 'scrap',
+ 'surface',
+ 'surflock',
+ 'time',
+ 'transform',
+ ]
+
+ assert names == wanted
+
+ def test_extension_init(self):
+ # the first argument, which is the name, must be a string
+ with pytest.raises(TypeError):
+ Extension(1, [])
+ ext = Extension('name', [])
+ assert ext.name == 'name'
+
+ # the second argument, which is the list of files, must
+ # be an iterable of strings or PathLike objects, and not a string
+ with pytest.raises(TypeError):
+ Extension('name', 'file')
+ with pytest.raises(TypeError):
+ Extension('name', ['file', 1])
+ ext = Extension('name', ['file1', 'file2'])
+ assert ext.sources == ['file1', 'file2']
+ ext = Extension('name', [pathlib.Path('file1'), pathlib.Path('file2')])
+ assert ext.sources == ['file1', 'file2']
+
+ # any non-string iterable of strings or PathLike objects should work
+ ext = Extension('name', ('file1', 'file2')) # tuple
+ assert ext.sources == ['file1', 'file2']
+ ext = Extension('name', {'file1', 'file2'}) # set
+ assert sorted(ext.sources) == ['file1', 'file2']
+ ext = Extension('name', iter(['file1', 'file2'])) # iterator
+ assert ext.sources == ['file1', 'file2']
+ ext = Extension('name', [pathlib.Path('file1'), 'file2']) # mixed types
+ assert ext.sources == ['file1', 'file2']
+
+ # others arguments have defaults
+ for attr in (
+ 'include_dirs',
+ 'define_macros',
+ 'undef_macros',
+ 'library_dirs',
+ 'libraries',
+ 'runtime_library_dirs',
+ 'extra_objects',
+ 'extra_compile_args',
+ 'extra_link_args',
+ 'export_symbols',
+ 'swig_opts',
+ 'depends',
+ ):
+ assert getattr(ext, attr) == []
+
+ assert ext.language is None
+ assert ext.optional is None
+
+ # if there are unknown keyword options, warn about them
+ with check_warnings() as w:
+ warnings.simplefilter('always')
+ ext = Extension('name', ['file1', 'file2'], chic=True)
+
+ assert len(w.warnings) == 1
+ assert str(w.warnings[0].message) == "Unknown Extension options: 'chic'"
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_file_util.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_file_util.py
new file mode 100644
index 0000000..a75d4a0
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_file_util.py
@@ -0,0 +1,95 @@
+"""Tests for distutils.file_util."""
+
+import errno
+import os
+import unittest.mock as mock
+from distutils.errors import DistutilsFileError
+from distutils.file_util import copy_file, move_file
+
+import jaraco.path
+import pytest
+
+
+@pytest.fixture(autouse=True)
+def stuff(request, tmp_path):
+ self = request.instance
+ self.source = tmp_path / 'f1'
+ self.target = tmp_path / 'f2'
+ self.target_dir = tmp_path / 'd1'
+
+
+class TestFileUtil:
+ def test_move_file_verbosity(self, caplog):
+ jaraco.path.build({self.source: 'some content'})
+
+ move_file(self.source, self.target, verbose=False)
+ assert not caplog.messages
+
+ # back to original state
+ move_file(self.target, self.source, verbose=False)
+
+ move_file(self.source, self.target, verbose=True)
+ wanted = [f'moving {self.source} -> {self.target}']
+ assert caplog.messages == wanted
+
+ # back to original state
+ move_file(self.target, self.source, verbose=False)
+
+ caplog.clear()
+ # now the target is a dir
+ os.mkdir(self.target_dir)
+ move_file(self.source, self.target_dir, verbose=True)
+ wanted = [f'moving {self.source} -> {self.target_dir}']
+ assert caplog.messages == wanted
+
+ def test_move_file_exception_unpacking_rename(self):
+ # see issue 22182
+ with (
+ mock.patch("os.rename", side_effect=OSError("wrong", 1)),
+ pytest.raises(DistutilsFileError),
+ ):
+ jaraco.path.build({self.source: 'spam eggs'})
+ move_file(self.source, self.target, verbose=False)
+
+ def test_move_file_exception_unpacking_unlink(self):
+ # see issue 22182
+ with (
+ mock.patch("os.rename", side_effect=OSError(errno.EXDEV, "wrong")),
+ mock.patch("os.unlink", side_effect=OSError("wrong", 1)),
+ pytest.raises(DistutilsFileError),
+ ):
+ jaraco.path.build({self.source: 'spam eggs'})
+ move_file(self.source, self.target, verbose=False)
+
+ def test_copy_file_hard_link(self):
+ jaraco.path.build({self.source: 'some content'})
+ # Check first that copy_file() will not fall back on copying the file
+ # instead of creating the hard link.
+ try:
+ os.link(self.source, self.target)
+ except OSError as e:
+ self.skipTest(f'os.link: {e}')
+ else:
+ self.target.unlink()
+ st = os.stat(self.source)
+ copy_file(self.source, self.target, link='hard')
+ st2 = os.stat(self.source)
+ st3 = os.stat(self.target)
+ assert os.path.samestat(st, st2), (st, st2)
+ assert os.path.samestat(st2, st3), (st2, st3)
+ assert self.source.read_text(encoding='utf-8') == 'some content'
+
+ def test_copy_file_hard_link_failure(self):
+ # If hard linking fails, copy_file() falls back on copying file
+ # (some special filesystems don't support hard linking even under
+ # Unix, see issue #8876).
+ jaraco.path.build({self.source: 'some content'})
+ st = os.stat(self.source)
+ with mock.patch("os.link", side_effect=OSError(0, "linking unsupported")):
+ copy_file(self.source, self.target, link='hard')
+ st2 = os.stat(self.source)
+ st3 = os.stat(self.target)
+ assert os.path.samestat(st, st2), (st, st2)
+ assert not os.path.samestat(st2, st3), (st2, st3)
+ for fn in (self.source, self.target):
+ assert fn.read_text(encoding='utf-8') == 'some content'
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_filelist.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_filelist.py
new file mode 100644
index 0000000..130e6fb
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_filelist.py
@@ -0,0 +1,336 @@
+"""Tests for distutils.filelist."""
+
+import logging
+import os
+import re
+from distutils import debug, filelist
+from distutils.errors import DistutilsTemplateError
+from distutils.filelist import FileList, glob_to_re, translate_pattern
+
+import jaraco.path
+import pytest
+
+from .compat import py39 as os_helper
+
+MANIFEST_IN = """\
+include ok
+include xo
+exclude xo
+include foo.tmp
+include buildout.cfg
+global-include *.x
+global-include *.txt
+global-exclude *.tmp
+recursive-include f *.oo
+recursive-exclude global *.x
+graft dir
+prune dir3
+"""
+
+
+def make_local_path(s):
+ """Converts '/' in a string to os.sep"""
+ return s.replace('/', os.sep)
+
+
+class TestFileList:
+ def assertNoWarnings(self, caplog):
+ warnings = [rec for rec in caplog.records if rec.levelno == logging.WARNING]
+ assert not warnings
+ caplog.clear()
+
+ def assertWarnings(self, caplog):
+ warnings = [rec for rec in caplog.records if rec.levelno == logging.WARNING]
+ assert warnings
+ caplog.clear()
+
+ def test_glob_to_re(self):
+ sep = os.sep
+ if os.sep == '\\':
+ sep = re.escape(os.sep)
+
+ for glob, regex in (
+ # simple cases
+ ('foo*', r'(?s:foo[^%(sep)s]*)\Z'),
+ ('foo?', r'(?s:foo[^%(sep)s])\Z'),
+ ('foo??', r'(?s:foo[^%(sep)s][^%(sep)s])\Z'),
+ # special cases
+ (r'foo\\*', r'(?s:foo\\\\[^%(sep)s]*)\Z'),
+ (r'foo\\\*', r'(?s:foo\\\\\\[^%(sep)s]*)\Z'),
+ ('foo????', r'(?s:foo[^%(sep)s][^%(sep)s][^%(sep)s][^%(sep)s])\Z'),
+ (r'foo\\??', r'(?s:foo\\\\[^%(sep)s][^%(sep)s])\Z'),
+ ):
+ regex = regex % {'sep': sep}
+ assert glob_to_re(glob) == regex
+
+ def test_process_template_line(self):
+ # testing all MANIFEST.in template patterns
+ file_list = FileList()
+ mlp = make_local_path
+
+ # simulated file list
+ file_list.allfiles = [
+ 'foo.tmp',
+ 'ok',
+ 'xo',
+ 'four.txt',
+ 'buildout.cfg',
+ # filelist does not filter out VCS directories,
+ # it's sdist that does
+ mlp('.hg/last-message.txt'),
+ mlp('global/one.txt'),
+ mlp('global/two.txt'),
+ mlp('global/files.x'),
+ mlp('global/here.tmp'),
+ mlp('f/o/f.oo'),
+ mlp('dir/graft-one'),
+ mlp('dir/dir2/graft2'),
+ mlp('dir3/ok'),
+ mlp('dir3/sub/ok.txt'),
+ ]
+
+ for line in MANIFEST_IN.split('\n'):
+ if line.strip() == '':
+ continue
+ file_list.process_template_line(line)
+
+ wanted = [
+ 'ok',
+ 'buildout.cfg',
+ 'four.txt',
+ mlp('.hg/last-message.txt'),
+ mlp('global/one.txt'),
+ mlp('global/two.txt'),
+ mlp('f/o/f.oo'),
+ mlp('dir/graft-one'),
+ mlp('dir/dir2/graft2'),
+ ]
+
+ assert file_list.files == wanted
+
+ def test_debug_print(self, capsys, monkeypatch):
+ file_list = FileList()
+ file_list.debug_print('xxx')
+ assert capsys.readouterr().out == ''
+
+ monkeypatch.setattr(debug, 'DEBUG', True)
+ file_list.debug_print('xxx')
+ assert capsys.readouterr().out == 'xxx\n'
+
+ def test_set_allfiles(self):
+ file_list = FileList()
+ files = ['a', 'b', 'c']
+ file_list.set_allfiles(files)
+ assert file_list.allfiles == files
+
+ def test_remove_duplicates(self):
+ file_list = FileList()
+ file_list.files = ['a', 'b', 'a', 'g', 'c', 'g']
+ # files must be sorted beforehand (sdist does it)
+ file_list.sort()
+ file_list.remove_duplicates()
+ assert file_list.files == ['a', 'b', 'c', 'g']
+
+ def test_translate_pattern(self):
+ # not regex
+ assert hasattr(translate_pattern('a', anchor=True, is_regex=False), 'search')
+
+ # is a regex
+ regex = re.compile('a')
+ assert translate_pattern(regex, anchor=True, is_regex=True) == regex
+
+ # plain string flagged as regex
+ assert hasattr(translate_pattern('a', anchor=True, is_regex=True), 'search')
+
+ # glob support
+ assert translate_pattern('*.py', anchor=True, is_regex=False).search(
+ 'filelist.py'
+ )
+
+ def test_exclude_pattern(self):
+ # return False if no match
+ file_list = FileList()
+ assert not file_list.exclude_pattern('*.py')
+
+ # return True if files match
+ file_list = FileList()
+ file_list.files = ['a.py', 'b.py']
+ assert file_list.exclude_pattern('*.py')
+
+ # test excludes
+ file_list = FileList()
+ file_list.files = ['a.py', 'a.txt']
+ file_list.exclude_pattern('*.py')
+ assert file_list.files == ['a.txt']
+
+ def test_include_pattern(self):
+ # return False if no match
+ file_list = FileList()
+ file_list.set_allfiles([])
+ assert not file_list.include_pattern('*.py')
+
+ # return True if files match
+ file_list = FileList()
+ file_list.set_allfiles(['a.py', 'b.txt'])
+ assert file_list.include_pattern('*.py')
+
+ # test * matches all files
+ file_list = FileList()
+ assert file_list.allfiles is None
+ file_list.set_allfiles(['a.py', 'b.txt'])
+ file_list.include_pattern('*')
+ assert file_list.allfiles == ['a.py', 'b.txt']
+
+ def test_process_template(self, caplog):
+ mlp = make_local_path
+ # invalid lines
+ file_list = FileList()
+ for action in (
+ 'include',
+ 'exclude',
+ 'global-include',
+ 'global-exclude',
+ 'recursive-include',
+ 'recursive-exclude',
+ 'graft',
+ 'prune',
+ 'blarg',
+ ):
+ with pytest.raises(DistutilsTemplateError):
+ file_list.process_template_line(action)
+
+ # include
+ file_list = FileList()
+ file_list.set_allfiles(['a.py', 'b.txt', mlp('d/c.py')])
+
+ file_list.process_template_line('include *.py')
+ assert file_list.files == ['a.py']
+ self.assertNoWarnings(caplog)
+
+ file_list.process_template_line('include *.rb')
+ assert file_list.files == ['a.py']
+ self.assertWarnings(caplog)
+
+ # exclude
+ file_list = FileList()
+ file_list.files = ['a.py', 'b.txt', mlp('d/c.py')]
+
+ file_list.process_template_line('exclude *.py')
+ assert file_list.files == ['b.txt', mlp('d/c.py')]
+ self.assertNoWarnings(caplog)
+
+ file_list.process_template_line('exclude *.rb')
+ assert file_list.files == ['b.txt', mlp('d/c.py')]
+ self.assertWarnings(caplog)
+
+ # global-include
+ file_list = FileList()
+ file_list.set_allfiles(['a.py', 'b.txt', mlp('d/c.py')])
+
+ file_list.process_template_line('global-include *.py')
+ assert file_list.files == ['a.py', mlp('d/c.py')]
+ self.assertNoWarnings(caplog)
+
+ file_list.process_template_line('global-include *.rb')
+ assert file_list.files == ['a.py', mlp('d/c.py')]
+ self.assertWarnings(caplog)
+
+ # global-exclude
+ file_list = FileList()
+ file_list.files = ['a.py', 'b.txt', mlp('d/c.py')]
+
+ file_list.process_template_line('global-exclude *.py')
+ assert file_list.files == ['b.txt']
+ self.assertNoWarnings(caplog)
+
+ file_list.process_template_line('global-exclude *.rb')
+ assert file_list.files == ['b.txt']
+ self.assertWarnings(caplog)
+
+ # recursive-include
+ file_list = FileList()
+ file_list.set_allfiles(['a.py', mlp('d/b.py'), mlp('d/c.txt'), mlp('d/d/e.py')])
+
+ file_list.process_template_line('recursive-include d *.py')
+ assert file_list.files == [mlp('d/b.py'), mlp('d/d/e.py')]
+ self.assertNoWarnings(caplog)
+
+ file_list.process_template_line('recursive-include e *.py')
+ assert file_list.files == [mlp('d/b.py'), mlp('d/d/e.py')]
+ self.assertWarnings(caplog)
+
+ # recursive-exclude
+ file_list = FileList()
+ file_list.files = ['a.py', mlp('d/b.py'), mlp('d/c.txt'), mlp('d/d/e.py')]
+
+ file_list.process_template_line('recursive-exclude d *.py')
+ assert file_list.files == ['a.py', mlp('d/c.txt')]
+ self.assertNoWarnings(caplog)
+
+ file_list.process_template_line('recursive-exclude e *.py')
+ assert file_list.files == ['a.py', mlp('d/c.txt')]
+ self.assertWarnings(caplog)
+
+ # graft
+ file_list = FileList()
+ file_list.set_allfiles(['a.py', mlp('d/b.py'), mlp('d/d/e.py'), mlp('f/f.py')])
+
+ file_list.process_template_line('graft d')
+ assert file_list.files == [mlp('d/b.py'), mlp('d/d/e.py')]
+ self.assertNoWarnings(caplog)
+
+ file_list.process_template_line('graft e')
+ assert file_list.files == [mlp('d/b.py'), mlp('d/d/e.py')]
+ self.assertWarnings(caplog)
+
+ # prune
+ file_list = FileList()
+ file_list.files = ['a.py', mlp('d/b.py'), mlp('d/d/e.py'), mlp('f/f.py')]
+
+ file_list.process_template_line('prune d')
+ assert file_list.files == ['a.py', mlp('f/f.py')]
+ self.assertNoWarnings(caplog)
+
+ file_list.process_template_line('prune e')
+ assert file_list.files == ['a.py', mlp('f/f.py')]
+ self.assertWarnings(caplog)
+
+
+class TestFindAll:
+ @os_helper.skip_unless_symlink
+ def test_missing_symlink(self, temp_cwd):
+ os.symlink('foo', 'bar')
+ assert filelist.findall() == []
+
+ def test_basic_discovery(self, temp_cwd):
+ """
+ When findall is called with no parameters or with
+ '.' as the parameter, the dot should be omitted from
+ the results.
+ """
+ jaraco.path.build({'foo': {'file1.txt': ''}, 'bar': {'file2.txt': ''}})
+ file1 = os.path.join('foo', 'file1.txt')
+ file2 = os.path.join('bar', 'file2.txt')
+ expected = [file2, file1]
+ assert sorted(filelist.findall()) == expected
+
+ def test_non_local_discovery(self, tmp_path):
+ """
+ When findall is called with another path, the full
+ path name should be returned.
+ """
+ jaraco.path.build({'file1.txt': ''}, tmp_path)
+ expected = [str(tmp_path / 'file1.txt')]
+ assert filelist.findall(tmp_path) == expected
+
+ @os_helper.skip_unless_symlink
+ def test_symlink_loop(self, tmp_path):
+ jaraco.path.build(
+ {
+ 'link-to-parent': jaraco.path.Symlink('.'),
+ 'somefile': '',
+ },
+ tmp_path,
+ )
+ files = filelist.findall(tmp_path)
+ assert len(files) == 1
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install.py
new file mode 100644
index 0000000..b3ffb2e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install.py
@@ -0,0 +1,245 @@
+"""Tests for distutils.command.install."""
+
+import logging
+import os
+import pathlib
+import site
+import sys
+from distutils import sysconfig
+from distutils.command import install as install_module
+from distutils.command.build_ext import build_ext
+from distutils.command.install import INSTALL_SCHEMES, install
+from distutils.core import Distribution
+from distutils.errors import DistutilsOptionError
+from distutils.extension import Extension
+from distutils.tests import missing_compiler_executable, support
+from distutils.util import is_mingw
+
+import pytest
+
+
+def _make_ext_name(modname):
+ return modname + sysconfig.get_config_var('EXT_SUFFIX')
+
+
+@support.combine_markers
+@pytest.mark.usefixtures('save_env')
+class TestInstall(
+ support.TempdirManager,
+):
+ @pytest.mark.xfail(
+ 'platform.system() == "Windows" and sys.version_info > (3, 11)',
+ reason="pypa/distutils#148",
+ )
+ def test_home_installation_scheme(self):
+ # This ensure two things:
+ # - that --home generates the desired set of directory names
+ # - test --home is supported on all platforms
+ builddir = self.mkdtemp()
+ destination = os.path.join(builddir, "installation")
+
+ dist = Distribution({"name": "foopkg"})
+ # script_name need not exist, it just need to be initialized
+ dist.script_name = os.path.join(builddir, "setup.py")
+ dist.command_obj["build"] = support.DummyCommand(
+ build_base=builddir,
+ build_lib=os.path.join(builddir, "lib"),
+ )
+
+ cmd = install(dist)
+ cmd.home = destination
+ cmd.ensure_finalized()
+
+ assert cmd.install_base == destination
+ assert cmd.install_platbase == destination
+
+ def check_path(got, expected):
+ got = os.path.normpath(got)
+ expected = os.path.normpath(expected)
+ assert got == expected
+
+ impl_name = sys.implementation.name.replace("cpython", "python")
+ libdir = os.path.join(destination, "lib", impl_name)
+ check_path(cmd.install_lib, libdir)
+ _platlibdir = getattr(sys, "platlibdir", "lib")
+ platlibdir = os.path.join(destination, _platlibdir, impl_name)
+ check_path(cmd.install_platlib, platlibdir)
+ check_path(cmd.install_purelib, libdir)
+ check_path(
+ cmd.install_headers,
+ os.path.join(destination, "include", impl_name, "foopkg"),
+ )
+ check_path(cmd.install_scripts, os.path.join(destination, "bin"))
+ check_path(cmd.install_data, destination)
+
+ def test_user_site(self, monkeypatch):
+ # test install with --user
+ # preparing the environment for the test
+ self.tmpdir = self.mkdtemp()
+ orig_site = site.USER_SITE
+ orig_base = site.USER_BASE
+ monkeypatch.setattr(site, 'USER_BASE', os.path.join(self.tmpdir, 'B'))
+ monkeypatch.setattr(site, 'USER_SITE', os.path.join(self.tmpdir, 'S'))
+ monkeypatch.setattr(install_module, 'USER_BASE', site.USER_BASE)
+ monkeypatch.setattr(install_module, 'USER_SITE', site.USER_SITE)
+
+ def _expanduser(path):
+ if path.startswith('~'):
+ return os.path.normpath(self.tmpdir + path[1:])
+ return path
+
+ monkeypatch.setattr(os.path, 'expanduser', _expanduser)
+
+ for key in ('nt_user', 'posix_user'):
+ assert key in INSTALL_SCHEMES
+
+ dist = Distribution({'name': 'xx'})
+ cmd = install(dist)
+
+ # making sure the user option is there
+ options = [name for name, short, label in cmd.user_options]
+ assert 'user' in options
+
+ # setting a value
+ cmd.user = True
+
+ # user base and site shouldn't be created yet
+ assert not os.path.exists(site.USER_BASE)
+ assert not os.path.exists(site.USER_SITE)
+
+ # let's run finalize
+ cmd.ensure_finalized()
+
+ # now they should
+ assert os.path.exists(site.USER_BASE)
+ assert os.path.exists(site.USER_SITE)
+
+ assert 'userbase' in cmd.config_vars
+ assert 'usersite' in cmd.config_vars
+
+ actual_headers = os.path.relpath(cmd.install_headers, site.USER_BASE)
+ if os.name == 'nt' and not is_mingw():
+ site_path = os.path.relpath(os.path.dirname(orig_site), orig_base)
+ include = os.path.join(site_path, 'Include')
+ else:
+ include = sysconfig.get_python_inc(0, '')
+ expect_headers = os.path.join(include, 'xx')
+
+ assert os.path.normcase(actual_headers) == os.path.normcase(expect_headers)
+
+ def test_handle_extra_path(self):
+ dist = Distribution({'name': 'xx', 'extra_path': 'path,dirs'})
+ cmd = install(dist)
+
+ # two elements
+ cmd.handle_extra_path()
+ assert cmd.extra_path == ['path', 'dirs']
+ assert cmd.extra_dirs == 'dirs'
+ assert cmd.path_file == 'path'
+
+ # one element
+ cmd.extra_path = ['path']
+ cmd.handle_extra_path()
+ assert cmd.extra_path == ['path']
+ assert cmd.extra_dirs == 'path'
+ assert cmd.path_file == 'path'
+
+ # none
+ dist.extra_path = cmd.extra_path = None
+ cmd.handle_extra_path()
+ assert cmd.extra_path is None
+ assert cmd.extra_dirs == ''
+ assert cmd.path_file is None
+
+ # three elements (no way !)
+ cmd.extra_path = 'path,dirs,again'
+ with pytest.raises(DistutilsOptionError):
+ cmd.handle_extra_path()
+
+ def test_finalize_options(self):
+ dist = Distribution({'name': 'xx'})
+ cmd = install(dist)
+
+ # must supply either prefix/exec-prefix/home or
+ # install-base/install-platbase -- not both
+ cmd.prefix = 'prefix'
+ cmd.install_base = 'base'
+ with pytest.raises(DistutilsOptionError):
+ cmd.finalize_options()
+
+ # must supply either home or prefix/exec-prefix -- not both
+ cmd.install_base = None
+ cmd.home = 'home'
+ with pytest.raises(DistutilsOptionError):
+ cmd.finalize_options()
+
+ # can't combine user with prefix/exec_prefix/home or
+ # install_(plat)base
+ cmd.prefix = None
+ cmd.user = 'user'
+ with pytest.raises(DistutilsOptionError):
+ cmd.finalize_options()
+
+ def test_record(self):
+ install_dir = self.mkdtemp()
+ project_dir, dist = self.create_dist(py_modules=['hello'], scripts=['sayhi'])
+ os.chdir(project_dir)
+ self.write_file('hello.py', "def main(): print('o hai')")
+ self.write_file('sayhi', 'from hello import main; main()')
+
+ cmd = install(dist)
+ dist.command_obj['install'] = cmd
+ cmd.root = install_dir
+ cmd.record = os.path.join(project_dir, 'filelist')
+ cmd.ensure_finalized()
+ cmd.run()
+
+ content = pathlib.Path(cmd.record).read_text(encoding='utf-8')
+
+ found = [pathlib.Path(line).name for line in content.splitlines()]
+ expected = [
+ 'hello.py',
+ f'hello.{sys.implementation.cache_tag}.pyc',
+ 'sayhi',
+ 'UNKNOWN-0.0.0-py{}.{}.egg-info'.format(*sys.version_info[:2]),
+ ]
+ assert found == expected
+
+ def test_record_extensions(self):
+ cmd = missing_compiler_executable()
+ if cmd is not None:
+ pytest.skip(f'The {cmd!r} command is not found')
+ install_dir = self.mkdtemp()
+ project_dir, dist = self.create_dist(
+ ext_modules=[Extension('xx', ['xxmodule.c'])]
+ )
+ os.chdir(project_dir)
+ support.copy_xxmodule_c(project_dir)
+
+ buildextcmd = build_ext(dist)
+ support.fixup_build_ext(buildextcmd)
+ buildextcmd.ensure_finalized()
+
+ cmd = install(dist)
+ dist.command_obj['install'] = cmd
+ dist.command_obj['build_ext'] = buildextcmd
+ cmd.root = install_dir
+ cmd.record = os.path.join(project_dir, 'filelist')
+ cmd.ensure_finalized()
+ cmd.run()
+
+ content = pathlib.Path(cmd.record).read_text(encoding='utf-8')
+
+ found = [pathlib.Path(line).name for line in content.splitlines()]
+ expected = [
+ _make_ext_name('xx'),
+ 'UNKNOWN-0.0.0-py{}.{}.egg-info'.format(*sys.version_info[:2]),
+ ]
+ assert found == expected
+
+ def test_debug_mode(self, caplog, monkeypatch):
+ # this covers the code called when DEBUG is set
+ monkeypatch.setattr(install_module, 'DEBUG', True)
+ caplog.set_level(logging.DEBUG)
+ self.test_record()
+ assert any(rec for rec in caplog.records if rec.levelno == logging.DEBUG)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_data.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_data.py
new file mode 100644
index 0000000..c800f86
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_data.py
@@ -0,0 +1,74 @@
+"""Tests for distutils.command.install_data."""
+
+import os
+import pathlib
+from distutils.command.install_data import install_data
+from distutils.tests import support
+
+import pytest
+
+
+@pytest.mark.usefixtures('save_env')
+class TestInstallData(
+ support.TempdirManager,
+):
+ def test_simple_run(self):
+ pkg_dir, dist = self.create_dist()
+ cmd = install_data(dist)
+ cmd.install_dir = inst = os.path.join(pkg_dir, 'inst')
+
+ # data_files can contain
+ # - simple files
+ # - a Path object
+ # - a tuple with a path, and a list of file
+ one = os.path.join(pkg_dir, 'one')
+ self.write_file(one, 'xxx')
+ inst2 = os.path.join(pkg_dir, 'inst2')
+ two = os.path.join(pkg_dir, 'two')
+ self.write_file(two, 'xxx')
+ three = pathlib.Path(pkg_dir) / 'three'
+ self.write_file(three, 'xxx')
+
+ cmd.data_files = [one, (inst2, [two]), three]
+ assert cmd.get_inputs() == [one, (inst2, [two]), three]
+
+ # let's run the command
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # let's check the result
+ assert len(cmd.get_outputs()) == 3
+ rthree = os.path.split(one)[-1]
+ assert os.path.exists(os.path.join(inst, rthree))
+ rtwo = os.path.split(two)[-1]
+ assert os.path.exists(os.path.join(inst2, rtwo))
+ rone = os.path.split(one)[-1]
+ assert os.path.exists(os.path.join(inst, rone))
+ cmd.outfiles = []
+
+ # let's try with warn_dir one
+ cmd.warn_dir = True
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # let's check the result
+ assert len(cmd.get_outputs()) == 3
+ assert os.path.exists(os.path.join(inst, rthree))
+ assert os.path.exists(os.path.join(inst2, rtwo))
+ assert os.path.exists(os.path.join(inst, rone))
+ cmd.outfiles = []
+
+ # now using root and empty dir
+ cmd.root = os.path.join(pkg_dir, 'root')
+ inst5 = os.path.join(pkg_dir, 'inst5')
+ four = os.path.join(cmd.install_dir, 'four')
+ self.write_file(four, 'xx')
+ cmd.data_files = [one, (inst2, [two]), three, ('inst5', [four]), (inst5, [])]
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # let's check the result
+ assert len(cmd.get_outputs()) == 5
+ assert os.path.exists(os.path.join(inst, rthree))
+ assert os.path.exists(os.path.join(inst2, rtwo))
+ assert os.path.exists(os.path.join(inst, rone))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_headers.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_headers.py
new file mode 100644
index 0000000..2c74f06
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_headers.py
@@ -0,0 +1,33 @@
+"""Tests for distutils.command.install_headers."""
+
+import os
+from distutils.command.install_headers import install_headers
+from distutils.tests import support
+
+import pytest
+
+
+@pytest.mark.usefixtures('save_env')
+class TestInstallHeaders(
+ support.TempdirManager,
+):
+ def test_simple_run(self):
+ # we have two headers
+ header_list = self.mkdtemp()
+ header1 = os.path.join(header_list, 'header1')
+ header2 = os.path.join(header_list, 'header2')
+ self.write_file(header1)
+ self.write_file(header2)
+ headers = [header1, header2]
+
+ pkg_dir, dist = self.create_dist(headers=headers)
+ cmd = install_headers(dist)
+ assert cmd.get_inputs() == headers
+
+ # let's run the command
+ cmd.install_dir = os.path.join(pkg_dir, 'inst')
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # let's check the results
+ assert len(cmd.get_outputs()) == 2
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_lib.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_lib.py
new file mode 100644
index 0000000..f685a57
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_lib.py
@@ -0,0 +1,110 @@
+"""Tests for distutils.command.install_data."""
+
+import importlib.util
+import os
+import sys
+from distutils.command.install_lib import install_lib
+from distutils.errors import DistutilsOptionError
+from distutils.extension import Extension
+from distutils.tests import support
+
+import pytest
+
+
+@support.combine_markers
+@pytest.mark.usefixtures('save_env')
+class TestInstallLib(
+ support.TempdirManager,
+):
+ def test_finalize_options(self):
+ dist = self.create_dist()[1]
+ cmd = install_lib(dist)
+
+ cmd.finalize_options()
+ assert cmd.compile == 1
+ assert cmd.optimize == 0
+
+ # optimize must be 0, 1, or 2
+ cmd.optimize = 'foo'
+ with pytest.raises(DistutilsOptionError):
+ cmd.finalize_options()
+ cmd.optimize = '4'
+ with pytest.raises(DistutilsOptionError):
+ cmd.finalize_options()
+
+ cmd.optimize = '2'
+ cmd.finalize_options()
+ assert cmd.optimize == 2
+
+ @pytest.mark.skipif('sys.dont_write_bytecode')
+ def test_byte_compile(self):
+ project_dir, dist = self.create_dist()
+ os.chdir(project_dir)
+ cmd = install_lib(dist)
+ cmd.compile = cmd.optimize = 1
+
+ f = os.path.join(project_dir, 'foo.py')
+ self.write_file(f, '# python file')
+ cmd.byte_compile([f])
+ pyc_file = importlib.util.cache_from_source('foo.py', optimization='')
+ pyc_opt_file = importlib.util.cache_from_source(
+ 'foo.py', optimization=cmd.optimize
+ )
+ assert os.path.exists(pyc_file)
+ assert os.path.exists(pyc_opt_file)
+
+ def test_get_outputs(self):
+ project_dir, dist = self.create_dist()
+ os.chdir(project_dir)
+ os.mkdir('spam')
+ cmd = install_lib(dist)
+
+ # setting up a dist environment
+ cmd.compile = cmd.optimize = 1
+ cmd.install_dir = self.mkdtemp()
+ f = os.path.join(project_dir, 'spam', '__init__.py')
+ self.write_file(f, '# python package')
+ cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
+ cmd.distribution.packages = ['spam']
+ cmd.distribution.script_name = 'setup.py'
+
+ # get_outputs should return 4 elements: spam/__init__.py and .pyc,
+ # foo.import-tag-abiflags.so / foo.pyd
+ outputs = cmd.get_outputs()
+ assert len(outputs) == 4, outputs
+
+ def test_get_inputs(self):
+ project_dir, dist = self.create_dist()
+ os.chdir(project_dir)
+ os.mkdir('spam')
+ cmd = install_lib(dist)
+
+ # setting up a dist environment
+ cmd.compile = cmd.optimize = 1
+ cmd.install_dir = self.mkdtemp()
+ f = os.path.join(project_dir, 'spam', '__init__.py')
+ self.write_file(f, '# python package')
+ cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
+ cmd.distribution.packages = ['spam']
+ cmd.distribution.script_name = 'setup.py'
+
+ # get_inputs should return 2 elements: spam/__init__.py and
+ # foo.import-tag-abiflags.so / foo.pyd
+ inputs = cmd.get_inputs()
+ assert len(inputs) == 2, inputs
+
+ def test_dont_write_bytecode(self, caplog):
+ # makes sure byte_compile is not used
+ dist = self.create_dist()[1]
+ cmd = install_lib(dist)
+ cmd.compile = True
+ cmd.optimize = 1
+
+ old_dont_write_bytecode = sys.dont_write_bytecode
+ sys.dont_write_bytecode = True
+ try:
+ cmd.byte_compile([])
+ finally:
+ sys.dont_write_bytecode = old_dont_write_bytecode
+
+ assert 'byte-compiling is disabled' in caplog.messages[0]
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_scripts.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_scripts.py
new file mode 100644
index 0000000..868b1c2
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_install_scripts.py
@@ -0,0 +1,52 @@
+"""Tests for distutils.command.install_scripts."""
+
+import os
+from distutils.command.install_scripts import install_scripts
+from distutils.core import Distribution
+from distutils.tests import support
+
+from . import test_build_scripts
+
+
+class TestInstallScripts(support.TempdirManager):
+ def test_default_settings(self):
+ dist = Distribution()
+ dist.command_obj["build"] = support.DummyCommand(build_scripts="/foo/bar")
+ dist.command_obj["install"] = support.DummyCommand(
+ install_scripts="/splat/funk",
+ force=True,
+ skip_build=True,
+ )
+ cmd = install_scripts(dist)
+ assert not cmd.force
+ assert not cmd.skip_build
+ assert cmd.build_dir is None
+ assert cmd.install_dir is None
+
+ cmd.finalize_options()
+
+ assert cmd.force
+ assert cmd.skip_build
+ assert cmd.build_dir == "/foo/bar"
+ assert cmd.install_dir == "/splat/funk"
+
+ def test_installation(self):
+ source = self.mkdtemp()
+
+ expected = test_build_scripts.TestBuildScripts.write_sample_scripts(source)
+
+ target = self.mkdtemp()
+ dist = Distribution()
+ dist.command_obj["build"] = support.DummyCommand(build_scripts=source)
+ dist.command_obj["install"] = support.DummyCommand(
+ install_scripts=target,
+ force=True,
+ skip_build=True,
+ )
+ cmd = install_scripts(dist)
+ cmd.finalize_options()
+ cmd.run()
+
+ installed = os.listdir(target)
+ for name in expected:
+ assert name in installed
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_log.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_log.py
new file mode 100644
index 0000000..d67779f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_log.py
@@ -0,0 +1,12 @@
+"""Tests for distutils.log"""
+
+import logging
+from distutils._log import log
+
+
+class TestLog:
+ def test_non_ascii(self, caplog):
+ caplog.set_level(logging.DEBUG)
+ log.debug('Dεbug\tMėssãge')
+ log.fatal('Fαtal\tÈrrōr')
+ assert caplog.messages == ['Dεbug\tMėssãge', 'Fαtal\tÈrrōr']
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_modified.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_modified.py
new file mode 100644
index 0000000..e35cec2
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_modified.py
@@ -0,0 +1,126 @@
+"""Tests for distutils._modified."""
+
+import os
+import types
+from distutils._modified import newer, newer_group, newer_pairwise, newer_pairwise_group
+from distutils.errors import DistutilsFileError
+from distutils.tests import support
+
+import pytest
+
+
+class TestDepUtil(support.TempdirManager):
+ def test_newer(self):
+ tmpdir = self.mkdtemp()
+ new_file = os.path.join(tmpdir, 'new')
+ old_file = os.path.abspath(__file__)
+
+ # Raise DistutilsFileError if 'new_file' does not exist.
+ with pytest.raises(DistutilsFileError):
+ newer(new_file, old_file)
+
+ # Return true if 'new_file' exists and is more recently modified than
+ # 'old_file', or if 'new_file' exists and 'old_file' doesn't.
+ self.write_file(new_file)
+ assert newer(new_file, 'I_dont_exist')
+ assert newer(new_file, old_file)
+
+ # Return false if both exist and 'old_file' is the same age or younger
+ # than 'new_file'.
+ assert not newer(old_file, new_file)
+
+ def _setup_1234(self):
+ tmpdir = self.mkdtemp()
+ sources = os.path.join(tmpdir, 'sources')
+ targets = os.path.join(tmpdir, 'targets')
+ os.mkdir(sources)
+ os.mkdir(targets)
+ one = os.path.join(sources, 'one')
+ two = os.path.join(sources, 'two')
+ three = os.path.abspath(__file__) # I am the old file
+ four = os.path.join(targets, 'four')
+ self.write_file(one)
+ self.write_file(two)
+ self.write_file(four)
+ return one, two, three, four
+
+ def test_newer_pairwise(self):
+ one, two, three, four = self._setup_1234()
+
+ assert newer_pairwise([one, two], [three, four]) == ([one], [three])
+
+ def test_newer_pairwise_mismatch(self):
+ one, two, three, four = self._setup_1234()
+
+ with pytest.raises(ValueError):
+ newer_pairwise([one], [three, four])
+
+ with pytest.raises(ValueError):
+ newer_pairwise([one, two], [three])
+
+ def test_newer_pairwise_empty(self):
+ assert newer_pairwise([], []) == ([], [])
+
+ def test_newer_pairwise_fresh(self):
+ one, two, three, four = self._setup_1234()
+
+ assert newer_pairwise([one, three], [two, four]) == ([], [])
+
+ def test_newer_group(self):
+ tmpdir = self.mkdtemp()
+ sources = os.path.join(tmpdir, 'sources')
+ os.mkdir(sources)
+ one = os.path.join(sources, 'one')
+ two = os.path.join(sources, 'two')
+ three = os.path.join(sources, 'three')
+ old_file = os.path.abspath(__file__)
+
+ # return true if 'old_file' is out-of-date with respect to any file
+ # listed in 'sources'.
+ self.write_file(one)
+ self.write_file(two)
+ self.write_file(three)
+ assert newer_group([one, two, three], old_file)
+ assert not newer_group([one, two, old_file], three)
+
+ # missing handling
+ os.remove(one)
+ with pytest.raises(OSError):
+ newer_group([one, two, old_file], three)
+
+ assert not newer_group([one, two, old_file], three, missing='ignore')
+
+ assert newer_group([one, two, old_file], three, missing='newer')
+
+
+@pytest.fixture
+def groups_target(tmp_path):
+ """
+ Set up some older sources, a target, and newer sources.
+
+ Returns a simple namespace with these values.
+ """
+ filenames = ['older.c', 'older.h', 'target.o', 'newer.c', 'newer.h']
+ paths = [tmp_path / name for name in filenames]
+
+ for mtime, path in enumerate(paths):
+ path.write_text('', encoding='utf-8')
+
+ # make sure modification times are sequential
+ os.utime(path, (mtime, mtime))
+
+ return types.SimpleNamespace(older=paths[:2], target=paths[2], newer=paths[3:])
+
+
+def test_newer_pairwise_group(groups_target):
+ older = newer_pairwise_group([groups_target.older], [groups_target.target])
+ newer = newer_pairwise_group([groups_target.newer], [groups_target.target])
+ assert older == ([], [])
+ assert newer == ([groups_target.newer], [groups_target.target])
+
+
+def test_newer_group_no_sources_no_target(tmp_path):
+ """
+ Consider no sources and no target "newer".
+ """
+ assert newer_group([], str(tmp_path / 'does-not-exist'))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_sdist.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_sdist.py
new file mode 100644
index 0000000..6b1a376
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_sdist.py
@@ -0,0 +1,470 @@
+"""Tests for distutils.command.sdist."""
+
+import os
+import pathlib
+import shutil # noqa: F401
+import tarfile
+import zipfile
+from distutils.archive_util import ARCHIVE_FORMATS
+from distutils.command.sdist import sdist, show_formats
+from distutils.core import Distribution
+from distutils.errors import DistutilsOptionError
+from distutils.filelist import FileList
+from os.path import join
+from textwrap import dedent
+
+import jaraco.path
+import path
+import pytest
+from more_itertools import ilen
+
+from . import support
+from .unix_compat import grp, pwd, require_uid_0, require_unix_id
+
+SETUP_PY = """
+from distutils.core import setup
+import somecode
+
+setup(name='fake')
+"""
+
+MANIFEST = """\
+# file GENERATED by distutils, do NOT edit
+README
+buildout.cfg
+inroot.txt
+setup.py
+data%(sep)sdata.dt
+scripts%(sep)sscript.py
+some%(sep)sfile.txt
+some%(sep)sother_file.txt
+somecode%(sep)s__init__.py
+somecode%(sep)sdoc.dat
+somecode%(sep)sdoc.txt
+"""
+
+
+@pytest.fixture(autouse=True)
+def project_dir(request, distutils_managed_tempdir):
+ self = request.instance
+ self.tmp_dir = self.mkdtemp()
+ jaraco.path.build(
+ {
+ 'somecode': {
+ '__init__.py': '#',
+ },
+ 'README': 'xxx',
+ 'setup.py': SETUP_PY,
+ },
+ self.tmp_dir,
+ )
+ with path.Path(self.tmp_dir):
+ yield
+
+
+def clean_lines(filepath):
+ with pathlib.Path(filepath).open(encoding='utf-8') as f:
+ yield from filter(None, map(str.strip, f))
+
+
+class TestSDist(support.TempdirManager):
+ def get_cmd(self, metadata=None):
+ """Returns a cmd"""
+ if metadata is None:
+ metadata = {
+ 'name': 'ns.fake--pkg',
+ 'version': '1.0',
+ 'url': 'xxx',
+ 'author': 'xxx',
+ 'author_email': 'xxx',
+ }
+ dist = Distribution(metadata)
+ dist.script_name = 'setup.py'
+ dist.packages = ['somecode']
+ dist.include_package_data = True
+ cmd = sdist(dist)
+ cmd.dist_dir = 'dist'
+ return dist, cmd
+
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_prune_file_list(self):
+ # this test creates a project with some VCS dirs and an NFS rename
+ # file, then launches sdist to check they get pruned on all systems
+
+ # creating VCS directories with some files in them
+ os.mkdir(join(self.tmp_dir, 'somecode', '.svn'))
+ self.write_file((self.tmp_dir, 'somecode', '.svn', 'ok.py'), 'xxx')
+
+ os.mkdir(join(self.tmp_dir, 'somecode', '.hg'))
+ self.write_file((self.tmp_dir, 'somecode', '.hg', 'ok'), 'xxx')
+
+ os.mkdir(join(self.tmp_dir, 'somecode', '.git'))
+ self.write_file((self.tmp_dir, 'somecode', '.git', 'ok'), 'xxx')
+
+ self.write_file((self.tmp_dir, 'somecode', '.nfs0001'), 'xxx')
+
+ # now building a sdist
+ dist, cmd = self.get_cmd()
+
+ # zip is available universally
+ # (tar might not be installed under win32)
+ cmd.formats = ['zip']
+
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # now let's check what we have
+ dist_folder = join(self.tmp_dir, 'dist')
+ files = os.listdir(dist_folder)
+ assert files == ['ns_fake_pkg-1.0.zip']
+
+ zip_file = zipfile.ZipFile(join(dist_folder, 'ns_fake_pkg-1.0.zip'))
+ try:
+ content = zip_file.namelist()
+ finally:
+ zip_file.close()
+
+ # making sure everything has been pruned correctly
+ expected = [
+ '',
+ 'PKG-INFO',
+ 'README',
+ 'setup.py',
+ 'somecode/',
+ 'somecode/__init__.py',
+ ]
+ assert sorted(content) == ['ns_fake_pkg-1.0/' + x for x in expected]
+
+ @pytest.mark.usefixtures('needs_zlib')
+ @pytest.mark.skipif("not shutil.which('tar')")
+ @pytest.mark.skipif("not shutil.which('gzip')")
+ def test_make_distribution(self):
+ # now building a sdist
+ dist, cmd = self.get_cmd()
+
+ # creating a gztar then a tar
+ cmd.formats = ['gztar', 'tar']
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # making sure we have two files
+ dist_folder = join(self.tmp_dir, 'dist')
+ result = os.listdir(dist_folder)
+ result.sort()
+ assert result == ['ns_fake_pkg-1.0.tar', 'ns_fake_pkg-1.0.tar.gz']
+
+ os.remove(join(dist_folder, 'ns_fake_pkg-1.0.tar'))
+ os.remove(join(dist_folder, 'ns_fake_pkg-1.0.tar.gz'))
+
+ # now trying a tar then a gztar
+ cmd.formats = ['tar', 'gztar']
+
+ cmd.ensure_finalized()
+ cmd.run()
+
+ result = os.listdir(dist_folder)
+ result.sort()
+ assert result == ['ns_fake_pkg-1.0.tar', 'ns_fake_pkg-1.0.tar.gz']
+
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_add_defaults(self):
+ # https://bugs.python.org/issue2279
+
+ # add_default should also include
+ # data_files and package_data
+ dist, cmd = self.get_cmd()
+
+ # filling data_files by pointing files
+ # in package_data
+ dist.package_data = {'': ['*.cfg', '*.dat'], 'somecode': ['*.txt']}
+ self.write_file((self.tmp_dir, 'somecode', 'doc.txt'), '#')
+ self.write_file((self.tmp_dir, 'somecode', 'doc.dat'), '#')
+
+ # adding some data in data_files
+ data_dir = join(self.tmp_dir, 'data')
+ os.mkdir(data_dir)
+ self.write_file((data_dir, 'data.dt'), '#')
+ some_dir = join(self.tmp_dir, 'some')
+ os.mkdir(some_dir)
+ # make sure VCS directories are pruned (#14004)
+ hg_dir = join(self.tmp_dir, '.hg')
+ os.mkdir(hg_dir)
+ self.write_file((hg_dir, 'last-message.txt'), '#')
+ # a buggy regex used to prevent this from working on windows (#6884)
+ self.write_file((self.tmp_dir, 'buildout.cfg'), '#')
+ self.write_file((self.tmp_dir, 'inroot.txt'), '#')
+ self.write_file((some_dir, 'file.txt'), '#')
+ self.write_file((some_dir, 'other_file.txt'), '#')
+
+ dist.data_files = [
+ ('data', ['data/data.dt', 'buildout.cfg', 'inroot.txt', 'notexisting']),
+ 'some/file.txt',
+ 'some/other_file.txt',
+ ]
+
+ # adding a script
+ script_dir = join(self.tmp_dir, 'scripts')
+ os.mkdir(script_dir)
+ self.write_file((script_dir, 'script.py'), '#')
+ dist.scripts = [join('scripts', 'script.py')]
+
+ cmd.formats = ['zip']
+ cmd.use_defaults = True
+
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # now let's check what we have
+ dist_folder = join(self.tmp_dir, 'dist')
+ files = os.listdir(dist_folder)
+ assert files == ['ns_fake_pkg-1.0.zip']
+
+ zip_file = zipfile.ZipFile(join(dist_folder, 'ns_fake_pkg-1.0.zip'))
+ try:
+ content = zip_file.namelist()
+ finally:
+ zip_file.close()
+
+ # making sure everything was added
+ expected = [
+ '',
+ 'PKG-INFO',
+ 'README',
+ 'buildout.cfg',
+ 'data/',
+ 'data/data.dt',
+ 'inroot.txt',
+ 'scripts/',
+ 'scripts/script.py',
+ 'setup.py',
+ 'some/',
+ 'some/file.txt',
+ 'some/other_file.txt',
+ 'somecode/',
+ 'somecode/__init__.py',
+ 'somecode/doc.dat',
+ 'somecode/doc.txt',
+ ]
+ assert sorted(content) == ['ns_fake_pkg-1.0/' + x for x in expected]
+
+ # checking the MANIFEST
+ manifest = pathlib.Path(self.tmp_dir, 'MANIFEST').read_text(encoding='utf-8')
+ assert manifest == MANIFEST % {'sep': os.sep}
+
+ @staticmethod
+ def warnings(messages, prefix='warning: '):
+ return [msg for msg in messages if msg.startswith(prefix)]
+
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_metadata_check_option(self, caplog):
+ # testing the `medata-check` option
+ dist, cmd = self.get_cmd(metadata={})
+
+ # this should raise some warnings !
+ # with the `check` subcommand
+ cmd.ensure_finalized()
+ cmd.run()
+ assert len(self.warnings(caplog.messages, 'warning: check: ')) == 1
+
+ # trying with a complete set of metadata
+ caplog.clear()
+ dist, cmd = self.get_cmd()
+ cmd.ensure_finalized()
+ cmd.metadata_check = False
+ cmd.run()
+ assert len(self.warnings(caplog.messages, 'warning: check: ')) == 0
+
+ def test_show_formats(self, capsys):
+ show_formats()
+
+ # the output should be a header line + one line per format
+ num_formats = len(ARCHIVE_FORMATS.keys())
+ output = [
+ line
+ for line in capsys.readouterr().out.split('\n')
+ if line.strip().startswith('--formats=')
+ ]
+ assert len(output) == num_formats
+
+ def test_finalize_options(self):
+ dist, cmd = self.get_cmd()
+ cmd.finalize_options()
+
+ # default options set by finalize
+ assert cmd.manifest == 'MANIFEST'
+ assert cmd.template == 'MANIFEST.in'
+ assert cmd.dist_dir == 'dist'
+
+ # formats has to be a string splitable on (' ', ',') or
+ # a stringlist
+ cmd.formats = 1
+ with pytest.raises(DistutilsOptionError):
+ cmd.finalize_options()
+ cmd.formats = ['zip']
+ cmd.finalize_options()
+
+ # formats has to be known
+ cmd.formats = 'supazipa'
+ with pytest.raises(DistutilsOptionError):
+ cmd.finalize_options()
+
+ # the following tests make sure there is a nice error message instead
+ # of a traceback when parsing an invalid manifest template
+
+ def _check_template(self, content, caplog):
+ dist, cmd = self.get_cmd()
+ os.chdir(self.tmp_dir)
+ self.write_file('MANIFEST.in', content)
+ cmd.ensure_finalized()
+ cmd.filelist = FileList()
+ cmd.read_template()
+ assert len(self.warnings(caplog.messages)) == 1
+
+ def test_invalid_template_unknown_command(self, caplog):
+ self._check_template('taunt knights *', caplog)
+
+ def test_invalid_template_wrong_arguments(self, caplog):
+ # this manifest command takes one argument
+ self._check_template('prune', caplog)
+
+ @pytest.mark.skipif("platform.system() != 'Windows'")
+ def test_invalid_template_wrong_path(self, caplog):
+ # on Windows, trailing slashes are not allowed
+ # this used to crash instead of raising a warning: #8286
+ self._check_template('include examples/', caplog)
+
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_get_file_list(self):
+ # make sure MANIFEST is recalculated
+ dist, cmd = self.get_cmd()
+
+ # filling data_files by pointing files in package_data
+ dist.package_data = {'somecode': ['*.txt']}
+ self.write_file((self.tmp_dir, 'somecode', 'doc.txt'), '#')
+ cmd.formats = ['gztar']
+ cmd.ensure_finalized()
+ cmd.run()
+
+ assert ilen(clean_lines(cmd.manifest)) == 5
+
+ # adding a file
+ self.write_file((self.tmp_dir, 'somecode', 'doc2.txt'), '#')
+
+ # make sure build_py is reinitialized, like a fresh run
+ build_py = dist.get_command_obj('build_py')
+ build_py.finalized = False
+ build_py.ensure_finalized()
+
+ cmd.run()
+
+ manifest2 = list(clean_lines(cmd.manifest))
+
+ # do we have the new file in MANIFEST ?
+ assert len(manifest2) == 6
+ assert 'doc2.txt' in manifest2[-1]
+
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_manifest_marker(self):
+ # check that autogenerated MANIFESTs have a marker
+ dist, cmd = self.get_cmd()
+ cmd.ensure_finalized()
+ cmd.run()
+
+ assert (
+ next(clean_lines(cmd.manifest))
+ == '# file GENERATED by distutils, do NOT edit'
+ )
+
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_manifest_comments(self):
+ # make sure comments don't cause exceptions or wrong includes
+ contents = dedent(
+ """\
+ # bad.py
+ #bad.py
+ good.py
+ """
+ )
+ dist, cmd = self.get_cmd()
+ cmd.ensure_finalized()
+ self.write_file((self.tmp_dir, cmd.manifest), contents)
+ self.write_file((self.tmp_dir, 'good.py'), '# pick me!')
+ self.write_file((self.tmp_dir, 'bad.py'), "# don't pick me!")
+ self.write_file((self.tmp_dir, '#bad.py'), "# don't pick me!")
+ cmd.run()
+ assert cmd.filelist.files == ['good.py']
+
+ @pytest.mark.usefixtures('needs_zlib')
+ def test_manual_manifest(self):
+ # check that a MANIFEST without a marker is left alone
+ dist, cmd = self.get_cmd()
+ cmd.formats = ['gztar']
+ cmd.ensure_finalized()
+ self.write_file((self.tmp_dir, cmd.manifest), 'README.manual')
+ self.write_file(
+ (self.tmp_dir, 'README.manual'),
+ 'This project maintains its MANIFEST file itself.',
+ )
+ cmd.run()
+ assert cmd.filelist.files == ['README.manual']
+
+ assert list(clean_lines(cmd.manifest)) == ['README.manual']
+
+ archive_name = join(self.tmp_dir, 'dist', 'ns_fake_pkg-1.0.tar.gz')
+ archive = tarfile.open(archive_name)
+ try:
+ filenames = [tarinfo.name for tarinfo in archive]
+ finally:
+ archive.close()
+ assert sorted(filenames) == [
+ 'ns_fake_pkg-1.0',
+ 'ns_fake_pkg-1.0/PKG-INFO',
+ 'ns_fake_pkg-1.0/README.manual',
+ ]
+
+ @pytest.mark.usefixtures('needs_zlib')
+ @require_unix_id
+ @require_uid_0
+ @pytest.mark.skipif("not shutil.which('tar')")
+ @pytest.mark.skipif("not shutil.which('gzip')")
+ def test_make_distribution_owner_group(self):
+ # now building a sdist
+ dist, cmd = self.get_cmd()
+
+ # creating a gztar and specifying the owner+group
+ cmd.formats = ['gztar']
+ cmd.owner = pwd.getpwuid(0)[0]
+ cmd.group = grp.getgrgid(0)[0]
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # making sure we have the good rights
+ archive_name = join(self.tmp_dir, 'dist', 'ns_fake_pkg-1.0.tar.gz')
+ archive = tarfile.open(archive_name)
+ try:
+ for member in archive.getmembers():
+ assert member.uid == 0
+ assert member.gid == 0
+ finally:
+ archive.close()
+
+ # building a sdist again
+ dist, cmd = self.get_cmd()
+
+ # creating a gztar
+ cmd.formats = ['gztar']
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # making sure we have the good rights
+ archive_name = join(self.tmp_dir, 'dist', 'ns_fake_pkg-1.0.tar.gz')
+ archive = tarfile.open(archive_name)
+
+ # note that we are not testing the group ownership here
+ # because, depending on the platforms and the container
+ # rights (see #7408)
+ try:
+ for member in archive.getmembers():
+ assert member.uid == os.getuid()
+ finally:
+ archive.close()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_spawn.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_spawn.py
new file mode 100644
index 0000000..3b9fc92
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_spawn.py
@@ -0,0 +1,141 @@
+"""Tests for distutils.spawn."""
+
+import os
+import stat
+import sys
+import unittest.mock as mock
+from distutils.errors import DistutilsExecError
+from distutils.spawn import find_executable, spawn
+from distutils.tests import support
+
+import path
+import pytest
+from test.support import unix_shell
+
+from .compat import py39 as os_helper
+
+
+class TestSpawn(support.TempdirManager):
+ @pytest.mark.skipif("os.name not in ('nt', 'posix')")
+ def test_spawn(self):
+ tmpdir = self.mkdtemp()
+
+ # creating something executable
+ # through the shell that returns 1
+ if sys.platform != 'win32':
+ exe = os.path.join(tmpdir, 'foo.sh')
+ self.write_file(exe, f'#!{unix_shell}\nexit 1')
+ else:
+ exe = os.path.join(tmpdir, 'foo.bat')
+ self.write_file(exe, 'exit 1')
+
+ os.chmod(exe, 0o777)
+ with pytest.raises(DistutilsExecError):
+ spawn([exe])
+
+ # now something that works
+ if sys.platform != 'win32':
+ exe = os.path.join(tmpdir, 'foo.sh')
+ self.write_file(exe, f'#!{unix_shell}\nexit 0')
+ else:
+ exe = os.path.join(tmpdir, 'foo.bat')
+ self.write_file(exe, 'exit 0')
+
+ os.chmod(exe, 0o777)
+ spawn([exe]) # should work without any error
+
+ def test_find_executable(self, tmp_path):
+ program_path = self._make_executable(tmp_path, '.exe')
+ program = program_path.name
+ program_noeext = program_path.with_suffix('').name
+ filename = str(program_path)
+ tmp_dir = path.Path(tmp_path)
+
+ # test path parameter
+ rv = find_executable(program, path=tmp_dir)
+ assert rv == filename
+
+ if sys.platform == 'win32':
+ # test without ".exe" extension
+ rv = find_executable(program_noeext, path=tmp_dir)
+ assert rv == filename
+
+ # test find in the current directory
+ with tmp_dir:
+ rv = find_executable(program)
+ assert rv == program
+
+ # test non-existent program
+ dont_exist_program = "dontexist_" + program
+ rv = find_executable(dont_exist_program, path=tmp_dir)
+ assert rv is None
+
+ # PATH='': no match, except in the current directory
+ with os_helper.EnvironmentVarGuard() as env:
+ env['PATH'] = ''
+ with (
+ mock.patch(
+ 'distutils.spawn.os.confstr', return_value=tmp_dir, create=True
+ ),
+ mock.patch('distutils.spawn.os.defpath', tmp_dir),
+ ):
+ rv = find_executable(program)
+ assert rv is None
+
+ # look in current directory
+ with tmp_dir:
+ rv = find_executable(program)
+ assert rv == program
+
+ # PATH=':': explicitly looks in the current directory
+ with os_helper.EnvironmentVarGuard() as env:
+ env['PATH'] = os.pathsep
+ with (
+ mock.patch('distutils.spawn.os.confstr', return_value='', create=True),
+ mock.patch('distutils.spawn.os.defpath', ''),
+ ):
+ rv = find_executable(program)
+ assert rv is None
+
+ # look in current directory
+ with tmp_dir:
+ rv = find_executable(program)
+ assert rv == program
+
+ # missing PATH: test os.confstr("CS_PATH") and os.defpath
+ with os_helper.EnvironmentVarGuard() as env:
+ env.pop('PATH', None)
+
+ # without confstr
+ with (
+ mock.patch(
+ 'distutils.spawn.os.confstr', side_effect=ValueError, create=True
+ ),
+ mock.patch('distutils.spawn.os.defpath', tmp_dir),
+ ):
+ rv = find_executable(program)
+ assert rv == filename
+
+ # with confstr
+ with (
+ mock.patch(
+ 'distutils.spawn.os.confstr', return_value=tmp_dir, create=True
+ ),
+ mock.patch('distutils.spawn.os.defpath', ''),
+ ):
+ rv = find_executable(program)
+ assert rv == filename
+
+ @staticmethod
+ def _make_executable(tmp_path, ext):
+ # Give the temporary program a suffix regardless of platform.
+ # It's needed on Windows and not harmful on others.
+ program = tmp_path.joinpath('program').with_suffix(ext)
+ program.write_text("", encoding='utf-8')
+ program.chmod(stat.S_IXUSR)
+ return program
+
+ def test_spawn_missing_exe(self):
+ with pytest.raises(DistutilsExecError) as ctx:
+ spawn(['does-not-exist'])
+ assert "command 'does-not-exist' failed" in str(ctx.value)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_sysconfig.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_sysconfig.py
new file mode 100644
index 0000000..43d77c2
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_sysconfig.py
@@ -0,0 +1,319 @@
+"""Tests for distutils.sysconfig."""
+
+import contextlib
+import distutils
+import os
+import pathlib
+import subprocess
+import sys
+from distutils import sysconfig
+from distutils.ccompiler import new_compiler # noqa: F401
+from distutils.unixccompiler import UnixCCompiler
+
+import jaraco.envs
+import path
+import pytest
+from jaraco.text import trim
+from test.support import swap_item
+
+
+def _gen_makefile(root, contents):
+ jaraco.path.build({'Makefile': trim(contents)}, root)
+ return root / 'Makefile'
+
+
+@pytest.mark.usefixtures('save_env')
+class TestSysconfig:
+ def test_get_config_h_filename(self):
+ config_h = sysconfig.get_config_h_filename()
+ assert os.path.isfile(config_h)
+
+ @pytest.mark.skipif("platform.system() == 'Windows'")
+ @pytest.mark.skipif("sys.implementation.name != 'cpython'")
+ def test_get_makefile_filename(self):
+ makefile = sysconfig.get_makefile_filename()
+ assert os.path.isfile(makefile)
+
+ def test_get_python_lib(self, tmp_path):
+ assert sysconfig.get_python_lib() != sysconfig.get_python_lib(prefix=tmp_path)
+
+ def test_get_config_vars(self):
+ cvars = sysconfig.get_config_vars()
+ assert isinstance(cvars, dict)
+ assert cvars
+
+ @pytest.mark.skipif('sysconfig.IS_PYPY')
+ @pytest.mark.skipif('sysconfig.python_build')
+ @pytest.mark.xfail('platform.system() == "Windows"')
+ def test_srcdir_simple(self):
+ # See #15364.
+ srcdir = pathlib.Path(sysconfig.get_config_var('srcdir'))
+
+ assert srcdir.absolute()
+ assert srcdir.is_dir()
+
+ makefile = pathlib.Path(sysconfig.get_makefile_filename())
+ assert makefile.parent.samefile(srcdir)
+
+ @pytest.mark.skipif('sysconfig.IS_PYPY')
+ @pytest.mark.skipif('not sysconfig.python_build')
+ def test_srcdir_python_build(self):
+ # See #15364.
+ srcdir = pathlib.Path(sysconfig.get_config_var('srcdir'))
+
+ # The python executable has not been installed so srcdir
+ # should be a full source checkout.
+ Python_h = srcdir.joinpath('Include', 'Python.h')
+ assert Python_h.is_file()
+ assert sysconfig._is_python_source_dir(srcdir)
+ assert sysconfig._is_python_source_dir(str(srcdir))
+
+ def test_srcdir_independent_of_cwd(self):
+ """
+ srcdir should be independent of the current working directory
+ """
+ # See #15364.
+ srcdir = sysconfig.get_config_var('srcdir')
+ with path.Path('..'):
+ srcdir2 = sysconfig.get_config_var('srcdir')
+ assert srcdir == srcdir2
+
+ def customize_compiler(self):
+ # make sure AR gets caught
+ class compiler:
+ compiler_type = 'unix'
+ executables = UnixCCompiler.executables
+
+ def __init__(self):
+ self.exes = {}
+
+ def set_executables(self, **kw):
+ for k, v in kw.items():
+ self.exes[k] = v
+
+ sysconfig_vars = {
+ 'AR': 'sc_ar',
+ 'CC': 'sc_cc',
+ 'CXX': 'sc_cxx',
+ 'ARFLAGS': '--sc-arflags',
+ 'CFLAGS': '--sc-cflags',
+ 'CCSHARED': '--sc-ccshared',
+ 'LDSHARED': 'sc_ldshared',
+ 'SHLIB_SUFFIX': 'sc_shutil_suffix',
+ }
+
+ comp = compiler()
+ with contextlib.ExitStack() as cm:
+ for key, value in sysconfig_vars.items():
+ cm.enter_context(swap_item(sysconfig._config_vars, key, value))
+ sysconfig.customize_compiler(comp)
+
+ return comp
+
+ @pytest.mark.skipif("not isinstance(new_compiler(), UnixCCompiler)")
+ @pytest.mark.usefixtures('disable_macos_customization')
+ def test_customize_compiler(self):
+ # Make sure that sysconfig._config_vars is initialized
+ sysconfig.get_config_vars()
+
+ os.environ['AR'] = 'env_ar'
+ os.environ['CC'] = 'env_cc'
+ os.environ['CPP'] = 'env_cpp'
+ os.environ['CXX'] = 'env_cxx --env-cxx-flags'
+ os.environ['LDSHARED'] = 'env_ldshared'
+ os.environ['LDFLAGS'] = '--env-ldflags'
+ os.environ['ARFLAGS'] = '--env-arflags'
+ os.environ['CFLAGS'] = '--env-cflags'
+ os.environ['CPPFLAGS'] = '--env-cppflags'
+ os.environ['RANLIB'] = 'env_ranlib'
+
+ comp = self.customize_compiler()
+ assert comp.exes['archiver'] == 'env_ar --env-arflags'
+ assert comp.exes['preprocessor'] == 'env_cpp --env-cppflags'
+ assert comp.exes['compiler'] == 'env_cc --env-cflags --env-cppflags'
+ assert comp.exes['compiler_so'] == (
+ 'env_cc --env-cflags --env-cppflags --sc-ccshared'
+ )
+ assert (
+ comp.exes['compiler_cxx']
+ == 'env_cxx --env-cxx-flags --sc-cflags --env-cppflags'
+ )
+ assert comp.exes['linker_exe'] == 'env_cc'
+ assert comp.exes['linker_so'] == (
+ 'env_ldshared --env-ldflags --env-cflags --env-cppflags'
+ )
+ assert comp.shared_lib_extension == 'sc_shutil_suffix'
+
+ if sys.platform == "darwin":
+ assert comp.exes['ranlib'] == 'env_ranlib'
+ else:
+ assert 'ranlib' not in comp.exes
+
+ del os.environ['AR']
+ del os.environ['CC']
+ del os.environ['CPP']
+ del os.environ['CXX']
+ del os.environ['LDSHARED']
+ del os.environ['LDFLAGS']
+ del os.environ['ARFLAGS']
+ del os.environ['CFLAGS']
+ del os.environ['CPPFLAGS']
+ del os.environ['RANLIB']
+
+ comp = self.customize_compiler()
+ assert comp.exes['archiver'] == 'sc_ar --sc-arflags'
+ assert comp.exes['preprocessor'] == 'sc_cc -E'
+ assert comp.exes['compiler'] == 'sc_cc --sc-cflags'
+ assert comp.exes['compiler_so'] == 'sc_cc --sc-cflags --sc-ccshared'
+ assert comp.exes['compiler_cxx'] == 'sc_cxx --sc-cflags'
+ assert comp.exes['linker_exe'] == 'sc_cc'
+ assert comp.exes['linker_so'] == 'sc_ldshared'
+ assert comp.shared_lib_extension == 'sc_shutil_suffix'
+ assert 'ranlib' not in comp.exes
+
+ def test_parse_makefile_base(self, tmp_path):
+ makefile = _gen_makefile(
+ tmp_path,
+ """
+ CONFIG_ARGS= '--arg1=optarg1' 'ENV=LIB'
+ VAR=$OTHER
+ OTHER=foo
+ """,
+ )
+ d = sysconfig.parse_makefile(makefile)
+ assert d == {'CONFIG_ARGS': "'--arg1=optarg1' 'ENV=LIB'", 'OTHER': 'foo'}
+
+ def test_parse_makefile_literal_dollar(self, tmp_path):
+ makefile = _gen_makefile(
+ tmp_path,
+ """
+ CONFIG_ARGS= '--arg1=optarg1' 'ENV=\\$$LIB'
+ VAR=$OTHER
+ OTHER=foo
+ """,
+ )
+ d = sysconfig.parse_makefile(makefile)
+ assert d == {'CONFIG_ARGS': r"'--arg1=optarg1' 'ENV=\$LIB'", 'OTHER': 'foo'}
+
+ def test_sysconfig_module(self):
+ import sysconfig as global_sysconfig
+
+ assert global_sysconfig.get_config_var('CFLAGS') == sysconfig.get_config_var(
+ 'CFLAGS'
+ )
+ assert global_sysconfig.get_config_var('LDFLAGS') == sysconfig.get_config_var(
+ 'LDFLAGS'
+ )
+
+ # On macOS, binary installers support extension module building on
+ # various levels of the operating system with differing Xcode
+ # configurations, requiring customization of some of the
+ # compiler configuration directives to suit the environment on
+ # the installed machine. Some of these customizations may require
+ # running external programs and are thus deferred until needed by
+ # the first extension module build. Only
+ # the Distutils version of sysconfig is used for extension module
+ # builds, which happens earlier in the Distutils tests. This may
+ # cause the following tests to fail since no tests have caused
+ # the global version of sysconfig to call the customization yet.
+ # The solution for now is to simply skip this test in this case.
+ # The longer-term solution is to only have one version of sysconfig.
+ @pytest.mark.skipif("sysconfig.get_config_var('CUSTOMIZED_OSX_COMPILER')")
+ def test_sysconfig_compiler_vars(self):
+ import sysconfig as global_sysconfig
+
+ if sysconfig.get_config_var('CUSTOMIZED_OSX_COMPILER'):
+ pytest.skip('compiler flags customized')
+ assert global_sysconfig.get_config_var('LDSHARED') == sysconfig.get_config_var(
+ 'LDSHARED'
+ )
+ assert global_sysconfig.get_config_var('CC') == sysconfig.get_config_var('CC')
+
+ @pytest.mark.skipif("not sysconfig.get_config_var('EXT_SUFFIX')")
+ def test_SO_deprecation(self):
+ with pytest.warns(DeprecationWarning):
+ sysconfig.get_config_var('SO')
+
+ def test_customize_compiler_before_get_config_vars(self, tmp_path):
+ # Issue #21923: test that a Distribution compiler
+ # instance can be called without an explicit call to
+ # get_config_vars().
+ jaraco.path.build(
+ {
+ 'file': trim("""
+ from distutils.core import Distribution
+ config = Distribution().get_command_obj('config')
+ # try_compile may pass or it may fail if no compiler
+ # is found but it should not raise an exception.
+ rc = config.try_compile('int x;')
+ """)
+ },
+ tmp_path,
+ )
+ p = subprocess.Popen(
+ [sys.executable, tmp_path / 'file'],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ universal_newlines=True,
+ encoding='utf-8',
+ )
+ outs, errs = p.communicate()
+ assert 0 == p.returncode, "Subprocess failed: " + outs
+
+ def test_parse_config_h(self):
+ config_h = sysconfig.get_config_h_filename()
+ input = {}
+ with open(config_h, encoding="utf-8") as f:
+ result = sysconfig.parse_config_h(f, g=input)
+ assert input is result
+ with open(config_h, encoding="utf-8") as f:
+ result = sysconfig.parse_config_h(f)
+ assert isinstance(result, dict)
+
+ @pytest.mark.skipif("platform.system() != 'Windows'")
+ @pytest.mark.skipif("sys.implementation.name != 'cpython'")
+ def test_win_ext_suffix(self):
+ assert sysconfig.get_config_var("EXT_SUFFIX").endswith(".pyd")
+ assert sysconfig.get_config_var("EXT_SUFFIX") != ".pyd"
+
+ @pytest.mark.skipif("platform.system() != 'Windows'")
+ @pytest.mark.skipif("sys.implementation.name != 'cpython'")
+ @pytest.mark.skipif(
+ '\\PCbuild\\'.casefold() not in sys.executable.casefold(),
+ reason='Need sys.executable to be in a source tree',
+ )
+ def test_win_build_venv_from_source_tree(self, tmp_path):
+ """Ensure distutils.sysconfig detects venvs from source tree builds."""
+ env = jaraco.envs.VEnv()
+ env.create_opts = env.clean_opts
+ env.root = tmp_path
+ env.ensure_env()
+ cmd = [
+ env.exe(),
+ "-c",
+ "import distutils.sysconfig; print(distutils.sysconfig.python_build)",
+ ]
+ distutils_path = os.path.dirname(os.path.dirname(distutils.__file__))
+ out = subprocess.check_output(
+ cmd, env={**os.environ, "PYTHONPATH": distutils_path}
+ )
+ assert out == "True"
+
+ def test_get_python_inc_missing_config_dir(self, monkeypatch):
+ """
+ In portable Python installations, the sysconfig will be broken,
+ pointing to the directories where the installation was built and
+ not where it currently is. In this case, ensure that the missing
+ directory isn't used for get_python_inc.
+
+ See pypa/distutils#178.
+ """
+
+ def override(name):
+ if name == 'INCLUDEPY':
+ return '/does-not-exist'
+ return sysconfig.get_config_var(name)
+
+ monkeypatch.setattr(sysconfig, 'get_config_var', override)
+
+ assert os.path.exists(sysconfig.get_python_inc())
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_text_file.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_text_file.py
new file mode 100644
index 0000000..f511156
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_text_file.py
@@ -0,0 +1,127 @@
+"""Tests for distutils.text_file."""
+
+from distutils.tests import support
+from distutils.text_file import TextFile
+
+import jaraco.path
+import path
+
+TEST_DATA = """# test file
+
+line 3 \\
+# intervening comment
+ continues on next line
+"""
+
+
+class TestTextFile(support.TempdirManager):
+ def test_class(self):
+ # old tests moved from text_file.__main__
+ # so they are really called by the buildbots
+
+ # result 1: no fancy options
+ result1 = [
+ '# test file\n',
+ '\n',
+ 'line 3 \\\n',
+ '# intervening comment\n',
+ ' continues on next line\n',
+ ]
+
+ # result 2: just strip comments
+ result2 = ["\n", "line 3 \\\n", " continues on next line\n"]
+
+ # result 3: just strip blank lines
+ result3 = [
+ "# test file\n",
+ "line 3 \\\n",
+ "# intervening comment\n",
+ " continues on next line\n",
+ ]
+
+ # result 4: default, strip comments, blank lines,
+ # and trailing whitespace
+ result4 = ["line 3 \\", " continues on next line"]
+
+ # result 5: strip comments and blanks, plus join lines (but don't
+ # "collapse" joined lines
+ result5 = ["line 3 continues on next line"]
+
+ # result 6: strip comments and blanks, plus join lines (and
+ # "collapse" joined lines
+ result6 = ["line 3 continues on next line"]
+
+ def test_input(count, description, file, expected_result):
+ result = file.readlines()
+ assert result == expected_result
+
+ tmp_path = path.Path(self.mkdtemp())
+ filename = tmp_path / 'test.txt'
+ jaraco.path.build({filename.name: TEST_DATA}, tmp_path)
+
+ in_file = TextFile(
+ filename,
+ strip_comments=False,
+ skip_blanks=False,
+ lstrip_ws=False,
+ rstrip_ws=False,
+ )
+ try:
+ test_input(1, "no processing", in_file, result1)
+ finally:
+ in_file.close()
+
+ in_file = TextFile(
+ filename,
+ strip_comments=True,
+ skip_blanks=False,
+ lstrip_ws=False,
+ rstrip_ws=False,
+ )
+ try:
+ test_input(2, "strip comments", in_file, result2)
+ finally:
+ in_file.close()
+
+ in_file = TextFile(
+ filename,
+ strip_comments=False,
+ skip_blanks=True,
+ lstrip_ws=False,
+ rstrip_ws=False,
+ )
+ try:
+ test_input(3, "strip blanks", in_file, result3)
+ finally:
+ in_file.close()
+
+ in_file = TextFile(filename)
+ try:
+ test_input(4, "default processing", in_file, result4)
+ finally:
+ in_file.close()
+
+ in_file = TextFile(
+ filename,
+ strip_comments=True,
+ skip_blanks=True,
+ join_lines=True,
+ rstrip_ws=True,
+ )
+ try:
+ test_input(5, "join lines without collapsing", in_file, result5)
+ finally:
+ in_file.close()
+
+ in_file = TextFile(
+ filename,
+ strip_comments=True,
+ skip_blanks=True,
+ join_lines=True,
+ rstrip_ws=True,
+ collapse_join=True,
+ )
+ try:
+ test_input(6, "join lines with collapsing", in_file, result6)
+ finally:
+ in_file.close()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_util.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_util.py
new file mode 100644
index 0000000..00c9743
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_util.py
@@ -0,0 +1,243 @@
+"""Tests for distutils.util."""
+
+import email
+import email.generator
+import email.policy
+import io
+import os
+import pathlib
+import sys
+import sysconfig as stdlib_sysconfig
+import unittest.mock as mock
+from copy import copy
+from distutils import sysconfig, util
+from distutils.errors import DistutilsByteCompileError, DistutilsPlatformError
+from distutils.util import (
+ byte_compile,
+ change_root,
+ check_environ,
+ convert_path,
+ get_host_platform,
+ get_platform,
+ grok_environment_error,
+ rfc822_escape,
+ split_quoted,
+ strtobool,
+)
+
+import pytest
+
+
+@pytest.fixture(autouse=True)
+def environment(monkeypatch):
+ monkeypatch.setattr(os, 'name', os.name)
+ monkeypatch.setattr(sys, 'platform', sys.platform)
+ monkeypatch.setattr(sys, 'version', sys.version)
+ monkeypatch.setattr(os, 'sep', os.sep)
+ monkeypatch.setattr(os.path, 'join', os.path.join)
+ monkeypatch.setattr(os.path, 'isabs', os.path.isabs)
+ monkeypatch.setattr(os.path, 'splitdrive', os.path.splitdrive)
+ monkeypatch.setattr(sysconfig, '_config_vars', copy(sysconfig._config_vars))
+
+
+@pytest.mark.usefixtures('save_env')
+class TestUtil:
+ def test_get_host_platform(self):
+ with mock.patch('os.name', 'nt'):
+ with mock.patch('sys.version', '... [... (ARM64)]'):
+ assert get_host_platform() == 'win-arm64'
+ with mock.patch('sys.version', '... [... (ARM)]'):
+ assert get_host_platform() == 'win-arm32'
+
+ with mock.patch('sys.version_info', (3, 9, 0, 'final', 0)):
+ assert get_host_platform() == stdlib_sysconfig.get_platform()
+
+ def test_get_platform(self):
+ with mock.patch('os.name', 'nt'):
+ with mock.patch.dict('os.environ', {'VSCMD_ARG_TGT_ARCH': 'x86'}):
+ assert get_platform() == 'win32'
+ with mock.patch.dict('os.environ', {'VSCMD_ARG_TGT_ARCH': 'x64'}):
+ assert get_platform() == 'win-amd64'
+ with mock.patch.dict('os.environ', {'VSCMD_ARG_TGT_ARCH': 'arm'}):
+ assert get_platform() == 'win-arm32'
+ with mock.patch.dict('os.environ', {'VSCMD_ARG_TGT_ARCH': 'arm64'}):
+ assert get_platform() == 'win-arm64'
+
+ def test_convert_path(self):
+ expected = os.sep.join(('', 'home', 'to', 'my', 'stuff'))
+ assert convert_path('/home/to/my/stuff') == expected
+ assert convert_path(pathlib.Path('/home/to/my/stuff')) == expected
+ assert convert_path('.') == os.curdir
+
+ def test_change_root(self):
+ # linux/mac
+ os.name = 'posix'
+
+ def _isabs(path):
+ return path[0] == '/'
+
+ os.path.isabs = _isabs
+
+ def _join(*path):
+ return '/'.join(path)
+
+ os.path.join = _join
+
+ assert change_root('/root', '/old/its/here') == '/root/old/its/here'
+ assert change_root('/root', 'its/here') == '/root/its/here'
+
+ # windows
+ os.name = 'nt'
+ os.sep = '\\'
+
+ def _isabs(path):
+ return path.startswith('c:\\')
+
+ os.path.isabs = _isabs
+
+ def _splitdrive(path):
+ if path.startswith('c:'):
+ return ('', path.replace('c:', ''))
+ return ('', path)
+
+ os.path.splitdrive = _splitdrive
+
+ def _join(*path):
+ return '\\'.join(path)
+
+ os.path.join = _join
+
+ assert (
+ change_root('c:\\root', 'c:\\old\\its\\here') == 'c:\\root\\old\\its\\here'
+ )
+ assert change_root('c:\\root', 'its\\here') == 'c:\\root\\its\\here'
+
+ # BugsBunny os (it's a great os)
+ os.name = 'BugsBunny'
+ with pytest.raises(DistutilsPlatformError):
+ change_root('c:\\root', 'its\\here')
+
+ # XXX platforms to be covered: mac
+
+ def test_check_environ(self):
+ util.check_environ.cache_clear()
+ os.environ.pop('HOME', None)
+
+ check_environ()
+
+ assert os.environ['PLAT'] == get_platform()
+
+ @pytest.mark.skipif("os.name != 'posix'")
+ def test_check_environ_getpwuid(self):
+ util.check_environ.cache_clear()
+ os.environ.pop('HOME', None)
+
+ import pwd
+
+ # only set pw_dir field, other fields are not used
+ result = pwd.struct_passwd((
+ None,
+ None,
+ None,
+ None,
+ None,
+ '/home/distutils',
+ None,
+ ))
+ with mock.patch.object(pwd, 'getpwuid', return_value=result):
+ check_environ()
+ assert os.environ['HOME'] == '/home/distutils'
+
+ util.check_environ.cache_clear()
+ os.environ.pop('HOME', None)
+
+ # bpo-10496: Catch pwd.getpwuid() error
+ with mock.patch.object(pwd, 'getpwuid', side_effect=KeyError):
+ check_environ()
+ assert 'HOME' not in os.environ
+
+ def test_split_quoted(self):
+ assert split_quoted('""one"" "two" \'three\' \\four') == [
+ 'one',
+ 'two',
+ 'three',
+ 'four',
+ ]
+
+ def test_strtobool(self):
+ yes = ('y', 'Y', 'yes', 'True', 't', 'true', 'True', 'On', 'on', '1')
+ no = ('n', 'no', 'f', 'false', 'off', '0', 'Off', 'No', 'N')
+
+ for y in yes:
+ assert strtobool(y)
+
+ for n in no:
+ assert not strtobool(n)
+
+ indent = 8 * ' '
+
+ @pytest.mark.parametrize(
+ "given,wanted",
+ [
+ # 0x0b, 0x0c, ..., etc are also considered a line break by Python
+ ("hello\x0b\nworld\n", f"hello\x0b{indent}\n{indent}world\n{indent}"),
+ ("hello\x1eworld", f"hello\x1e{indent}world"),
+ ("", ""),
+ (
+ "I am a\npoor\nlonesome\nheader\n",
+ f"I am a\n{indent}poor\n{indent}lonesome\n{indent}header\n{indent}",
+ ),
+ ],
+ )
+ def test_rfc822_escape(self, given, wanted):
+ """
+ We want to ensure a multi-line header parses correctly.
+
+ For interoperability, the escaped value should also "round-trip" over
+ `email.generator.Generator.flatten` and `email.message_from_*`
+ (see pypa/setuptools#4033).
+
+ The main issue is that internally `email.policy.EmailPolicy` uses
+ `splitlines` which will split on some control chars. If all the new lines
+ are not prefixed with spaces, the parser will interrupt reading
+ the current header and produce an incomplete value, while
+ incorrectly interpreting the rest of the headers as part of the payload.
+ """
+ res = rfc822_escape(given)
+
+ policy = email.policy.EmailPolicy(
+ utf8=True,
+ mangle_from_=False,
+ max_line_length=0,
+ )
+ with io.StringIO() as buffer:
+ raw = f"header: {res}\nother-header: 42\n\npayload\n"
+ orig = email.message_from_string(raw)
+ email.generator.Generator(buffer, policy=policy).flatten(orig)
+ buffer.seek(0)
+ regen = email.message_from_file(buffer)
+
+ for msg in (orig, regen):
+ assert msg.get_payload() == "payload\n"
+ assert msg["other-header"] == "42"
+ # Generator may replace control chars with `\n`
+ assert set(msg["header"].splitlines()) == set(res.splitlines())
+
+ assert res == wanted
+
+ def test_dont_write_bytecode(self):
+ # makes sure byte_compile raise a DistutilsError
+ # if sys.dont_write_bytecode is True
+ old_dont_write_bytecode = sys.dont_write_bytecode
+ sys.dont_write_bytecode = True
+ try:
+ with pytest.raises(DistutilsByteCompileError):
+ byte_compile([])
+ finally:
+ sys.dont_write_bytecode = old_dont_write_bytecode
+
+ def test_grok_environment_error(self):
+ # test obsolete function to ensure backward compat (#4931)
+ exc = OSError("Unable to find batch file")
+ msg = grok_environment_error(exc)
+ assert msg == "error: Unable to find batch file"
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_version.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_version.py
new file mode 100644
index 0000000..b68f097
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_version.py
@@ -0,0 +1,80 @@
+"""Tests for distutils.version."""
+
+import distutils
+from distutils.version import LooseVersion, StrictVersion
+
+import pytest
+
+
+@pytest.fixture(autouse=True)
+def suppress_deprecation():
+ with distutils.version.suppress_known_deprecation():
+ yield
+
+
+class TestVersion:
+ def test_prerelease(self):
+ version = StrictVersion('1.2.3a1')
+ assert version.version == (1, 2, 3)
+ assert version.prerelease == ('a', 1)
+ assert str(version) == '1.2.3a1'
+
+ version = StrictVersion('1.2.0')
+ assert str(version) == '1.2'
+
+ def test_cmp_strict(self):
+ versions = (
+ ('1.5.1', '1.5.2b2', -1),
+ ('161', '3.10a', ValueError),
+ ('8.02', '8.02', 0),
+ ('3.4j', '1996.07.12', ValueError),
+ ('3.2.pl0', '3.1.1.6', ValueError),
+ ('2g6', '11g', ValueError),
+ ('0.9', '2.2', -1),
+ ('1.2.1', '1.2', 1),
+ ('1.1', '1.2.2', -1),
+ ('1.2', '1.1', 1),
+ ('1.2.1', '1.2.2', -1),
+ ('1.2.2', '1.2', 1),
+ ('1.2', '1.2.2', -1),
+ ('0.4.0', '0.4', 0),
+ ('1.13++', '5.5.kw', ValueError),
+ )
+
+ for v1, v2, wanted in versions:
+ try:
+ res = StrictVersion(v1)._cmp(StrictVersion(v2))
+ except ValueError:
+ if wanted is ValueError:
+ continue
+ else:
+ raise AssertionError(f"cmp({v1}, {v2}) shouldn't raise ValueError")
+ assert res == wanted, f'cmp({v1}, {v2}) should be {wanted}, got {res}'
+ res = StrictVersion(v1)._cmp(v2)
+ assert res == wanted, f'cmp({v1}, {v2}) should be {wanted}, got {res}'
+ res = StrictVersion(v1)._cmp(object())
+ assert res is NotImplemented, (
+ f'cmp({v1}, {v2}) should be NotImplemented, got {res}'
+ )
+
+ def test_cmp(self):
+ versions = (
+ ('1.5.1', '1.5.2b2', -1),
+ ('161', '3.10a', 1),
+ ('8.02', '8.02', 0),
+ ('3.4j', '1996.07.12', -1),
+ ('3.2.pl0', '3.1.1.6', 1),
+ ('2g6', '11g', -1),
+ ('0.960923', '2.2beta29', -1),
+ ('1.13++', '5.5.kw', -1),
+ )
+
+ for v1, v2, wanted in versions:
+ res = LooseVersion(v1)._cmp(LooseVersion(v2))
+ assert res == wanted, f'cmp({v1}, {v2}) should be {wanted}, got {res}'
+ res = LooseVersion(v1)._cmp(v2)
+ assert res == wanted, f'cmp({v1}, {v2}) should be {wanted}, got {res}'
+ res = LooseVersion(v1)._cmp(object())
+ assert res is NotImplemented, (
+ f'cmp({v1}, {v2}) should be NotImplemented, got {res}'
+ )
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_versionpredicate.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/test_versionpredicate.py
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/unix_compat.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/unix_compat.py
new file mode 100644
index 0000000..a5d9ee4
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/tests/unix_compat.py
@@ -0,0 +1,17 @@
+import sys
+
+try:
+ import grp
+ import pwd
+except ImportError:
+ grp = pwd = None
+
+import pytest
+
+UNIX_ID_SUPPORT = grp and pwd
+UID_0_SUPPORT = UNIX_ID_SUPPORT and sys.platform != "cygwin"
+
+require_unix_id = pytest.mark.skipif(
+ not UNIX_ID_SUPPORT, reason="Requires grp and pwd support"
+)
+require_uid_0 = pytest.mark.skipif(not UID_0_SUPPORT, reason="Requires UID 0 support")
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/text_file.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/text_file.py
new file mode 100644
index 0000000..89d9048
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/text_file.py
@@ -0,0 +1,286 @@
+"""text_file
+
+provides the TextFile class, which gives an interface to text files
+that (optionally) takes care of stripping comments, ignoring blank
+lines, and joining lines with backslashes."""
+
+import sys
+
+
+class TextFile:
+ """Provides a file-like object that takes care of all the things you
+ commonly want to do when processing a text file that has some
+ line-by-line syntax: strip comments (as long as "#" is your
+ comment character), skip blank lines, join adjacent lines by
+ escaping the newline (ie. backslash at end of line), strip
+ leading and/or trailing whitespace. All of these are optional
+ and independently controllable.
+
+ Provides a 'warn()' method so you can generate warning messages that
+ report physical line number, even if the logical line in question
+ spans multiple physical lines. Also provides 'unreadline()' for
+ implementing line-at-a-time lookahead.
+
+ Constructor is called as:
+
+ TextFile (filename=None, file=None, **options)
+
+ It bombs (RuntimeError) if both 'filename' and 'file' are None;
+ 'filename' should be a string, and 'file' a file object (or
+ something that provides 'readline()' and 'close()' methods). It is
+ recommended that you supply at least 'filename', so that TextFile
+ can include it in warning messages. If 'file' is not supplied,
+ TextFile creates its own using 'io.open()'.
+
+ The options are all boolean, and affect the value returned by
+ 'readline()':
+ strip_comments [default: true]
+ strip from "#" to end-of-line, as well as any whitespace
+ leading up to the "#" -- unless it is escaped by a backslash
+ lstrip_ws [default: false]
+ strip leading whitespace from each line before returning it
+ rstrip_ws [default: true]
+ strip trailing whitespace (including line terminator!) from
+ each line before returning it
+ skip_blanks [default: true}
+ skip lines that are empty *after* stripping comments and
+ whitespace. (If both lstrip_ws and rstrip_ws are false,
+ then some lines may consist of solely whitespace: these will
+ *not* be skipped, even if 'skip_blanks' is true.)
+ join_lines [default: false]
+ if a backslash is the last non-newline character on a line
+ after stripping comments and whitespace, join the following line
+ to it to form one "logical line"; if N consecutive lines end
+ with a backslash, then N+1 physical lines will be joined to
+ form one logical line.
+ collapse_join [default: false]
+ strip leading whitespace from lines that are joined to their
+ predecessor; only matters if (join_lines and not lstrip_ws)
+ errors [default: 'strict']
+ error handler used to decode the file content
+
+ Note that since 'rstrip_ws' can strip the trailing newline, the
+ semantics of 'readline()' must differ from those of the builtin file
+ object's 'readline()' method! In particular, 'readline()' returns
+ None for end-of-file: an empty string might just be a blank line (or
+ an all-whitespace line), if 'rstrip_ws' is true but 'skip_blanks' is
+ not."""
+
+ default_options = {
+ 'strip_comments': 1,
+ 'skip_blanks': 1,
+ 'lstrip_ws': 0,
+ 'rstrip_ws': 1,
+ 'join_lines': 0,
+ 'collapse_join': 0,
+ 'errors': 'strict',
+ }
+
+ def __init__(self, filename=None, file=None, **options):
+ """Construct a new TextFile object. At least one of 'filename'
+ (a string) and 'file' (a file-like object) must be supplied.
+ They keyword argument options are described above and affect
+ the values returned by 'readline()'."""
+ if filename is None and file is None:
+ raise RuntimeError(
+ "you must supply either or both of 'filename' and 'file'"
+ )
+
+ # set values for all options -- either from client option hash
+ # or fallback to default_options
+ for opt in self.default_options.keys():
+ if opt in options:
+ setattr(self, opt, options[opt])
+ else:
+ setattr(self, opt, self.default_options[opt])
+
+ # sanity check client option hash
+ for opt in options.keys():
+ if opt not in self.default_options:
+ raise KeyError(f"invalid TextFile option '{opt}'")
+
+ if file is None:
+ self.open(filename)
+ else:
+ self.filename = filename
+ self.file = file
+ self.current_line = 0 # assuming that file is at BOF!
+
+ # 'linebuf' is a stack of lines that will be emptied before we
+ # actually read from the file; it's only populated by an
+ # 'unreadline()' operation
+ self.linebuf = []
+
+ def open(self, filename):
+ """Open a new file named 'filename'. This overrides both the
+ 'filename' and 'file' arguments to the constructor."""
+ self.filename = filename
+ self.file = open(self.filename, errors=self.errors, encoding='utf-8')
+ self.current_line = 0
+
+ def close(self):
+ """Close the current file and forget everything we know about it
+ (filename, current line number)."""
+ file = self.file
+ self.file = None
+ self.filename = None
+ self.current_line = None
+ file.close()
+
+ def gen_error(self, msg, line=None):
+ outmsg = []
+ if line is None:
+ line = self.current_line
+ outmsg.append(self.filename + ", ")
+ if isinstance(line, (list, tuple)):
+ outmsg.append("lines {}-{}: ".format(*line))
+ else:
+ outmsg.append(f"line {int(line)}: ")
+ outmsg.append(str(msg))
+ return "".join(outmsg)
+
+ def error(self, msg, line=None):
+ raise ValueError("error: " + self.gen_error(msg, line))
+
+ def warn(self, msg, line=None):
+ """Print (to stderr) a warning message tied to the current logical
+ line in the current file. If the current logical line in the
+ file spans multiple physical lines, the warning refers to the
+ whole range, eg. "lines 3-5". If 'line' supplied, it overrides
+ the current line number; it may be a list or tuple to indicate a
+ range of physical lines, or an integer for a single physical
+ line."""
+ sys.stderr.write("warning: " + self.gen_error(msg, line) + "\n")
+
+ def readline(self): # noqa: C901
+ """Read and return a single logical line from the current file (or
+ from an internal buffer if lines have previously been "unread"
+ with 'unreadline()'). If the 'join_lines' option is true, this
+ may involve reading multiple physical lines concatenated into a
+ single string. Updates the current line number, so calling
+ 'warn()' after 'readline()' emits a warning about the physical
+ line(s) just read. Returns None on end-of-file, since the empty
+ string can occur if 'rstrip_ws' is true but 'strip_blanks' is
+ not."""
+ # If any "unread" lines waiting in 'linebuf', return the top
+ # one. (We don't actually buffer read-ahead data -- lines only
+ # get put in 'linebuf' if the client explicitly does an
+ # 'unreadline()'.
+ if self.linebuf:
+ line = self.linebuf[-1]
+ del self.linebuf[-1]
+ return line
+
+ buildup_line = ''
+
+ while True:
+ # read the line, make it None if EOF
+ line = self.file.readline()
+ if line == '':
+ line = None
+
+ if self.strip_comments and line:
+ # Look for the first "#" in the line. If none, never
+ # mind. If we find one and it's the first character, or
+ # is not preceded by "\", then it starts a comment --
+ # strip the comment, strip whitespace before it, and
+ # carry on. Otherwise, it's just an escaped "#", so
+ # unescape it (and any other escaped "#"'s that might be
+ # lurking in there) and otherwise leave the line alone.
+
+ pos = line.find("#")
+ if pos == -1: # no "#" -- no comments
+ pass
+
+ # It's definitely a comment -- either "#" is the first
+ # character, or it's elsewhere and unescaped.
+ elif pos == 0 or line[pos - 1] != "\\":
+ # Have to preserve the trailing newline, because it's
+ # the job of a later step (rstrip_ws) to remove it --
+ # and if rstrip_ws is false, we'd better preserve it!
+ # (NB. this means that if the final line is all comment
+ # and has no trailing newline, we will think that it's
+ # EOF; I think that's OK.)
+ eol = (line[-1] == '\n') and '\n' or ''
+ line = line[0:pos] + eol
+
+ # If all that's left is whitespace, then skip line
+ # *now*, before we try to join it to 'buildup_line' --
+ # that way constructs like
+ # hello \\
+ # # comment that should be ignored
+ # there
+ # result in "hello there".
+ if line.strip() == "":
+ continue
+ else: # it's an escaped "#"
+ line = line.replace("\\#", "#")
+
+ # did previous line end with a backslash? then accumulate
+ if self.join_lines and buildup_line:
+ # oops: end of file
+ if line is None:
+ self.warn("continuation line immediately precedes end-of-file")
+ return buildup_line
+
+ if self.collapse_join:
+ line = line.lstrip()
+ line = buildup_line + line
+
+ # careful: pay attention to line number when incrementing it
+ if isinstance(self.current_line, list):
+ self.current_line[1] = self.current_line[1] + 1
+ else:
+ self.current_line = [self.current_line, self.current_line + 1]
+ # just an ordinary line, read it as usual
+ else:
+ if line is None: # eof
+ return None
+
+ # still have to be careful about incrementing the line number!
+ if isinstance(self.current_line, list):
+ self.current_line = self.current_line[1] + 1
+ else:
+ self.current_line = self.current_line + 1
+
+ # strip whitespace however the client wants (leading and
+ # trailing, or one or the other, or neither)
+ if self.lstrip_ws and self.rstrip_ws:
+ line = line.strip()
+ elif self.lstrip_ws:
+ line = line.lstrip()
+ elif self.rstrip_ws:
+ line = line.rstrip()
+
+ # blank line (whether we rstrip'ed or not)? skip to next line
+ # if appropriate
+ if line in ('', '\n') and self.skip_blanks:
+ continue
+
+ if self.join_lines:
+ if line[-1] == '\\':
+ buildup_line = line[:-1]
+ continue
+
+ if line[-2:] == '\\\n':
+ buildup_line = line[0:-2] + '\n'
+ continue
+
+ # well, I guess there's some actual content there: return it
+ return line
+
+ def readlines(self):
+ """Read and return the list of all logical lines remaining in the
+ current file."""
+ lines = []
+ while True:
+ line = self.readline()
+ if line is None:
+ return lines
+ lines.append(line)
+
+ def unreadline(self, line):
+ """Push 'line' (a string) onto an internal buffer that will be
+ checked by future 'readline()' calls. Handy for implementing
+ a parser with line-at-a-time lookahead."""
+ self.linebuf.append(line)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/unixccompiler.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/unixccompiler.py
new file mode 100644
index 0000000..20b8ce6
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/unixccompiler.py
@@ -0,0 +1,9 @@
+import importlib
+
+from .compilers.C import unix
+
+UnixCCompiler = unix.Compiler
+
+# ensure import of unixccompiler implies ccompiler imported
+# (pypa/setuptools#4871)
+importlib.import_module('distutils.ccompiler')
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/util.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/util.py
new file mode 100644
index 0000000..6dbe049
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/util.py
@@ -0,0 +1,518 @@
+"""distutils.util
+
+Miscellaneous utility functions -- anything that doesn't fit into
+one of the other *util.py modules.
+"""
+
+from __future__ import annotations
+
+import functools
+import importlib.util
+import os
+import pathlib
+import re
+import string
+import subprocess
+import sys
+import sysconfig
+import tempfile
+from collections.abc import Callable, Iterable, Mapping
+from typing import TYPE_CHECKING, AnyStr
+
+from jaraco.functools import pass_none
+
+from ._log import log
+from ._modified import newer
+from .errors import DistutilsByteCompileError, DistutilsPlatformError
+from .spawn import spawn
+
+if TYPE_CHECKING:
+ from typing_extensions import TypeVarTuple, Unpack
+
+ _Ts = TypeVarTuple("_Ts")
+
+
+def get_host_platform() -> str:
+ """
+ Return a string that identifies the current platform. Use this
+ function to distinguish platform-specific build directories and
+ platform-specific built distributions.
+ """
+
+ # This function initially exposed platforms as defined in Python 3.9
+ # even with older Python versions when distutils was split out.
+ # Now it delegates to stdlib sysconfig.
+
+ return sysconfig.get_platform()
+
+
+def get_platform() -> str:
+ if os.name == 'nt':
+ TARGET_TO_PLAT = {
+ 'x86': 'win32',
+ 'x64': 'win-amd64',
+ 'arm': 'win-arm32',
+ 'arm64': 'win-arm64',
+ }
+ target = os.environ.get('VSCMD_ARG_TGT_ARCH')
+ return TARGET_TO_PLAT.get(target) or get_host_platform()
+ return get_host_platform()
+
+
+if sys.platform == 'darwin':
+ _syscfg_macosx_ver = None # cache the version pulled from sysconfig
+MACOSX_VERSION_VAR = 'MACOSX_DEPLOYMENT_TARGET'
+
+
+def _clear_cached_macosx_ver():
+ """For testing only. Do not call."""
+ global _syscfg_macosx_ver
+ _syscfg_macosx_ver = None
+
+
+def get_macosx_target_ver_from_syscfg():
+ """Get the version of macOS latched in the Python interpreter configuration.
+ Returns the version as a string or None if can't obtain one. Cached."""
+ global _syscfg_macosx_ver
+ if _syscfg_macosx_ver is None:
+ from distutils import sysconfig
+
+ ver = sysconfig.get_config_var(MACOSX_VERSION_VAR) or ''
+ if ver:
+ _syscfg_macosx_ver = ver
+ return _syscfg_macosx_ver
+
+
+def get_macosx_target_ver():
+ """Return the version of macOS for which we are building.
+
+ The target version defaults to the version in sysconfig latched at time
+ the Python interpreter was built, unless overridden by an environment
+ variable. If neither source has a value, then None is returned"""
+
+ syscfg_ver = get_macosx_target_ver_from_syscfg()
+ env_ver = os.environ.get(MACOSX_VERSION_VAR)
+
+ if env_ver:
+ # Validate overridden version against sysconfig version, if have both.
+ # Ensure that the deployment target of the build process is not less
+ # than 10.3 if the interpreter was built for 10.3 or later. This
+ # ensures extension modules are built with correct compatibility
+ # values, specifically LDSHARED which can use
+ # '-undefined dynamic_lookup' which only works on >= 10.3.
+ if (
+ syscfg_ver
+ and split_version(syscfg_ver) >= [10, 3]
+ and split_version(env_ver) < [10, 3]
+ ):
+ my_msg = (
+ '$' + MACOSX_VERSION_VAR + ' mismatch: '
+ f'now "{env_ver}" but "{syscfg_ver}" during configure; '
+ 'must use 10.3 or later'
+ )
+ raise DistutilsPlatformError(my_msg)
+ return env_ver
+ return syscfg_ver
+
+
+def split_version(s: str) -> list[int]:
+ """Convert a dot-separated string into a list of numbers for comparisons"""
+ return [int(n) for n in s.split('.')]
+
+
+@pass_none
+def convert_path(pathname: str | os.PathLike[str]) -> str:
+ r"""
+ Allow for pathlib.Path inputs, coax to a native path string.
+
+ If None is passed, will just pass it through as
+ Setuptools relies on this behavior.
+
+ >>> convert_path(None) is None
+ True
+
+ Removes empty paths.
+
+ >>> convert_path('foo/./bar').replace('\\', '/')
+ 'foo/bar'
+ """
+ return os.fspath(pathlib.PurePath(pathname))
+
+
+def change_root(
+ new_root: AnyStr | os.PathLike[AnyStr], pathname: AnyStr | os.PathLike[AnyStr]
+) -> AnyStr:
+ """Return 'pathname' with 'new_root' prepended. If 'pathname' is
+ relative, this is equivalent to "os.path.join(new_root,pathname)".
+ Otherwise, it requires making 'pathname' relative and then joining the
+ two, which is tricky on DOS/Windows and Mac OS.
+ """
+ if os.name == 'posix':
+ if not os.path.isabs(pathname):
+ return os.path.join(new_root, pathname)
+ else:
+ return os.path.join(new_root, pathname[1:])
+
+ elif os.name == 'nt':
+ (drive, path) = os.path.splitdrive(pathname)
+ if path[0] == os.sep:
+ path = path[1:]
+ return os.path.join(new_root, path)
+
+ raise DistutilsPlatformError(f"nothing known about platform '{os.name}'")
+
+
+@functools.lru_cache
+def check_environ() -> None:
+ """Ensure that 'os.environ' has all the environment variables we
+ guarantee that users can use in config files, command-line options,
+ etc. Currently this includes:
+ HOME - user's home directory (Unix only)
+ PLAT - description of the current platform, including hardware
+ and OS (see 'get_platform()')
+ """
+ if os.name == 'posix' and 'HOME' not in os.environ:
+ try:
+ import pwd
+
+ os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
+ except (ImportError, KeyError):
+ # bpo-10496: if the current user identifier doesn't exist in the
+ # password database, do nothing
+ pass
+
+ if 'PLAT' not in os.environ:
+ os.environ['PLAT'] = get_platform()
+
+
+def subst_vars(s, local_vars: Mapping[str, object]) -> str:
+ """
+ Perform variable substitution on 'string'.
+ Variables are indicated by format-style braces ("{var}").
+ Variable is substituted by the value found in the 'local_vars'
+ dictionary or in 'os.environ' if it's not in 'local_vars'.
+ 'os.environ' is first checked/augmented to guarantee that it contains
+ certain values: see 'check_environ()'. Raise ValueError for any
+ variables not found in either 'local_vars' or 'os.environ'.
+ """
+ check_environ()
+ lookup = dict(os.environ)
+ lookup.update((name, str(value)) for name, value in local_vars.items())
+ try:
+ return _subst_compat(s).format_map(lookup)
+ except KeyError as var:
+ raise ValueError(f"invalid variable {var}")
+
+
+def _subst_compat(s):
+ """
+ Replace shell/Perl-style variable substitution with
+ format-style. For compatibility.
+ """
+
+ def _subst(match):
+ return f'{{{match.group(1)}}}'
+
+ repl = re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)
+ if repl != s:
+ import warnings
+
+ warnings.warn(
+ "shell/Perl-style substitutions are deprecated",
+ DeprecationWarning,
+ )
+ return repl
+
+
+def grok_environment_error(exc: object, prefix: str = "error: ") -> str:
+ # Function kept for backward compatibility.
+ # Used to try clever things with EnvironmentErrors,
+ # but nowadays str(exception) produces good messages.
+ return prefix + str(exc)
+
+
+# Needed by 'split_quoted()'
+_wordchars_re = _squote_re = _dquote_re = None
+
+
+def _init_regex():
+ global _wordchars_re, _squote_re, _dquote_re
+ _wordchars_re = re.compile(rf'[^\\\'\"{string.whitespace} ]*')
+ _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")
+ _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')
+
+
+def split_quoted(s: str) -> list[str]:
+ """Split a string up according to Unix shell-like rules for quotes and
+ backslashes. In short: words are delimited by spaces, as long as those
+ spaces are not escaped by a backslash, or inside a quoted string.
+ Single and double quotes are equivalent, and the quote characters can
+ be backslash-escaped. The backslash is stripped from any two-character
+ escape sequence, leaving only the escaped character. The quote
+ characters are stripped from any quoted string. Returns a list of
+ words.
+ """
+
+ # This is a nice algorithm for splitting up a single string, since it
+ # doesn't require character-by-character examination. It was a little
+ # bit of a brain-bender to get it working right, though...
+ if _wordchars_re is None:
+ _init_regex()
+
+ s = s.strip()
+ words = []
+ pos = 0
+
+ while s:
+ m = _wordchars_re.match(s, pos)
+ end = m.end()
+ if end == len(s):
+ words.append(s[:end])
+ break
+
+ if s[end] in string.whitespace:
+ # unescaped, unquoted whitespace: now
+ # we definitely have a word delimiter
+ words.append(s[:end])
+ s = s[end:].lstrip()
+ pos = 0
+
+ elif s[end] == '\\':
+ # preserve whatever is being escaped;
+ # will become part of the current word
+ s = s[:end] + s[end + 1 :]
+ pos = end + 1
+
+ else:
+ if s[end] == "'": # slurp singly-quoted string
+ m = _squote_re.match(s, end)
+ elif s[end] == '"': # slurp doubly-quoted string
+ m = _dquote_re.match(s, end)
+ else:
+ raise RuntimeError(f"this can't happen (bad char '{s[end]}')")
+
+ if m is None:
+ raise ValueError(f"bad string (mismatched {s[end]} quotes?)")
+
+ (beg, end) = m.span()
+ s = s[:beg] + s[beg + 1 : end - 1] + s[end:]
+ pos = m.end() - 2
+
+ if pos >= len(s):
+ words.append(s)
+ break
+
+ return words
+
+
+# split_quoted ()
+
+
+def execute(
+ func: Callable[[Unpack[_Ts]], object],
+ args: tuple[Unpack[_Ts]],
+ msg: object = None,
+ verbose: bool = False,
+ dry_run: bool = False,
+) -> None:
+ """
+ Perform some action that affects the outside world (e.g. by
+ writing to the filesystem). Such actions are special because they
+ are disabled by the 'dry_run' flag. This method handles that
+ complication; simply supply the
+ function to call and an argument tuple for it (to embody the
+ "external action" being performed) and an optional message to
+ emit.
+ """
+ if msg is None:
+ msg = f"{func.__name__}{args!r}"
+ if msg[-2:] == ',)': # correct for singleton tuple
+ msg = msg[0:-2] + ')'
+
+ log.info(msg)
+ if not dry_run:
+ func(*args)
+
+
+def strtobool(val: str) -> bool:
+ """Convert a string representation of truth to true (1) or false (0).
+
+ True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
+ are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
+ 'val' is anything else.
+ """
+ val = val.lower()
+ if val in ('y', 'yes', 't', 'true', 'on', '1'):
+ return True
+ elif val in ('n', 'no', 'f', 'false', 'off', '0'):
+ return False
+ else:
+ raise ValueError(f"invalid truth value {val!r}")
+
+
+def byte_compile( # noqa: C901
+ py_files: Iterable[str],
+ optimize: int = 0,
+ force: bool = False,
+ prefix: str | None = None,
+ base_dir: str | None = None,
+ verbose: bool = True,
+ dry_run: bool = False,
+ direct: bool | None = None,
+) -> None:
+ """Byte-compile a collection of Python source files to .pyc
+ files in a __pycache__ subdirectory. 'py_files' is a list
+ of files to compile; any files that don't end in ".py" are silently
+ skipped. 'optimize' must be one of the following:
+ 0 - don't optimize
+ 1 - normal optimization (like "python -O")
+ 2 - extra optimization (like "python -OO")
+ If 'force' is true, all files are recompiled regardless of
+ timestamps.
+
+ The source filename encoded in each bytecode file defaults to the
+ filenames listed in 'py_files'; you can modify these with 'prefix' and
+ 'basedir'. 'prefix' is a string that will be stripped off of each
+ source filename, and 'base_dir' is a directory name that will be
+ prepended (after 'prefix' is stripped). You can supply either or both
+ (or neither) of 'prefix' and 'base_dir', as you wish.
+
+ If 'dry_run' is true, doesn't actually do anything that would
+ affect the filesystem.
+
+ Byte-compilation is either done directly in this interpreter process
+ with the standard py_compile module, or indirectly by writing a
+ temporary script and executing it. Normally, you should let
+ 'byte_compile()' figure out to use direct compilation or not (see
+ the source for details). The 'direct' flag is used by the script
+ generated in indirect mode; unless you know what you're doing, leave
+ it set to None.
+ """
+
+ # nothing is done if sys.dont_write_bytecode is True
+ if sys.dont_write_bytecode:
+ raise DistutilsByteCompileError('byte-compiling is disabled.')
+
+ # First, if the caller didn't force us into direct or indirect mode,
+ # figure out which mode we should be in. We take a conservative
+ # approach: choose direct mode *only* if the current interpreter is
+ # in debug mode and optimize is 0. If we're not in debug mode (-O
+ # or -OO), we don't know which level of optimization this
+ # interpreter is running with, so we can't do direct
+ # byte-compilation and be certain that it's the right thing. Thus,
+ # always compile indirectly if the current interpreter is in either
+ # optimize mode, or if either optimization level was requested by
+ # the caller.
+ if direct is None:
+ direct = __debug__ and optimize == 0
+
+ # "Indirect" byte-compilation: write a temporary script and then
+ # run it with the appropriate flags.
+ if not direct:
+ (script_fd, script_name) = tempfile.mkstemp(".py")
+ log.info("writing byte-compilation script '%s'", script_name)
+ if not dry_run:
+ script = os.fdopen(script_fd, "w", encoding='utf-8')
+
+ with script:
+ script.write(
+ """\
+from distutils.util import byte_compile
+files = [
+"""
+ )
+
+ # XXX would be nice to write absolute filenames, just for
+ # safety's sake (script should be more robust in the face of
+ # chdir'ing before running it). But this requires abspath'ing
+ # 'prefix' as well, and that breaks the hack in build_lib's
+ # 'byte_compile()' method that carefully tacks on a trailing
+ # slash (os.sep really) to make sure the prefix here is "just
+ # right". This whole prefix business is rather delicate -- the
+ # problem is that it's really a directory, but I'm treating it
+ # as a dumb string, so trailing slashes and so forth matter.
+
+ script.write(",\n".join(map(repr, py_files)) + "]\n")
+ script.write(
+ f"""
+byte_compile(files, optimize={optimize!r}, force={force!r},
+ prefix={prefix!r}, base_dir={base_dir!r},
+ verbose={verbose!r}, dry_run=False,
+ direct=True)
+"""
+ )
+
+ cmd = [sys.executable]
+ cmd.extend(subprocess._optim_args_from_interpreter_flags())
+ cmd.append(script_name)
+ spawn(cmd, dry_run=dry_run)
+ execute(os.remove, (script_name,), f"removing {script_name}", dry_run=dry_run)
+
+ # "Direct" byte-compilation: use the py_compile module to compile
+ # right here, right now. Note that the script generated in indirect
+ # mode simply calls 'byte_compile()' in direct mode, a weird sort of
+ # cross-process recursion. Hey, it works!
+ else:
+ from py_compile import compile
+
+ for file in py_files:
+ if file[-3:] != ".py":
+ # This lets us be lazy and not filter filenames in
+ # the "install_lib" command.
+ continue
+
+ # Terminology from the py_compile module:
+ # cfile - byte-compiled file
+ # dfile - purported source filename (same as 'file' by default)
+ if optimize >= 0:
+ opt = '' if optimize == 0 else optimize
+ cfile = importlib.util.cache_from_source(file, optimization=opt)
+ else:
+ cfile = importlib.util.cache_from_source(file)
+ dfile = file
+ if prefix:
+ if file[: len(prefix)] != prefix:
+ raise ValueError(
+ f"invalid prefix: filename {file!r} doesn't start with {prefix!r}"
+ )
+ dfile = dfile[len(prefix) :]
+ if base_dir:
+ dfile = os.path.join(base_dir, dfile)
+
+ cfile_base = os.path.basename(cfile)
+ if direct:
+ if force or newer(file, cfile):
+ log.info("byte-compiling %s to %s", file, cfile_base)
+ if not dry_run:
+ compile(file, cfile, dfile)
+ else:
+ log.debug("skipping byte-compilation of %s to %s", file, cfile_base)
+
+
+def rfc822_escape(header: str) -> str:
+ """Return a version of the string escaped for inclusion in an
+ RFC-822 header, by ensuring there are 8 spaces space after each newline.
+ """
+ indent = 8 * " "
+ lines = header.splitlines(keepends=True)
+
+ # Emulate the behaviour of `str.split`
+ # (the terminal line break in `splitlines` does not result in an extra line):
+ ends_in_newline = lines and lines[-1].splitlines()[0] != lines[-1]
+ suffix = indent if ends_in_newline else ""
+
+ return indent.join(lines) + suffix
+
+
+def is_mingw() -> bool:
+ """Returns True if the current platform is mingw.
+
+ Python compiled with Mingw-w64 has sys.platform == 'win32' and
+ get_platform() starts with 'mingw'.
+ """
+ return sys.platform == 'win32' and get_platform().startswith('mingw')
+
+
+def is_freethreaded():
+ """Return True if the Python interpreter is built with free threading support."""
+ return bool(sysconfig.get_config_var('Py_GIL_DISABLED'))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/version.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/version.py
new file mode 100644
index 0000000..2223ee9
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/version.py
@@ -0,0 +1,348 @@
+#
+# distutils/version.py
+#
+# Implements multiple version numbering conventions for the
+# Python Module Distribution Utilities.
+#
+# $Id$
+#
+
+"""Provides classes to represent module version numbers (one class for
+each style of version numbering). There are currently two such classes
+implemented: StrictVersion and LooseVersion.
+
+Every version number class implements the following interface:
+ * the 'parse' method takes a string and parses it to some internal
+ representation; if the string is an invalid version number,
+ 'parse' raises a ValueError exception
+ * the class constructor takes an optional string argument which,
+ if supplied, is passed to 'parse'
+ * __str__ reconstructs the string that was passed to 'parse' (or
+ an equivalent string -- ie. one that will generate an equivalent
+ version number instance)
+ * __repr__ generates Python code to recreate the version number instance
+ * _cmp compares the current instance with either another instance
+ of the same class or a string (which will be parsed to an instance
+ of the same class, thus must follow the same rules)
+"""
+
+import contextlib
+import re
+import warnings
+
+
+@contextlib.contextmanager
+def suppress_known_deprecation():
+ with warnings.catch_warnings(record=True) as ctx:
+ warnings.filterwarnings(
+ action='default',
+ category=DeprecationWarning,
+ message="distutils Version classes are deprecated.",
+ )
+ yield ctx
+
+
+class Version:
+ """Abstract base class for version numbering classes. Just provides
+ constructor (__init__) and reproducer (__repr__), because those
+ seem to be the same for all version numbering classes; and route
+ rich comparisons to _cmp.
+ """
+
+ def __init__(self, vstring=None):
+ if vstring:
+ self.parse(vstring)
+ warnings.warn(
+ "distutils Version classes are deprecated. Use packaging.version instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+
+ def __repr__(self):
+ return f"{self.__class__.__name__} ('{self}')"
+
+ def __eq__(self, other):
+ c = self._cmp(other)
+ if c is NotImplemented:
+ return c
+ return c == 0
+
+ def __lt__(self, other):
+ c = self._cmp(other)
+ if c is NotImplemented:
+ return c
+ return c < 0
+
+ def __le__(self, other):
+ c = self._cmp(other)
+ if c is NotImplemented:
+ return c
+ return c <= 0
+
+ def __gt__(self, other):
+ c = self._cmp(other)
+ if c is NotImplemented:
+ return c
+ return c > 0
+
+ def __ge__(self, other):
+ c = self._cmp(other)
+ if c is NotImplemented:
+ return c
+ return c >= 0
+
+
+# Interface for version-number classes -- must be implemented
+# by the following classes (the concrete ones -- Version should
+# be treated as an abstract class).
+# __init__ (string) - create and take same action as 'parse'
+# (string parameter is optional)
+# parse (string) - convert a string representation to whatever
+# internal representation is appropriate for
+# this style of version numbering
+# __str__ (self) - convert back to a string; should be very similar
+# (if not identical to) the string supplied to parse
+# __repr__ (self) - generate Python code to recreate
+# the instance
+# _cmp (self, other) - compare two version numbers ('other' may
+# be an unparsed version string, or another
+# instance of your version class)
+
+
+class StrictVersion(Version):
+ """Version numbering for anal retentives and software idealists.
+ Implements the standard interface for version number classes as
+ described above. A version number consists of two or three
+ dot-separated numeric components, with an optional "pre-release" tag
+ on the end. The pre-release tag consists of the letter 'a' or 'b'
+ followed by a number. If the numeric components of two version
+ numbers are equal, then one with a pre-release tag will always
+ be deemed earlier (lesser) than one without.
+
+ The following are valid version numbers (shown in the order that
+ would be obtained by sorting according to the supplied cmp function):
+
+ 0.4 0.4.0 (these two are equivalent)
+ 0.4.1
+ 0.5a1
+ 0.5b3
+ 0.5
+ 0.9.6
+ 1.0
+ 1.0.4a3
+ 1.0.4b1
+ 1.0.4
+
+ The following are examples of invalid version numbers:
+
+ 1
+ 2.7.2.2
+ 1.3.a4
+ 1.3pl1
+ 1.3c4
+
+ The rationale for this version numbering system will be explained
+ in the distutils documentation.
+ """
+
+ version_re = re.compile(
+ r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', re.VERBOSE | re.ASCII
+ )
+
+ def parse(self, vstring):
+ match = self.version_re.match(vstring)
+ if not match:
+ raise ValueError(f"invalid version number '{vstring}'")
+
+ (major, minor, patch, prerelease, prerelease_num) = match.group(1, 2, 4, 5, 6)
+
+ if patch:
+ self.version = tuple(map(int, [major, minor, patch]))
+ else:
+ self.version = tuple(map(int, [major, minor])) + (0,)
+
+ if prerelease:
+ self.prerelease = (prerelease[0], int(prerelease_num))
+ else:
+ self.prerelease = None
+
+ def __str__(self):
+ if self.version[2] == 0:
+ vstring = '.'.join(map(str, self.version[0:2]))
+ else:
+ vstring = '.'.join(map(str, self.version))
+
+ if self.prerelease:
+ vstring = vstring + self.prerelease[0] + str(self.prerelease[1])
+
+ return vstring
+
+ def _cmp(self, other):
+ if isinstance(other, str):
+ with suppress_known_deprecation():
+ other = StrictVersion(other)
+ elif not isinstance(other, StrictVersion):
+ return NotImplemented
+
+ if self.version == other.version:
+ # versions match; pre-release drives the comparison
+ return self._cmp_prerelease(other)
+
+ return -1 if self.version < other.version else 1
+
+ def _cmp_prerelease(self, other):
+ """
+ case 1: self has prerelease, other doesn't; other is greater
+ case 2: self doesn't have prerelease, other does: self is greater
+ case 3: both or neither have prerelease: compare them!
+ """
+ if self.prerelease and not other.prerelease:
+ return -1
+ elif not self.prerelease and other.prerelease:
+ return 1
+
+ if self.prerelease == other.prerelease:
+ return 0
+ elif self.prerelease < other.prerelease:
+ return -1
+ else:
+ return 1
+
+
+# end class StrictVersion
+
+
+# The rules according to Greg Stein:
+# 1) a version number has 1 or more numbers separated by a period or by
+# sequences of letters. If only periods, then these are compared
+# left-to-right to determine an ordering.
+# 2) sequences of letters are part of the tuple for comparison and are
+# compared lexicographically
+# 3) recognize the numeric components may have leading zeroes
+#
+# The LooseVersion class below implements these rules: a version number
+# string is split up into a tuple of integer and string components, and
+# comparison is a simple tuple comparison. This means that version
+# numbers behave in a predictable and obvious way, but a way that might
+# not necessarily be how people *want* version numbers to behave. There
+# wouldn't be a problem if people could stick to purely numeric version
+# numbers: just split on period and compare the numbers as tuples.
+# However, people insist on putting letters into their version numbers;
+# the most common purpose seems to be:
+# - indicating a "pre-release" version
+# ('alpha', 'beta', 'a', 'b', 'pre', 'p')
+# - indicating a post-release patch ('p', 'pl', 'patch')
+# but of course this can't cover all version number schemes, and there's
+# no way to know what a programmer means without asking him.
+#
+# The problem is what to do with letters (and other non-numeric
+# characters) in a version number. The current implementation does the
+# obvious and predictable thing: keep them as strings and compare
+# lexically within a tuple comparison. This has the desired effect if
+# an appended letter sequence implies something "post-release":
+# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002".
+#
+# However, if letters in a version number imply a pre-release version,
+# the "obvious" thing isn't correct. Eg. you would expect that
+# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison
+# implemented here, this just isn't so.
+#
+# Two possible solutions come to mind. The first is to tie the
+# comparison algorithm to a particular set of semantic rules, as has
+# been done in the StrictVersion class above. This works great as long
+# as everyone can go along with bondage and discipline. Hopefully a
+# (large) subset of Python module programmers will agree that the
+# particular flavour of bondage and discipline provided by StrictVersion
+# provides enough benefit to be worth using, and will submit their
+# version numbering scheme to its domination. The free-thinking
+# anarchists in the lot will never give in, though, and something needs
+# to be done to accommodate them.
+#
+# Perhaps a "moderately strict" version class could be implemented that
+# lets almost anything slide (syntactically), and makes some heuristic
+# assumptions about non-digits in version number strings. This could
+# sink into special-case-hell, though; if I was as talented and
+# idiosyncratic as Larry Wall, I'd go ahead and implement a class that
+# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is
+# just as happy dealing with things like "2g6" and "1.13++". I don't
+# think I'm smart enough to do it right though.
+#
+# In any case, I've coded the test suite for this module (see
+# ../test/test_version.py) specifically to fail on things like comparing
+# "1.2a2" and "1.2". That's not because the *code* is doing anything
+# wrong, it's because the simple, obvious design doesn't match my
+# complicated, hairy expectations for real-world version numbers. It
+# would be a snap to fix the test suite to say, "Yep, LooseVersion does
+# the Right Thing" (ie. the code matches the conception). But I'd rather
+# have a conception that matches common notions about version numbers.
+
+
+class LooseVersion(Version):
+ """Version numbering for anarchists and software realists.
+ Implements the standard interface for version number classes as
+ described above. A version number consists of a series of numbers,
+ separated by either periods or strings of letters. When comparing
+ version numbers, the numeric components will be compared
+ numerically, and the alphabetic components lexically. The following
+ are all valid version numbers, in no particular order:
+
+ 1.5.1
+ 1.5.2b2
+ 161
+ 3.10a
+ 8.02
+ 3.4j
+ 1996.07.12
+ 3.2.pl0
+ 3.1.1.6
+ 2g6
+ 11g
+ 0.960923
+ 2.2beta29
+ 1.13++
+ 5.5.kw
+ 2.0b1pl0
+
+ In fact, there is no such thing as an invalid version number under
+ this scheme; the rules for comparison are simple and predictable,
+ but may not always give the results you want (for some definition
+ of "want").
+ """
+
+ component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE)
+
+ def parse(self, vstring):
+ # I've given up on thinking I can reconstruct the version string
+ # from the parsed tuple -- so I just store the string here for
+ # use by __str__
+ self.vstring = vstring
+ components = [x for x in self.component_re.split(vstring) if x and x != '.']
+ for i, obj in enumerate(components):
+ try:
+ components[i] = int(obj)
+ except ValueError:
+ pass
+
+ self.version = components
+
+ def __str__(self):
+ return self.vstring
+
+ def __repr__(self):
+ return f"LooseVersion ('{self}')"
+
+ def _cmp(self, other):
+ if isinstance(other, str):
+ other = LooseVersion(other)
+ elif not isinstance(other, LooseVersion):
+ return NotImplemented
+
+ if self.version == other.version:
+ return 0
+ if self.version < other.version:
+ return -1
+ if self.version > other.version:
+ return 1
+
+
+# end class LooseVersion
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/versionpredicate.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/versionpredicate.py
new file mode 100644
index 0000000..fe31b0e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/versionpredicate.py
@@ -0,0 +1,175 @@
+"""Module for parsing and testing package version predicate strings."""
+
+import operator
+import re
+
+from . import version
+
+re_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)", re.ASCII)
+# (package) (rest)
+
+re_paren = re.compile(r"^\s*\((.*)\)\s*$") # (list) inside of parentheses
+re_splitComparison = re.compile(r"^\s*(<=|>=|<|>|!=|==)\s*([^\s,]+)\s*$")
+# (comp) (version)
+
+
+def splitUp(pred):
+ """Parse a single version comparison.
+
+ Return (comparison string, StrictVersion)
+ """
+ res = re_splitComparison.match(pred)
+ if not res:
+ raise ValueError(f"bad package restriction syntax: {pred!r}")
+ comp, verStr = res.groups()
+ with version.suppress_known_deprecation():
+ other = version.StrictVersion(verStr)
+ return (comp, other)
+
+
+compmap = {
+ "<": operator.lt,
+ "<=": operator.le,
+ "==": operator.eq,
+ ">": operator.gt,
+ ">=": operator.ge,
+ "!=": operator.ne,
+}
+
+
+class VersionPredicate:
+ """Parse and test package version predicates.
+
+ >>> v = VersionPredicate('pyepat.abc (>1.0, <3333.3a1, !=1555.1b3)')
+
+ The `name` attribute provides the full dotted name that is given::
+
+ >>> v.name
+ 'pyepat.abc'
+
+ The str() of a `VersionPredicate` provides a normalized
+ human-readable version of the expression::
+
+ >>> print(v)
+ pyepat.abc (> 1.0, < 3333.3a1, != 1555.1b3)
+
+ The `satisfied_by()` method can be used to determine with a given
+ version number is included in the set described by the version
+ restrictions::
+
+ >>> v.satisfied_by('1.1')
+ True
+ >>> v.satisfied_by('1.4')
+ True
+ >>> v.satisfied_by('1.0')
+ False
+ >>> v.satisfied_by('4444.4')
+ False
+ >>> v.satisfied_by('1555.1b3')
+ False
+
+ `VersionPredicate` is flexible in accepting extra whitespace::
+
+ >>> v = VersionPredicate(' pat( == 0.1 ) ')
+ >>> v.name
+ 'pat'
+ >>> v.satisfied_by('0.1')
+ True
+ >>> v.satisfied_by('0.2')
+ False
+
+ If any version numbers passed in do not conform to the
+ restrictions of `StrictVersion`, a `ValueError` is raised::
+
+ >>> v = VersionPredicate('p1.p2.p3.p4(>=1.0, <=1.3a1, !=1.2zb3)')
+ Traceback (most recent call last):
+ ...
+ ValueError: invalid version number '1.2zb3'
+
+ It the module or package name given does not conform to what's
+ allowed as a legal module or package name, `ValueError` is
+ raised::
+
+ >>> v = VersionPredicate('foo-bar')
+ Traceback (most recent call last):
+ ...
+ ValueError: expected parenthesized list: '-bar'
+
+ >>> v = VersionPredicate('foo bar (12.21)')
+ Traceback (most recent call last):
+ ...
+ ValueError: expected parenthesized list: 'bar (12.21)'
+
+ """
+
+ def __init__(self, versionPredicateStr):
+ """Parse a version predicate string."""
+ # Fields:
+ # name: package name
+ # pred: list of (comparison string, StrictVersion)
+
+ versionPredicateStr = versionPredicateStr.strip()
+ if not versionPredicateStr:
+ raise ValueError("empty package restriction")
+ match = re_validPackage.match(versionPredicateStr)
+ if not match:
+ raise ValueError(f"bad package name in {versionPredicateStr!r}")
+ self.name, paren = match.groups()
+ paren = paren.strip()
+ if paren:
+ match = re_paren.match(paren)
+ if not match:
+ raise ValueError(f"expected parenthesized list: {paren!r}")
+ str = match.groups()[0]
+ self.pred = [splitUp(aPred) for aPred in str.split(",")]
+ if not self.pred:
+ raise ValueError(f"empty parenthesized list in {versionPredicateStr!r}")
+ else:
+ self.pred = []
+
+ def __str__(self):
+ if self.pred:
+ seq = [cond + " " + str(ver) for cond, ver in self.pred]
+ return self.name + " (" + ", ".join(seq) + ")"
+ else:
+ return self.name
+
+ def satisfied_by(self, version):
+ """True if version is compatible with all the predicates in self.
+ The parameter version must be acceptable to the StrictVersion
+ constructor. It may be either a string or StrictVersion.
+ """
+ for cond, ver in self.pred:
+ if not compmap[cond](version, ver):
+ return False
+ return True
+
+
+_provision_rx = None
+
+
+def split_provision(value):
+ """Return the name and optional version number of a provision.
+
+ The version number, if given, will be returned as a `StrictVersion`
+ instance, otherwise it will be `None`.
+
+ >>> split_provision('mypkg')
+ ('mypkg', None)
+ >>> split_provision(' mypkg( 1.2 ) ')
+ ('mypkg', StrictVersion ('1.2'))
+ """
+ global _provision_rx
+ if _provision_rx is None:
+ _provision_rx = re.compile(
+ r"([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$", re.ASCII
+ )
+ value = value.strip()
+ m = _provision_rx.match(value)
+ if not m:
+ raise ValueError(f"illegal provides specification: {value!r}")
+ ver = m.group(2) or None
+ if ver:
+ with version.suppress_known_deprecation():
+ ver = version.StrictVersion(ver)
+ return m.group(1), ver
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_distutils/zosccompiler.py b/testcline/lib/python3.12/site-packages/setuptools/_distutils/zosccompiler.py
new file mode 100644
index 0000000..e49630a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_distutils/zosccompiler.py
@@ -0,0 +1,3 @@
+from .compilers.C import zos
+
+zOSCCompiler = zos.Compiler
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_entry_points.py b/testcline/lib/python3.12/site-packages/setuptools/_entry_points.py
new file mode 100644
index 0000000..e785fc7
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_entry_points.py
@@ -0,0 +1,90 @@
+import functools
+import itertools
+import operator
+
+from jaraco.functools import pass_none
+from jaraco.text import yield_lines
+from more_itertools import consume
+
+from ._importlib import metadata
+from ._itertools import ensure_unique
+from .errors import OptionError
+
+
+def ensure_valid(ep):
+ """
+ Exercise one of the dynamic properties to trigger
+ the pattern match.
+ """
+ try:
+ ep.extras
+ except (AttributeError, AssertionError) as ex:
+ # Why both? See https://github.com/python/importlib_metadata/issues/488
+ msg = (
+ f"Problems to parse {ep}.\nPlease ensure entry-point follows the spec: "
+ "https://packaging.python.org/en/latest/specifications/entry-points/"
+ )
+ raise OptionError(msg) from ex
+
+
+def load_group(value, group):
+ """
+ Given a value of an entry point or series of entry points,
+ return each as an EntryPoint.
+ """
+ # normalize to a single sequence of lines
+ lines = yield_lines(value)
+ text = f'[{group}]\n' + '\n'.join(lines)
+ return metadata.EntryPoints._from_text(text)
+
+
+def by_group_and_name(ep):
+ return ep.group, ep.name
+
+
+def validate(eps: metadata.EntryPoints):
+ """
+ Ensure entry points are unique by group and name and validate each.
+ """
+ consume(map(ensure_valid, ensure_unique(eps, key=by_group_and_name)))
+ return eps
+
+
+@functools.singledispatch
+def load(eps):
+ """
+ Given a Distribution.entry_points, produce EntryPoints.
+ """
+ groups = itertools.chain.from_iterable(
+ load_group(value, group) for group, value in eps.items()
+ )
+ return validate(metadata.EntryPoints(groups))
+
+
+@load.register(str)
+def _(eps):
+ r"""
+ >>> ep, = load('[console_scripts]\nfoo=bar')
+ >>> ep.group
+ 'console_scripts'
+ >>> ep.name
+ 'foo'
+ >>> ep.value
+ 'bar'
+ """
+ return validate(metadata.EntryPoints(metadata.EntryPoints._from_text(eps)))
+
+
+load.register(type(None), lambda x: x)
+
+
+@pass_none
+def render(eps: metadata.EntryPoints):
+ by_group = operator.attrgetter('group')
+ groups = itertools.groupby(sorted(eps, key=by_group), by_group)
+
+ return '\n'.join(f'[{group}]\n{render_items(items)}\n' for group, items in groups)
+
+
+def render_items(eps):
+ return '\n'.join(f'{ep.name} = {ep.value}' for ep in sorted(eps))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_imp.py b/testcline/lib/python3.12/site-packages/setuptools/_imp.py
new file mode 100644
index 0000000..f1d9f29
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_imp.py
@@ -0,0 +1,87 @@
+"""
+Re-implementation of find_module and get_frozen_object
+from the deprecated imp module.
+"""
+
+import importlib.machinery
+import importlib.util
+import os
+import tokenize
+from importlib.util import module_from_spec
+
+PY_SOURCE = 1
+PY_COMPILED = 2
+C_EXTENSION = 3
+C_BUILTIN = 6
+PY_FROZEN = 7
+
+
+def find_spec(module, paths):
+ finder = (
+ importlib.machinery.PathFinder().find_spec
+ if isinstance(paths, list)
+ else importlib.util.find_spec
+ )
+ return finder(module, paths)
+
+
+def find_module(module, paths=None):
+ """Just like 'imp.find_module()', but with package support"""
+ spec = find_spec(module, paths)
+ if spec is None:
+ raise ImportError(f"Can't find {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 compatibility
+ elif (
+ spec.origin == 'built-in'
+ or static
+ and issubclass(spec.loader, importlib.machinery.BuiltinImporter)
+ ):
+ kind = C_BUILTIN
+ path = None # imp compabilty
+ suffix = mode = '' # imp compatibility
+ 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
+ file = tokenize.open(path)
+ elif suffix in importlib.machinery.BYTECODE_SUFFIXES:
+ kind = PY_COMPILED
+ file = open(path, 'rb')
+ elif suffix in importlib.machinery.EXTENSION_SUFFIXES:
+ kind = C_EXTENSION
+
+ else:
+ path = None
+ suffix = mode = ''
+
+ return file, path, (suffix, mode, kind)
+
+
+def get_frozen_object(module, paths=None):
+ spec = find_spec(module, paths)
+ if not spec:
+ raise ImportError(f"Can't find {module}")
+ return spec.loader.get_code(module)
+
+
+def get_module(module, paths, info):
+ spec = find_spec(module, paths)
+ if not spec:
+ raise ImportError(f"Can't find {module}")
+ return module_from_spec(spec)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_importlib.py b/testcline/lib/python3.12/site-packages/setuptools/_importlib.py
new file mode 100644
index 0000000..ce0fd52
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_importlib.py
@@ -0,0 +1,9 @@
+import sys
+
+if sys.version_info < (3, 10):
+ import importlib_metadata as metadata # pragma: no cover
+else:
+ import importlib.metadata as metadata # noqa: F401
+
+
+import importlib.resources as resources # noqa: F401
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_itertools.py b/testcline/lib/python3.12/site-packages/setuptools/_itertools.py
new file mode 100644
index 0000000..d6ca841
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_itertools.py
@@ -0,0 +1,23 @@
+from more_itertools import consume # noqa: F401
+
+
+# copied from jaraco.itertools 6.1
+def ensure_unique(iterable, key=lambda x: x):
+ """
+ Wrap an iterable to raise a ValueError if non-unique values are encountered.
+
+ >>> list(ensure_unique('abc'))
+ ['a', 'b', 'c']
+ >>> consume(ensure_unique('abca'))
+ Traceback (most recent call last):
+ ...
+ ValueError: Duplicate element 'a' encountered.
+ """
+ seen = set()
+ seen_add = seen.add
+ for element in iterable:
+ k = key(element)
+ if k in seen:
+ raise ValueError(f"Duplicate element {element!r} encountered.")
+ seen_add(k)
+ yield element
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_normalization.py b/testcline/lib/python3.12/site-packages/setuptools/_normalization.py
new file mode 100644
index 0000000..0937a4f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_normalization.py
@@ -0,0 +1,179 @@
+"""
+Helpers for normalization as expected in wheel/sdist/module file names
+and core metadata
+"""
+
+import re
+from typing import TYPE_CHECKING
+
+import packaging
+
+# https://packaging.python.org/en/latest/specifications/core-metadata/#name
+_VALID_NAME = re.compile(r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.I)
+_UNSAFE_NAME_CHARS = re.compile(r"[^A-Z0-9._-]+", re.I)
+_NON_ALPHANUMERIC = re.compile(r"[^A-Z0-9]+", re.I)
+_PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.I)
+
+
+def safe_identifier(name: str) -> str:
+ """Make a string safe to be used as Python identifier.
+ >>> safe_identifier("12abc")
+ '_12abc'
+ >>> safe_identifier("__editable__.myns.pkg-78.9.3_local")
+ '__editable___myns_pkg_78_9_3_local'
+ """
+ safe = re.sub(r'\W|^(?=\d)', '_', name)
+ assert safe.isidentifier()
+ return safe
+
+
+def safe_name(component: str) -> str:
+ """Escape a component used as a project name according to Core Metadata.
+ >>> safe_name("hello world")
+ 'hello-world'
+ >>> safe_name("hello?world")
+ 'hello-world'
+ >>> safe_name("hello_world")
+ 'hello_world'
+ """
+ # See pkg_resources.safe_name
+ return _UNSAFE_NAME_CHARS.sub("-", component)
+
+
+def safe_version(version: str) -> str:
+ """Convert an arbitrary string into a valid version string.
+ Can still raise an ``InvalidVersion`` exception.
+ To avoid exceptions use ``best_effort_version``.
+ >>> safe_version("1988 12 25")
+ '1988.12.25'
+ >>> safe_version("v0.2.1")
+ '0.2.1'
+ >>> safe_version("v0.2?beta")
+ '0.2b0'
+ >>> safe_version("v0.2 beta")
+ '0.2b0'
+ >>> safe_version("ubuntu lts")
+ Traceback (most recent call last):
+ ...
+ packaging.version.InvalidVersion: Invalid version: 'ubuntu.lts'
+ """
+ v = version.replace(' ', '.')
+ try:
+ return str(packaging.version.Version(v))
+ except packaging.version.InvalidVersion:
+ attempt = _UNSAFE_NAME_CHARS.sub("-", v)
+ return str(packaging.version.Version(attempt))
+
+
+def best_effort_version(version: str) -> str:
+ """Convert an arbitrary string into a version-like string.
+ Fallback when ``safe_version`` is not safe enough.
+ >>> best_effort_version("v0.2 beta")
+ '0.2b0'
+ >>> best_effort_version("ubuntu lts")
+ '0.dev0+sanitized.ubuntu.lts'
+ >>> best_effort_version("0.23ubuntu1")
+ '0.23.dev0+sanitized.ubuntu1'
+ >>> best_effort_version("0.23-")
+ '0.23.dev0+sanitized'
+ >>> best_effort_version("0.-_")
+ '0.dev0+sanitized'
+ >>> best_effort_version("42.+?1")
+ '42.dev0+sanitized.1'
+ """
+ # See pkg_resources._forgiving_version
+ try:
+ return safe_version(version)
+ except packaging.version.InvalidVersion:
+ v = version.replace(' ', '.')
+ match = _PEP440_FALLBACK.search(v)
+ if match:
+ safe = match["safe"]
+ rest = v[len(safe) :]
+ else:
+ safe = "0"
+ rest = version
+ safe_rest = _NON_ALPHANUMERIC.sub(".", rest).strip(".")
+ local = f"sanitized.{safe_rest}".strip(".")
+ return safe_version(f"{safe}.dev0+{local}")
+
+
+def safe_extra(extra: str) -> str:
+ """Normalize extra name according to PEP 685
+ >>> safe_extra("_FrIeNdLy-._.-bArD")
+ 'friendly-bard'
+ >>> safe_extra("FrIeNdLy-._.-bArD__._-")
+ 'friendly-bard'
+ """
+ return _NON_ALPHANUMERIC.sub("-", extra).strip("-").lower()
+
+
+def filename_component(value: str) -> str:
+ """Normalize each component of a filename (e.g. distribution/version part of wheel)
+ Note: ``value`` needs to be already normalized.
+ >>> filename_component("my-pkg")
+ 'my_pkg'
+ """
+ return value.replace("-", "_").strip("_")
+
+
+def filename_component_broken(value: str) -> str:
+ """
+ Produce the incorrect filename component for compatibility.
+
+ See pypa/setuptools#4167 for detailed analysis.
+
+ TODO: replace this with filename_component after pip 24 is
+ nearly-ubiquitous.
+
+ >>> filename_component_broken('foo_bar-baz')
+ 'foo-bar-baz'
+ """
+ return value.replace('_', '-')
+
+
+def safer_name(value: str) -> str:
+ """Like ``safe_name`` but can be used as filename component for wheel"""
+ # See bdist_wheel.safer_name
+ return (
+ # Per https://packaging.python.org/en/latest/specifications/name-normalization/#name-normalization
+ re.sub(r"[-_.]+", "-", safe_name(value))
+ .lower()
+ # Per https://packaging.python.org/en/latest/specifications/binary-distribution-format/#escaping-and-unicode
+ .replace("-", "_")
+ )
+
+
+def safer_best_effort_version(value: str) -> str:
+ """Like ``best_effort_version`` but can be used as filename component for wheel"""
+ # See bdist_wheel.safer_verion
+ # TODO: Replace with only safe_version in the future (no need for best effort)
+ return filename_component(best_effort_version(value))
+
+
+def _missing_canonicalize_license_expression(expression: str) -> str:
+ """
+ Defer import error to affect only users that actually use it
+ https://github.com/pypa/setuptools/issues/4894
+ >>> _missing_canonicalize_license_expression("a OR b")
+ Traceback (most recent call last):
+ ...
+ ImportError: ...Cannot import `packaging.licenses`...
+ """
+ raise ImportError(
+ "Cannot import `packaging.licenses`."
+ """
+ Setuptools>=77.0.0 requires "packaging>=24.2" to work properly.
+ Please make sure you have a suitable version installed.
+ """
+ )
+
+
+try:
+ from packaging.licenses import (
+ canonicalize_license_expression as _canonicalize_license_expression,
+ )
+except ImportError: # pragma: nocover
+ if not TYPE_CHECKING:
+ # XXX: pyright is still upset even with # pyright: ignore[reportAssignmentType]
+ _canonicalize_license_expression = _missing_canonicalize_license_expression
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_path.py b/testcline/lib/python3.12/site-packages/setuptools/_path.py
new file mode 100644
index 0000000..0d99b0f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_path.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+import contextlib
+import os
+import sys
+from typing import TYPE_CHECKING, TypeVar, Union
+
+from more_itertools import unique_everseen
+
+if TYPE_CHECKING:
+ from typing_extensions import TypeAlias
+
+StrPath: TypeAlias = Union[str, os.PathLike[str]] # Same as _typeshed.StrPath
+StrPathT = TypeVar("StrPathT", bound=Union[str, os.PathLike[str]])
+
+
+def ensure_directory(path):
+ """Ensure that the parent directory of `path` exists"""
+ dirname = os.path.dirname(path)
+ os.makedirs(dirname, exist_ok=True)
+
+
+def same_path(p1: StrPath, p2: StrPath) -> bool:
+ """Differs from os.path.samefile because it does not require paths to exist.
+ Purely string based (no comparison between i-nodes).
+ >>> same_path("a/b", "./a/b")
+ True
+ >>> same_path("a/b", "a/./b")
+ True
+ >>> same_path("a/b", "././a/b")
+ True
+ >>> same_path("a/b", "./a/b/c/..")
+ True
+ >>> same_path("a/b", "../a/b/c")
+ False
+ >>> same_path("a", "a/b")
+ False
+ """
+ return normpath(p1) == normpath(p2)
+
+
+def normpath(filename: StrPath) -> str:
+ """Normalize a file/dir name for comparison purposes."""
+ # See pkg_resources.normalize_path for notes about cygwin
+ file = os.path.abspath(filename) if sys.platform == 'cygwin' else filename
+ return os.path.normcase(os.path.realpath(os.path.normpath(file)))
+
+
+@contextlib.contextmanager
+def paths_on_pythonpath(paths):
+ """
+ Add the indicated paths to the head of the PYTHONPATH environment
+ variable so that subprocesses will also see the packages at
+ these paths.
+
+ Do this in a context that restores the value on exit.
+
+ >>> getfixture('monkeypatch').setenv('PYTHONPATH', 'anything')
+ >>> with paths_on_pythonpath(['foo', 'bar']):
+ ... assert 'foo' in os.environ['PYTHONPATH']
+ ... assert 'anything' in os.environ['PYTHONPATH']
+ >>> os.environ['PYTHONPATH']
+ 'anything'
+
+ >>> getfixture('monkeypatch').delenv('PYTHONPATH')
+ >>> with paths_on_pythonpath(['foo', 'bar']):
+ ... assert 'foo' in os.environ['PYTHONPATH']
+ >>> os.environ.get('PYTHONPATH')
+ """
+ nothing = object()
+ orig_pythonpath = os.environ.get('PYTHONPATH', nothing)
+ current_pythonpath = os.environ.get('PYTHONPATH', '')
+ try:
+ prefix = os.pathsep.join(unique_everseen(paths))
+ to_join = filter(None, [prefix, current_pythonpath])
+ new_path = os.pathsep.join(to_join)
+ if new_path:
+ os.environ['PYTHONPATH'] = new_path
+ yield
+ finally:
+ if orig_pythonpath is nothing:
+ os.environ.pop('PYTHONPATH', None)
+ else:
+ os.environ['PYTHONPATH'] = orig_pythonpath
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_reqs.py b/testcline/lib/python3.12/site-packages/setuptools/_reqs.py
new file mode 100644
index 0000000..c793be4
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_reqs.py
@@ -0,0 +1,42 @@
+from __future__ import annotations
+
+from collections.abc import Iterable, Iterator
+from functools import lru_cache
+from typing import TYPE_CHECKING, Callable, TypeVar, Union, overload
+
+import jaraco.text as text
+from packaging.requirements import Requirement
+
+if TYPE_CHECKING:
+ from typing_extensions import TypeAlias
+
+_T = TypeVar("_T")
+_StrOrIter: TypeAlias = Union[str, Iterable[str]]
+
+
+parse_req: Callable[[str], Requirement] = lru_cache()(Requirement)
+# Setuptools parses the same requirement many times
+# (e.g. first for validation than for normalisation),
+# so it might be worth to cache.
+
+
+def parse_strings(strs: _StrOrIter) -> Iterator[str]:
+ """
+ Yield requirement strings for each specification in `strs`.
+
+ `strs` must be a string, or a (possibly-nested) iterable thereof.
+ """
+ return text.join_continuation(map(text.drop_comment, text.yield_lines(strs)))
+
+
+# These overloads are only needed because of a mypy false-positive, pyright gets it right
+# https://github.com/python/mypy/issues/3737
+@overload
+def parse(strs: _StrOrIter) -> Iterator[Requirement]: ...
+@overload
+def parse(strs: _StrOrIter, parser: Callable[[str], _T]) -> Iterator[_T]: ...
+def parse(strs: _StrOrIter, parser: Callable[[str], _T] = parse_req) -> Iterator[_T]: # type: ignore[assignment]
+ """
+ Replacement for ``pkg_resources.parse_requirements`` that uses ``packaging``.
+ """
+ return map(parser, parse_strings(strs))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_shutil.py b/testcline/lib/python3.12/site-packages/setuptools/_shutil.py
new file mode 100644
index 0000000..6acbb42
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_shutil.py
@@ -0,0 +1,53 @@
+"""Convenience layer on top of stdlib's shutil and os"""
+
+import os
+import stat
+from typing import Callable, TypeVar
+
+from .compat import py311
+
+from distutils import log
+
+try:
+ from os import chmod # pyright: ignore[reportAssignmentType]
+ # Losing type-safety w/ pyright, but that's ok
+except ImportError: # pragma: no cover
+ # Jython compatibility
+ def chmod(*args: object, **kwargs: object) -> None: # type: ignore[misc] # Mypy reuses the imported definition anyway
+ pass
+
+
+_T = TypeVar("_T")
+
+
+def attempt_chmod_verbose(path, mode):
+ log.debug("changing mode of %s to %o", path, mode)
+ try:
+ chmod(path, mode)
+ except OSError as e: # pragma: no cover
+ log.debug("chmod failed: %s", e)
+
+
+# Must match shutil._OnExcCallback
+def _auto_chmod(
+ func: Callable[..., _T], arg: str, exc: BaseException
+) -> _T: # pragma: no cover
+ """shutils onexc callback to automatically call chmod for certain functions."""
+ # Only retry for scenarios known to have an issue
+ if func in [os.unlink, os.remove] and os.name == 'nt':
+ attempt_chmod_verbose(arg, stat.S_IWRITE)
+ return func(arg)
+ raise exc
+
+
+def rmtree(path, ignore_errors=False, onexc=_auto_chmod):
+ """
+ Similar to ``shutil.rmtree`` but automatically executes ``chmod``
+ for well know Windows failure scenarios.
+ """
+ return py311.shutil_rmtree(path, ignore_errors, onexc)
+
+
+def rmdir(path, **opts):
+ if os.path.isdir(path):
+ rmtree(path, **opts)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_static.py b/testcline/lib/python3.12/site-packages/setuptools/_static.py
new file mode 100644
index 0000000..af35862
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_static.py
@@ -0,0 +1,188 @@
+from functools import wraps
+from typing import TypeVar
+
+import packaging.specifiers
+
+from .warnings import SetuptoolsDeprecationWarning
+
+
+class Static:
+ """
+ Wrapper for built-in object types that are allow setuptools to identify
+ static core metadata (in opposition to ``Dynamic``, as defined :pep:`643`).
+
+ The trick is to mark values with :class:`Static` when they come from
+ ``pyproject.toml`` or ``setup.cfg``, so if any plugin overwrite the value
+ with a built-in, setuptools will be able to recognise the change.
+
+ We inherit from built-in classes, so that we don't need to change the existing
+ code base to deal with the new types.
+ We also should strive for immutability objects to avoid changes after the
+ initial parsing.
+ """
+
+ _mutated_: bool = False # TODO: Remove after deprecation warning is solved
+
+
+def _prevent_modification(target: type, method: str, copying: str) -> None:
+ """
+ Because setuptools is very flexible we cannot fully prevent
+ plugins and user customizations from modifying static values that were
+ parsed from config files.
+ But we can attempt to block "in-place" mutations and identify when they
+ were done.
+ """
+ fn = getattr(target, method, None)
+ if fn is None:
+ return
+
+ @wraps(fn)
+ def _replacement(self: Static, *args, **kwargs):
+ # TODO: After deprecation period raise NotImplementedError instead of warning
+ # which obviated the existence and checks of the `_mutated_` attribute.
+ self._mutated_ = True
+ SetuptoolsDeprecationWarning.emit(
+ "Direct modification of value will be disallowed",
+ f"""
+ In an effort to implement PEP 643, direct/in-place changes of static values
+ that come from configuration files are deprecated.
+ If you need to modify this value, please first create a copy with {copying}
+ and make sure conform to all relevant standards when overriding setuptools
+ functionality (https://packaging.python.org/en/latest/specifications/).
+ """,
+ due_date=(2025, 10, 10), # Initially introduced in 2024-09-06
+ )
+ return fn(self, *args, **kwargs)
+
+ _replacement.__doc__ = "" # otherwise doctest may fail.
+ setattr(target, method, _replacement)
+
+
+class Str(str, Static):
+ pass
+
+
+class Tuple(tuple, Static):
+ pass
+
+
+class List(list, Static):
+ """
+ :meta private:
+ >>> x = List([1, 2, 3])
+ >>> is_static(x)
+ True
+ >>> x += [0] # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ SetuptoolsDeprecationWarning: Direct modification ...
+ >>> is_static(x) # no longer static after modification
+ False
+ >>> y = list(x)
+ >>> y.clear()
+ >>> y
+ []
+ >>> y == x
+ False
+ >>> is_static(List(y))
+ True
+ """
+
+
+# Make `List` immutable-ish
+# (certain places of setuptools/distutils issue a warn if we use tuple instead of list)
+for _method in (
+ '__delitem__',
+ '__iadd__',
+ '__setitem__',
+ 'append',
+ 'clear',
+ 'extend',
+ 'insert',
+ 'remove',
+ 'reverse',
+ 'pop',
+):
+ _prevent_modification(List, _method, "`list(value)`")
+
+
+class Dict(dict, Static):
+ """
+ :meta private:
+ >>> x = Dict({'a': 1, 'b': 2})
+ >>> is_static(x)
+ True
+ >>> x['c'] = 0 # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ SetuptoolsDeprecationWarning: Direct modification ...
+ >>> x._mutated_
+ True
+ >>> is_static(x) # no longer static after modification
+ False
+ >>> y = dict(x)
+ >>> y.popitem()
+ ('b', 2)
+ >>> y == x
+ False
+ >>> is_static(Dict(y))
+ True
+ """
+
+
+# Make `Dict` immutable-ish (we cannot inherit from types.MappingProxyType):
+for _method in (
+ '__delitem__',
+ '__ior__',
+ '__setitem__',
+ 'clear',
+ 'pop',
+ 'popitem',
+ 'setdefault',
+ 'update',
+):
+ _prevent_modification(Dict, _method, "`dict(value)`")
+
+
+class SpecifierSet(packaging.specifiers.SpecifierSet, Static):
+ """Not exactly a built-in type but useful for ``requires-python``"""
+
+
+T = TypeVar("T")
+
+
+def noop(value: T) -> T:
+ """
+ >>> noop(42)
+ 42
+ """
+ return value
+
+
+_CONVERSIONS = {str: Str, tuple: Tuple, list: List, dict: Dict}
+
+
+def attempt_conversion(value: T) -> T:
+ """
+ >>> is_static(attempt_conversion("hello"))
+ True
+ >>> is_static(object())
+ False
+ """
+ return _CONVERSIONS.get(type(value), noop)(value) # type: ignore[call-overload]
+
+
+def is_static(value: object) -> bool:
+ """
+ >>> is_static(a := Dict({'a': 1}))
+ True
+ >>> is_static(dict(a))
+ False
+ >>> is_static(b := List([1, 2, 3]))
+ True
+ >>> is_static(list(b))
+ False
+ """
+ return isinstance(value, Static) and not value._mutated_
+
+
+EMPTY_LIST = List()
+EMPTY_DICT = Dict()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/__pycache__/typing_extensions.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/__pycache__/typing_extensions.cpython-312.pyc
new file mode 100644
index 0000000..ffa656e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/__pycache__/typing_extensions.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/LICENSE
new file mode 100644
index 0000000..b49c3af
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/LICENSE
@@ -0,0 +1,166 @@
+GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
+
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/METADATA b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/METADATA
new file mode 100644
index 0000000..32214fb
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/METADATA
@@ -0,0 +1,420 @@
+Metadata-Version: 2.1
+Name: autocommand
+Version: 2.2.2
+Summary: A library to create a command-line program from a function
+Home-page: https://github.com/Lucretiel/autocommand
+Author: Nathan West
+License: LGPLv3
+Project-URL: Homepage, https://github.com/Lucretiel/autocommand
+Project-URL: Bug Tracker, https://github.com/Lucretiel/autocommand/issues
+Platform: any
+Classifier: Development Status :: 6 - Mature
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Topic :: Software Development
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Requires-Python: >=3.7
+Description-Content-Type: text/markdown
+License-File: LICENSE
+
+[](https://badge.fury.io/py/autocommand)
+
+# autocommand
+
+A library to automatically generate and run simple argparse parsers from function signatures.
+
+## Installation
+
+Autocommand is installed via pip:
+
+```
+$ pip install autocommand
+```
+
+## Usage
+
+Autocommand turns a function into a command-line program. It converts the function's parameter signature into command-line arguments, and automatically runs the function if the module was called as `__main__`. In effect, it lets your create a smart main function.
+
+```python
+from autocommand import autocommand
+
+# This program takes exactly one argument and echos it.
+@autocommand(__name__)
+def echo(thing):
+ print(thing)
+```
+
+```
+$ python echo.py hello
+hello
+$ python echo.py -h
+usage: echo [-h] thing
+
+positional arguments:
+ thing
+
+optional arguments:
+ -h, --help show this help message and exit
+$ python echo.py hello world # too many arguments
+usage: echo.py [-h] thing
+echo.py: error: unrecognized arguments: world
+```
+
+As you can see, autocommand converts the signature of the function into an argument spec. When you run the file as a program, autocommand collects the command-line arguments and turns them into function arguments. The function is executed with these arguments, and then the program exits with the return value of the function, via `sys.exit`. Autocommand also automatically creates a usage message, which can be invoked with `-h` or `--help`, and automatically prints an error message when provided with invalid arguments.
+
+### Types
+
+You can use a type annotation to give an argument a type. Any type (or in fact any callable) that returns an object when given a string argument can be used, though there are a few special cases that are described later.
+
+```python
+@autocommand(__name__)
+def net_client(host, port: int):
+ ...
+```
+
+Autocommand will catch `TypeErrors` raised by the type during argument parsing, so you can supply a callable and do some basic argument validation as well.
+
+### Trailing Arguments
+
+You can add a `*args` parameter to your function to give it trailing arguments. The command will collect 0 or more trailing arguments and supply them to `args` as a tuple. If a type annotation is supplied, the type is applied to each argument.
+
+```python
+# Write the contents of each file, one by one
+@autocommand(__name__)
+def cat(*files):
+ for filename in files:
+ with open(filename) as file:
+ for line in file:
+ print(line.rstrip())
+```
+
+```
+$ python cat.py -h
+usage: ipython [-h] [file [file ...]]
+
+positional arguments:
+ file
+
+optional arguments:
+ -h, --help show this help message and exit
+```
+
+### Options
+
+To create `--option` switches, just assign a default. Autocommand will automatically create `--long` and `-s`hort switches.
+
+```python
+@autocommand(__name__)
+def do_with_config(argument, config='~/foo.conf'):
+ pass
+```
+
+```
+$ python example.py -h
+usage: example.py [-h] [-c CONFIG] argument
+
+positional arguments:
+ argument
+
+optional arguments:
+ -h, --help show this help message and exit
+ -c CONFIG, --config CONFIG
+```
+
+The option's type is automatically deduced from the default, unless one is explicitly given in an annotation:
+
+```python
+@autocommand(__name__)
+def http_connect(host, port=80):
+ print('{}:{}'.format(host, port))
+```
+
+```
+$ python http.py -h
+usage: http.py [-h] [-p PORT] host
+
+positional arguments:
+ host
+
+optional arguments:
+ -h, --help show this help message and exit
+ -p PORT, --port PORT
+$ python http.py localhost
+localhost:80
+$ python http.py localhost -p 8080
+localhost:8080
+$ python http.py localhost -p blah
+usage: http.py [-h] [-p PORT] host
+http.py: error: argument -p/--port: invalid int value: 'blah'
+```
+
+#### None
+
+If an option is given a default value of `None`, it reads in a value as normal, but supplies `None` if the option isn't provided.
+
+#### Switches
+
+If an argument is given a default value of `True` or `False`, or
+given an explicit `bool` type, it becomes an option switch.
+
+```python
+ @autocommand(__name__)
+ def example(verbose=False, quiet=False):
+ pass
+```
+
+```
+$ python example.py -h
+usage: example.py [-h] [-v] [-q]
+
+optional arguments:
+ -h, --help show this help message and exit
+ -v, --verbose
+ -q, --quiet
+```
+
+Autocommand attempts to do the "correct thing" in these cases- if the default is `True`, then supplying the switch makes the argument `False`; if the type is `bool` and the default is some other `True` value, then supplying the switch makes the argument `False`, while not supplying the switch makes the argument the default value.
+
+Autocommand also supports the creation of switch inverters. Pass `add_nos=True` to `autocommand` to enable this.
+
+```
+ @autocommand(__name__, add_nos=True)
+ def example(verbose=False):
+ pass
+```
+
+```
+$ python example.py -h
+usage: ipython [-h] [-v] [--no-verbose]
+
+optional arguments:
+ -h, --help show this help message and exit
+ -v, --verbose
+ --no-verbose
+```
+
+Using the `--no-` version of a switch will pass the opposite value in as a function argument. If multiple switches are present, the last one takes precedence.
+
+#### Files
+
+If the default value is a file object, such as `sys.stdout`, then autocommand just looks for a string, for a file path. It doesn't do any special checking on the string, though (such as checking if the file exists); it's better to let the client decide how to handle errors in this case. Instead, it provides a special context manager called `smart_open`, which behaves exactly like `open` if a filename or other openable type is provided, but also lets you use already open files:
+
+```python
+from autocommand import autocommand, smart_open
+import sys
+
+# Write the contents of stdin, or a file, to stdout
+@autocommand(__name__)
+def write_out(infile=sys.stdin):
+ with smart_open(infile) as f:
+ for line in f:
+ print(line.rstrip())
+ # If a file was opened, it is closed here. If it was just stdin, it is untouched.
+```
+
+```
+$ echo "Hello World!" | python write_out.py | tee hello.txt
+Hello World!
+$ python write_out.py --infile hello.txt
+Hello World!
+```
+
+### Descriptions and docstrings
+
+The `autocommand` decorator accepts `description` and `epilog` kwargs, corresponding to the `description `_ and `epilog `_ of the `ArgumentParser`. If no description is given, but the decorated function has a docstring, then it is taken as the `description` for the `ArgumentParser`. You can also provide both the description and epilog in the docstring by splitting it into two sections with 4 or more - characters.
+
+```python
+@autocommand(__name__)
+def copy(infile=sys.stdin, outfile=sys.stdout):
+ '''
+ Copy an the contents of a file (or stdin) to another file (or stdout)
+ ----------
+ Some extra documentation in the epilog
+ '''
+ with smart_open(infile) as istr:
+ with smart_open(outfile, 'w') as ostr:
+ for line in istr:
+ ostr.write(line)
+```
+
+```
+$ python copy.py -h
+usage: copy.py [-h] [-i INFILE] [-o OUTFILE]
+
+Copy an the contents of a file (or stdin) to another file (or stdout)
+
+optional arguments:
+ -h, --help show this help message and exit
+ -i INFILE, --infile INFILE
+ -o OUTFILE, --outfile OUTFILE
+
+Some extra documentation in the epilog
+$ echo "Hello World" | python copy.py --outfile hello.txt
+$ python copy.py --infile hello.txt --outfile hello2.txt
+$ python copy.py --infile hello2.txt
+Hello World
+```
+
+### Parameter descriptions
+
+You can also attach description text to individual parameters in the annotation. To attach both a type and a description, supply them both in any order in a tuple
+
+```python
+@autocommand(__name__)
+def copy_net(
+ infile: 'The name of the file to send',
+ host: 'The host to send the file to',
+ port: (int, 'The port to connect to')):
+
+ '''
+ Copy a file over raw TCP to a remote destination.
+ '''
+ # Left as an exercise to the reader
+```
+
+### Decorators and wrappers
+
+Autocommand automatically follows wrapper chains created by `@functools.wraps`. This means that you can apply other wrapping decorators to your main function, and autocommand will still correctly detect the signature.
+
+```python
+from functools import wraps
+from autocommand import autocommand
+
+def print_yielded(func):
+ '''
+ Convert a generator into a function that prints all yielded elements
+ '''
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ for thing in func(*args, **kwargs):
+ print(thing)
+ return wrapper
+
+@autocommand(__name__,
+ description= 'Print all the values from START to STOP, inclusive, in steps of STEP',
+ epilog= 'STOP and STEP default to 1')
+@print_yielded
+def seq(stop, start=1, step=1):
+ for i in range(start, stop + 1, step):
+ yield i
+```
+
+```
+$ seq.py -h
+usage: seq.py [-h] [-s START] [-S STEP] stop
+
+Print all the values from START to STOP, inclusive, in steps of STEP
+
+positional arguments:
+ stop
+
+optional arguments:
+ -h, --help show this help message and exit
+ -s START, --start START
+ -S STEP, --step STEP
+
+STOP and STEP default to 1
+```
+
+Even though autocommand is being applied to the `wrapper` returned by `print_yielded`, it still retreives the signature of the underlying `seq` function to create the argument parsing.
+
+### Custom Parser
+
+While autocommand's automatic parser generator is a powerful convenience, it doesn't cover all of the different features that argparse provides. If you need these features, you can provide your own parser as a kwarg to `autocommand`:
+
+```python
+from argparse import ArgumentParser
+from autocommand import autocommand
+
+parser = ArgumentParser()
+# autocommand can't do optional positonal parameters
+parser.add_argument('arg', nargs='?')
+# or mutually exclusive options
+group = parser.add_mutually_exclusive_group()
+group.add_argument('-v', '--verbose', action='store_true')
+group.add_argument('-q', '--quiet', action='store_true')
+
+@autocommand(__name__, parser=parser)
+def main(arg, verbose, quiet):
+ print(arg, verbose, quiet)
+```
+
+```
+$ python parser.py -h
+usage: write_file.py [-h] [-v | -q] [arg]
+
+positional arguments:
+ arg
+
+optional arguments:
+ -h, --help show this help message and exit
+ -v, --verbose
+ -q, --quiet
+$ python parser.py
+None False False
+$ python parser.py hello
+hello False False
+$ python parser.py -v
+None True False
+$ python parser.py -q
+None False True
+$ python parser.py -vq
+usage: parser.py [-h] [-v | -q] [arg]
+parser.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
+```
+
+Any parser should work fine, so long as each of the parser's arguments has a corresponding parameter in the decorated main function. The order of parameters doesn't matter, as long as they are all present. Note that when using a custom parser, autocommand doesn't modify the parser or the retrieved arguments. This means that no description/epilog will be added, and the function's type annotations and defaults (if present) will be ignored.
+
+## Testing and Library use
+
+The decorated function is only called and exited from if the first argument to `autocommand` is `'__main__'` or `True`. If it is neither of these values, or no argument is given, then a new main function is created by the decorator. This function has the signature `main(argv=None)`, and is intended to be called with arguments as if via `main(sys.argv[1:])`. The function has the attributes `parser` and `main`, which are the generated `ArgumentParser` and the original main function that was decorated. This is to facilitate testing and library use of your main. Calling the function triggers a `parse_args()` with the supplied arguments, and returns the result of the main function. Note that, while it returns instead of calling `sys.exit`, the `parse_args()` function will raise a `SystemExit` in the event of a parsing error or `-h/--help` argument.
+
+```python
+ @autocommand()
+ def test_prog(arg1, arg2: int, quiet=False, verbose=False):
+ if not quiet:
+ print(arg1, arg2)
+ if verbose:
+ print("LOUD NOISES")
+
+ return 0
+
+ print(test_prog(['-v', 'hello', '80']))
+```
+
+```
+$ python test_prog.py
+hello 80
+LOUD NOISES
+0
+```
+
+If the function is called with no arguments, `sys.argv[1:]` is used. This is to allow the autocommand function to be used as a setuptools entry point.
+
+## Exceptions and limitations
+
+- There are a few possible exceptions that `autocommand` can raise. All of them derive from `autocommand.AutocommandError`.
+
+ - If an invalid annotation is given (that is, it isn't a `type`, `str`, `(type, str)`, or `(str, type)`, an `AnnotationError` is raised. The `type` may be any callable, as described in the `Types`_ section.
+ - If the function has a `**kwargs` parameter, a `KWargError` is raised.
+ - If, somehow, the function has a positional-only parameter, a `PositionalArgError` is raised. This means that the argument doesn't have a name, which is currently not possible with a plain `def` or `lambda`, though many built-in functions have this kind of parameter.
+
+- There are a few argparse features that are not supported by autocommand.
+
+ - It isn't possible to have an optional positional argument (as opposed to a `--option`). POSIX thinks this is bad form anyway.
+ - It isn't possible to have mutually exclusive arguments or options
+ - It isn't possible to have subcommands or subparsers, though I'm working on a few solutions involving classes or nested function definitions to allow this.
+
+## Development
+
+Autocommand cannot be important from the project root; this is to enforce separation of concerns and prevent accidental importing of `setup.py` or tests. To develop, install the project in editable mode:
+
+```
+$ python setup.py develop
+```
+
+This will create a link to the source files in the deployment directory, so that any source changes are reflected when it is imported.
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/RECORD b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/RECORD
new file mode 100644
index 0000000..e6e12ea
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/RECORD
@@ -0,0 +1,18 @@
+autocommand-2.2.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+autocommand-2.2.2.dist-info/LICENSE,sha256=reeNBJgtaZctREqOFKlPh6IzTdOFXMgDSOqOJAqg3y0,7634
+autocommand-2.2.2.dist-info/METADATA,sha256=OADZuR3O6iBlpu1ieTgzYul6w4uOVrk0P0BO5TGGAJk,15006
+autocommand-2.2.2.dist-info/RECORD,,
+autocommand-2.2.2.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
+autocommand-2.2.2.dist-info/top_level.txt,sha256=AzfhgKKS8EdAwWUTSF8mgeVQbXOY9kokHB6kSqwwqu0,12
+autocommand/__init__.py,sha256=zko5Rnvolvb-UXjCx_2ArPTGBWwUK5QY4LIQIKYR7As,1037
+autocommand/__pycache__/__init__.cpython-312.pyc,,
+autocommand/__pycache__/autoasync.cpython-312.pyc,,
+autocommand/__pycache__/autocommand.cpython-312.pyc,,
+autocommand/__pycache__/automain.cpython-312.pyc,,
+autocommand/__pycache__/autoparse.cpython-312.pyc,,
+autocommand/__pycache__/errors.cpython-312.pyc,,
+autocommand/autoasync.py,sha256=AMdyrxNS4pqWJfP_xuoOcImOHWD-qT7x06wmKN1Vp-U,5680
+autocommand/autocommand.py,sha256=hmkEmQ72HtL55gnURVjDOnsfYlGd5lLXbvT4KG496Qw,2505
+autocommand/automain.py,sha256=A2b8i754Mxc_DjU9WFr6vqYDWlhz0cn8miu8d8EsxV8,2076
+autocommand/autoparse.py,sha256=WVWmZJPcbzUKXP40raQw_0HD8qPJ2V9VG1eFFmmnFxw,11642
+autocommand/errors.py,sha256=7aa3roh9Herd6nIKpQHNWEslWE8oq7GiHYVUuRqORnA,886
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/WHEEL
new file mode 100644
index 0000000..57e3d84
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.38.4)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/top_level.txt
new file mode 100644
index 0000000..dda5158
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand-2.2.2.dist-info/top_level.txt
@@ -0,0 +1 @@
+autocommand
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__init__.py
new file mode 100644
index 0000000..73fbfca
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__init__.py
@@ -0,0 +1,27 @@
+# Copyright 2014-2016 Nathan West
+#
+# This file is part of autocommand.
+#
+# autocommand is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# autocommand is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with autocommand. If not, see .
+
+# flake8 flags all these imports as unused, hence the NOQAs everywhere.
+
+from .automain import automain # NOQA
+from .autoparse import autoparse, smart_open # NOQA
+from .autocommand import autocommand # NOQA
+
+try:
+ from .autoasync import autoasync # NOQA
+except ImportError: # pragma: no cover
+ pass
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..18d5b6f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/autoasync.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/autoasync.cpython-312.pyc
new file mode 100644
index 0000000..41d1f09
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/autoasync.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/autocommand.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/autocommand.cpython-312.pyc
new file mode 100644
index 0000000..0de5f8d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/autocommand.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/automain.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/automain.cpython-312.pyc
new file mode 100644
index 0000000..e636a5c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/automain.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/autoparse.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/autoparse.cpython-312.pyc
new file mode 100644
index 0000000..0c6ef1b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/autoparse.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/errors.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/errors.cpython-312.pyc
new file mode 100644
index 0000000..7dac0b7
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/__pycache__/errors.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/autoasync.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/autoasync.py
new file mode 100644
index 0000000..688f7e0
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/autoasync.py
@@ -0,0 +1,142 @@
+# Copyright 2014-2015 Nathan West
+#
+# This file is part of autocommand.
+#
+# autocommand is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# autocommand is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with autocommand. If not, see .
+
+from asyncio import get_event_loop, iscoroutine
+from functools import wraps
+from inspect import signature
+
+
+async def _run_forever_coro(coro, args, kwargs, loop):
+ '''
+ This helper function launches an async main function that was tagged with
+ forever=True. There are two possibilities:
+
+ - The function is a normal function, which handles initializing the event
+ loop, which is then run forever
+ - The function is a coroutine, which needs to be scheduled in the event
+ loop, which is then run forever
+ - There is also the possibility that the function is a normal function
+ wrapping a coroutine function
+
+ The function is therefore called unconditionally and scheduled in the event
+ loop if the return value is a coroutine object.
+
+ The reason this is a separate function is to make absolutely sure that all
+ the objects created are garbage collected after all is said and done; we
+ do this to ensure that any exceptions raised in the tasks are collected
+ ASAP.
+ '''
+
+ # Personal note: I consider this an antipattern, as it relies on the use of
+ # unowned resources. The setup function dumps some stuff into the event
+ # loop where it just whirls in the ether without a well defined owner or
+ # lifetime. For this reason, there's a good chance I'll remove the
+ # forever=True feature from autoasync at some point in the future.
+ thing = coro(*args, **kwargs)
+ if iscoroutine(thing):
+ await thing
+
+
+def autoasync(coro=None, *, loop=None, forever=False, pass_loop=False):
+ '''
+ Convert an asyncio coroutine into a function which, when called, is
+ evaluted in an event loop, and the return value returned. This is intented
+ to make it easy to write entry points into asyncio coroutines, which
+ otherwise need to be explictly evaluted with an event loop's
+ run_until_complete.
+
+ If `loop` is given, it is used as the event loop to run the coro in. If it
+ is None (the default), the loop is retreived using asyncio.get_event_loop.
+ This call is defered until the decorated function is called, so that
+ callers can install custom event loops or event loop policies after
+ @autoasync is applied.
+
+ If `forever` is True, the loop is run forever after the decorated coroutine
+ is finished. Use this for servers created with asyncio.start_server and the
+ like.
+
+ If `pass_loop` is True, the event loop object is passed into the coroutine
+ as the `loop` kwarg when the wrapper function is called. In this case, the
+ wrapper function's __signature__ is updated to remove this parameter, so
+ that autoparse can still be used on it without generating a parameter for
+ `loop`.
+
+ This coroutine can be called with ( @autoasync(...) ) or without
+ ( @autoasync ) arguments.
+
+ Examples:
+
+ @autoasync
+ def get_file(host, port):
+ reader, writer = yield from asyncio.open_connection(host, port)
+ data = reader.read()
+ sys.stdout.write(data.decode())
+
+ get_file(host, port)
+
+ @autoasync(forever=True, pass_loop=True)
+ def server(host, port, loop):
+ yield_from loop.create_server(Proto, host, port)
+
+ server('localhost', 8899)
+
+ '''
+ if coro is None:
+ return lambda c: autoasync(
+ c, loop=loop,
+ forever=forever,
+ pass_loop=pass_loop)
+
+ # The old and new signatures are required to correctly bind the loop
+ # parameter in 100% of cases, even if it's a positional parameter.
+ # NOTE: A future release will probably require the loop parameter to be
+ # a kwonly parameter.
+ if pass_loop:
+ old_sig = signature(coro)
+ new_sig = old_sig.replace(parameters=(
+ param for name, param in old_sig.parameters.items()
+ if name != "loop"))
+
+ @wraps(coro)
+ def autoasync_wrapper(*args, **kwargs):
+ # Defer the call to get_event_loop so that, if a custom policy is
+ # installed after the autoasync decorator, it is respected at call time
+ local_loop = get_event_loop() if loop is None else loop
+
+ # Inject the 'loop' argument. We have to use this signature binding to
+ # ensure it's injected in the correct place (positional, keyword, etc)
+ if pass_loop:
+ bound_args = old_sig.bind_partial()
+ bound_args.arguments.update(
+ loop=local_loop,
+ **new_sig.bind(*args, **kwargs).arguments)
+ args, kwargs = bound_args.args, bound_args.kwargs
+
+ if forever:
+ local_loop.create_task(_run_forever_coro(
+ coro, args, kwargs, local_loop
+ ))
+ local_loop.run_forever()
+ else:
+ return local_loop.run_until_complete(coro(*args, **kwargs))
+
+ # Attach the updated signature. This allows 'pass_loop' to be used with
+ # autoparse
+ if pass_loop:
+ autoasync_wrapper.__signature__ = new_sig
+
+ return autoasync_wrapper
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/autocommand.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/autocommand.py
new file mode 100644
index 0000000..097e86d
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/autocommand.py
@@ -0,0 +1,70 @@
+# Copyright 2014-2015 Nathan West
+#
+# This file is part of autocommand.
+#
+# autocommand is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# autocommand is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with autocommand. If not, see .
+
+from .autoparse import autoparse
+from .automain import automain
+try:
+ from .autoasync import autoasync
+except ImportError: # pragma: no cover
+ pass
+
+
+def autocommand(
+ module, *,
+ description=None,
+ epilog=None,
+ add_nos=False,
+ parser=None,
+ loop=None,
+ forever=False,
+ pass_loop=False):
+
+ if callable(module):
+ raise TypeError('autocommand requires a module name argument')
+
+ def autocommand_decorator(func):
+ # Step 1: if requested, run it all in an asyncio event loop. autoasync
+ # patches the __signature__ of the decorated function, so that in the
+ # event that pass_loop is True, the `loop` parameter of the original
+ # function will *not* be interpreted as a command-line argument by
+ # autoparse
+ if loop is not None or forever or pass_loop:
+ func = autoasync(
+ func,
+ loop=None if loop is True else loop,
+ pass_loop=pass_loop,
+ forever=forever)
+
+ # Step 2: create parser. We do this second so that the arguments are
+ # parsed and passed *before* entering the asyncio event loop, if it
+ # exists. This simplifies the stack trace and ensures errors are
+ # reported earlier. It also ensures that errors raised during parsing &
+ # passing are still raised if `forever` is True.
+ func = autoparse(
+ func,
+ description=description,
+ epilog=epilog,
+ add_nos=add_nos,
+ parser=parser)
+
+ # Step 3: call the function automatically if __name__ == '__main__' (or
+ # if True was provided)
+ func = automain(module)(func)
+
+ return func
+
+ return autocommand_decorator
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/automain.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/automain.py
new file mode 100644
index 0000000..6cc45db
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/automain.py
@@ -0,0 +1,59 @@
+# Copyright 2014-2015 Nathan West
+#
+# This file is part of autocommand.
+#
+# autocommand is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# autocommand is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with autocommand. If not, see .
+
+import sys
+from .errors import AutocommandError
+
+
+class AutomainRequiresModuleError(AutocommandError, TypeError):
+ pass
+
+
+def automain(module, *, args=(), kwargs=None):
+ '''
+ This decorator automatically invokes a function if the module is being run
+ as the "__main__" module. Optionally, provide args or kwargs with which to
+ call the function. If `module` is "__main__", the function is called, and
+ the program is `sys.exit`ed with the return value. You can also pass `True`
+ to cause the function to be called unconditionally. If the function is not
+ called, it is returned unchanged by the decorator.
+
+ Usage:
+
+ @automain(__name__) # Pass __name__ to check __name__=="__main__"
+ def main():
+ ...
+
+ If __name__ is "__main__" here, the main function is called, and then
+ sys.exit called with the return value.
+ '''
+
+ # Check that @automain(...) was called, rather than @automain
+ if callable(module):
+ raise AutomainRequiresModuleError(module)
+
+ if module == '__main__' or module is True:
+ if kwargs is None:
+ kwargs = {}
+
+ # Use a function definition instead of a lambda for a neater traceback
+ def automain_decorator(main):
+ sys.exit(main(*args, **kwargs))
+
+ return automain_decorator
+ else:
+ return lambda main: main
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/autoparse.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/autoparse.py
new file mode 100644
index 0000000..0276a3f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/autoparse.py
@@ -0,0 +1,333 @@
+# Copyright 2014-2015 Nathan West
+#
+# This file is part of autocommand.
+#
+# autocommand is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# autocommand is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with autocommand. If not, see .
+
+import sys
+from re import compile as compile_regex
+from inspect import signature, getdoc, Parameter
+from argparse import ArgumentParser
+from contextlib import contextmanager
+from functools import wraps
+from io import IOBase
+from autocommand.errors import AutocommandError
+
+
+_empty = Parameter.empty
+
+
+class AnnotationError(AutocommandError):
+ '''Annotation error: annotation must be a string, type, or tuple of both'''
+
+
+class PositionalArgError(AutocommandError):
+ '''
+ Postional Arg Error: autocommand can't handle postional-only parameters
+ '''
+
+
+class KWArgError(AutocommandError):
+ '''kwarg Error: autocommand can't handle a **kwargs parameter'''
+
+
+class DocstringError(AutocommandError):
+ '''Docstring error'''
+
+
+class TooManySplitsError(DocstringError):
+ '''
+ The docstring had too many ---- section splits. Currently we only support
+ using up to a single split, to split the docstring into description and
+ epilog parts.
+ '''
+
+
+def _get_type_description(annotation):
+ '''
+ Given an annotation, return the (type, description) for the parameter.
+ If you provide an annotation that is somehow both a string and a callable,
+ the behavior is undefined.
+ '''
+ if annotation is _empty:
+ return None, None
+ elif callable(annotation):
+ return annotation, None
+ elif isinstance(annotation, str):
+ return None, annotation
+ elif isinstance(annotation, tuple):
+ try:
+ arg1, arg2 = annotation
+ except ValueError as e:
+ raise AnnotationError(annotation) from e
+ else:
+ if callable(arg1) and isinstance(arg2, str):
+ return arg1, arg2
+ elif isinstance(arg1, str) and callable(arg2):
+ return arg2, arg1
+
+ raise AnnotationError(annotation)
+
+
+def _add_arguments(param, parser, used_char_args, add_nos):
+ '''
+ Add the argument(s) to an ArgumentParser (using add_argument) for a given
+ parameter. used_char_args is the set of -short options currently already in
+ use, and is updated (if necessary) by this function. If add_nos is True,
+ this will also add an inverse switch for all boolean options. For
+ instance, for the boolean parameter "verbose", this will create --verbose
+ and --no-verbose.
+ '''
+
+ # Impl note: This function is kept separate from make_parser because it's
+ # already very long and I wanted to separate out as much as possible into
+ # its own call scope, to prevent even the possibility of suble mutation
+ # bugs.
+ if param.kind is param.POSITIONAL_ONLY:
+ raise PositionalArgError(param)
+ elif param.kind is param.VAR_KEYWORD:
+ raise KWArgError(param)
+
+ # These are the kwargs for the add_argument function.
+ arg_spec = {}
+ is_option = False
+
+ # Get the type and default from the annotation.
+ arg_type, description = _get_type_description(param.annotation)
+
+ # Get the default value
+ default = param.default
+
+ # If there is no explicit type, and the default is present and not None,
+ # infer the type from the default.
+ if arg_type is None and default not in {_empty, None}:
+ arg_type = type(default)
+
+ # Add default. The presence of a default means this is an option, not an
+ # argument.
+ if default is not _empty:
+ arg_spec['default'] = default
+ is_option = True
+
+ # Add the type
+ if arg_type is not None:
+ # Special case for bool: make it just a --switch
+ if arg_type is bool:
+ if not default or default is _empty:
+ arg_spec['action'] = 'store_true'
+ else:
+ arg_spec['action'] = 'store_false'
+
+ # Switches are always options
+ is_option = True
+
+ # Special case for file types: make it a string type, for filename
+ elif isinstance(default, IOBase):
+ arg_spec['type'] = str
+
+ # TODO: special case for list type.
+ # - How to specificy type of list members?
+ # - param: [int]
+ # - param: int =[]
+ # - action='append' vs nargs='*'
+
+ else:
+ arg_spec['type'] = arg_type
+
+ # nargs: if the signature includes *args, collect them as trailing CLI
+ # arguments in a list. *args can't have a default value, so it can never be
+ # an option.
+ if param.kind is param.VAR_POSITIONAL:
+ # TODO: consider depluralizing metavar/name here.
+ arg_spec['nargs'] = '*'
+
+ # Add description.
+ if description is not None:
+ arg_spec['help'] = description
+
+ # Get the --flags
+ flags = []
+ name = param.name
+
+ if is_option:
+ # Add the first letter as a -short option.
+ for letter in name[0], name[0].swapcase():
+ if letter not in used_char_args:
+ used_char_args.add(letter)
+ flags.append('-{}'.format(letter))
+ break
+
+ # If the parameter is a --long option, or is a -short option that
+ # somehow failed to get a flag, add it.
+ if len(name) > 1 or not flags:
+ flags.append('--{}'.format(name))
+
+ arg_spec['dest'] = name
+ else:
+ flags.append(name)
+
+ parser.add_argument(*flags, **arg_spec)
+
+ # Create the --no- version for boolean switches
+ if add_nos and arg_type is bool:
+ parser.add_argument(
+ '--no-{}'.format(name),
+ action='store_const',
+ dest=name,
+ const=default if default is not _empty else False)
+
+
+def make_parser(func_sig, description, epilog, add_nos):
+ '''
+ Given the signature of a function, create an ArgumentParser
+ '''
+ parser = ArgumentParser(description=description, epilog=epilog)
+
+ used_char_args = {'h'}
+
+ # Arange the params so that single-character arguments are first. This
+ # esnures they don't have to get --long versions. sorted is stable, so the
+ # parameters will otherwise still be in relative order.
+ params = sorted(
+ func_sig.parameters.values(),
+ key=lambda param: len(param.name) > 1)
+
+ for param in params:
+ _add_arguments(param, parser, used_char_args, add_nos)
+
+ return parser
+
+
+_DOCSTRING_SPLIT = compile_regex(r'\n\s*-{4,}\s*\n')
+
+
+def parse_docstring(docstring):
+ '''
+ Given a docstring, parse it into a description and epilog part
+ '''
+ if docstring is None:
+ return '', ''
+
+ parts = _DOCSTRING_SPLIT.split(docstring)
+
+ if len(parts) == 1:
+ return docstring, ''
+ elif len(parts) == 2:
+ return parts[0], parts[1]
+ else:
+ raise TooManySplitsError()
+
+
+def autoparse(
+ func=None, *,
+ description=None,
+ epilog=None,
+ add_nos=False,
+ parser=None):
+ '''
+ This decorator converts a function that takes normal arguments into a
+ function which takes a single optional argument, argv, parses it using an
+ argparse.ArgumentParser, and calls the underlying function with the parsed
+ arguments. If it is not given, sys.argv[1:] is used. This is so that the
+ function can be used as a setuptools entry point, as well as a normal main
+ function. sys.argv[1:] is not evaluated until the function is called, to
+ allow injecting different arguments for testing.
+
+ It uses the argument signature of the function to create an
+ ArgumentParser. Parameters without defaults become positional parameters,
+ while parameters *with* defaults become --options. Use annotations to set
+ the type of the parameter.
+
+ The `desctiption` and `epilog` parameters corrospond to the same respective
+ argparse parameters. If no description is given, it defaults to the
+ decorated functions's docstring, if present.
+
+ If add_nos is True, every boolean option (that is, every parameter with a
+ default of True/False or a type of bool) will have a --no- version created
+ as well, which inverts the option. For instance, the --verbose option will
+ have a --no-verbose counterpart. These are not mutually exclusive-
+ whichever one appears last in the argument list will have precedence.
+
+ If a parser is given, it is used instead of one generated from the function
+ signature. In this case, no parser is created; instead, the given parser is
+ used to parse the argv argument. The parser's results' argument names must
+ match up with the parameter names of the decorated function.
+
+ The decorated function is attached to the result as the `func` attribute,
+ and the parser is attached as the `parser` attribute.
+ '''
+
+ # If @autoparse(...) is used instead of @autoparse
+ if func is None:
+ return lambda f: autoparse(
+ f, description=description,
+ epilog=epilog,
+ add_nos=add_nos,
+ parser=parser)
+
+ func_sig = signature(func)
+
+ docstr_description, docstr_epilog = parse_docstring(getdoc(func))
+
+ if parser is None:
+ parser = make_parser(
+ func_sig,
+ description or docstr_description,
+ epilog or docstr_epilog,
+ add_nos)
+
+ @wraps(func)
+ def autoparse_wrapper(argv=None):
+ if argv is None:
+ argv = sys.argv[1:]
+
+ # Get empty argument binding, to fill with parsed arguments. This
+ # object does all the heavy lifting of turning named arguments into
+ # into correctly bound *args and **kwargs.
+ parsed_args = func_sig.bind_partial()
+ parsed_args.arguments.update(vars(parser.parse_args(argv)))
+
+ return func(*parsed_args.args, **parsed_args.kwargs)
+
+ # TODO: attach an updated __signature__ to autoparse_wrapper, just in case.
+
+ # Attach the wrapped function and parser, and return the wrapper.
+ autoparse_wrapper.func = func
+ autoparse_wrapper.parser = parser
+ return autoparse_wrapper
+
+
+@contextmanager
+def smart_open(filename_or_file, *args, **kwargs):
+ '''
+ This context manager allows you to open a filename, if you want to default
+ some already-existing file object, like sys.stdout, which shouldn't be
+ closed at the end of the context. If the filename argument is a str, bytes,
+ or int, the file object is created via a call to open with the given *args
+ and **kwargs, sent to the context, and closed at the end of the context,
+ just like "with open(filename) as f:". If it isn't one of the openable
+ types, the object simply sent to the context unchanged, and left unclosed
+ at the end of the context. Example:
+
+ def work_with_file(name=sys.stdout):
+ with smart_open(name) as f:
+ # Works correctly if name is a str filename or sys.stdout
+ print("Some stuff", file=f)
+ # If it was a filename, f is closed at the end here.
+ '''
+ if isinstance(filename_or_file, (str, bytes, int)):
+ with open(filename_or_file, *args, **kwargs) as file:
+ yield file
+ else:
+ yield filename_or_file
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/errors.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/errors.py
new file mode 100644
index 0000000..2570607
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/autocommand/errors.py
@@ -0,0 +1,23 @@
+# Copyright 2014-2016 Nathan West
+#
+# This file is part of autocommand.
+#
+# autocommand is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# autocommand is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with autocommand. If not, see .
+
+
+class AutocommandError(Exception):
+ '''Base class for autocommand exceptions'''
+ pass
+
+# Individual modules will define errors specific to that module.
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/LICENSE
new file mode 100644
index 0000000..1bb5a44
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/LICENSE
@@ -0,0 +1,17 @@
+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/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/METADATA b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/METADATA
new file mode 100644
index 0000000..db0a2dc
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/METADATA
@@ -0,0 +1,46 @@
+Metadata-Version: 2.1
+Name: backports.tarfile
+Version: 1.2.0
+Summary: Backport of CPython tarfile module
+Author-email: "Jason R. Coombs"
+Project-URL: Homepage, https://github.com/jaraco/backports.tarfile
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+Requires-Python: >=3.8
+Description-Content-Type: text/x-rst
+License-File: LICENSE
+Provides-Extra: docs
+Requires-Dist: sphinx >=3.5 ; extra == 'docs'
+Requires-Dist: jaraco.packaging >=9.3 ; extra == 'docs'
+Requires-Dist: rst.linker >=1.9 ; extra == 'docs'
+Requires-Dist: furo ; extra == 'docs'
+Requires-Dist: sphinx-lint ; extra == 'docs'
+Provides-Extra: testing
+Requires-Dist: pytest !=8.1.*,>=6 ; extra == 'testing'
+Requires-Dist: pytest-checkdocs >=2.4 ; extra == 'testing'
+Requires-Dist: pytest-cov ; extra == 'testing'
+Requires-Dist: pytest-enabler >=2.2 ; extra == 'testing'
+Requires-Dist: jaraco.test ; extra == 'testing'
+Requires-Dist: pytest !=8.0.* ; extra == 'testing'
+
+.. image:: https://img.shields.io/pypi/v/backports.tarfile.svg
+ :target: https://pypi.org/project/backports.tarfile
+
+.. image:: https://img.shields.io/pypi/pyversions/backports.tarfile.svg
+
+.. image:: https://github.com/jaraco/backports.tarfile/actions/workflows/main.yml/badge.svg
+ :target: https://github.com/jaraco/backports.tarfile/actions?query=workflow%3A%22tests%22
+ :alt: tests
+
+.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+ :target: https://github.com/astral-sh/ruff
+ :alt: Ruff
+
+.. .. image:: https://readthedocs.org/projects/backportstarfile/badge/?version=latest
+.. :target: https://backportstarfile.readthedocs.io/en/latest/?badge=latest
+
+.. image:: https://img.shields.io/badge/skeleton-2024-informational
+ :target: https://blog.jaraco.com/skeleton
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/RECORD b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/RECORD
new file mode 100644
index 0000000..536dc2f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/RECORD
@@ -0,0 +1,17 @@
+backports.tarfile-1.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+backports.tarfile-1.2.0.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+backports.tarfile-1.2.0.dist-info/METADATA,sha256=ghXFTq132dxaEIolxr3HK1mZqm9iyUmaRANZQSr6WlE,2020
+backports.tarfile-1.2.0.dist-info/RECORD,,
+backports.tarfile-1.2.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+backports.tarfile-1.2.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+backports.tarfile-1.2.0.dist-info/top_level.txt,sha256=cGjaLMOoBR1FK0ApojtzWVmViTtJ7JGIK_HwXiEsvtU,10
+backports/__init__.py,sha256=iOEMwnlORWezdO8-2vxBIPSR37D7JGjluZ8f55vzxls,81
+backports/__pycache__/__init__.cpython-312.pyc,,
+backports/tarfile/__init__.py,sha256=Pwf2qUIfB0SolJPCKcx3vz3UEu_aids4g4sAfxy94qg,108491
+backports/tarfile/__main__.py,sha256=Yw2oGT1afrz2eBskzdPYL8ReB_3liApmhFkN2EbDmc4,59
+backports/tarfile/__pycache__/__init__.cpython-312.pyc,,
+backports/tarfile/__pycache__/__main__.cpython-312.pyc,,
+backports/tarfile/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+backports/tarfile/compat/__pycache__/__init__.cpython-312.pyc,,
+backports/tarfile/compat/__pycache__/py38.cpython-312.pyc,,
+backports/tarfile/compat/py38.py,sha256=iYkyt_gvWjLzGUTJD9TuTfMMjOk-ersXZmRlvQYN2qE,568
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/REQUESTED b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/REQUESTED
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/WHEEL
new file mode 100644
index 0000000..bab98d6
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.43.0)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/top_level.txt
new file mode 100644
index 0000000..99d2be5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports.tarfile-1.2.0.dist-info/top_level.txt
@@ -0,0 +1 @@
+backports
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/__init__.py
new file mode 100644
index 0000000..0d1f7ed
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/__init__.py
@@ -0,0 +1 @@
+__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..867e09e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__init__.py
new file mode 100644
index 0000000..8c16881
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__init__.py
@@ -0,0 +1,2937 @@
+#-------------------------------------------------------------------
+# tarfile.py
+#-------------------------------------------------------------------
+# Copyright (C) 2002 Lars Gustaebel
+# All rights reserved.
+#
+# 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.
+#
+"""Read from and write to tar format archives.
+"""
+
+version = "0.9.0"
+__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)"
+__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend."
+
+#---------
+# Imports
+#---------
+from builtins import open as bltn_open
+import sys
+import os
+import io
+import shutil
+import stat
+import time
+import struct
+import copy
+import re
+
+from .compat.py38 import removesuffix
+
+try:
+ import pwd
+except ImportError:
+ pwd = None
+try:
+ import grp
+except ImportError:
+ grp = None
+
+# os.symlink on Windows prior to 6.0 raises NotImplementedError
+# OSError (winerror=1314) will be raised if the caller does not hold the
+# SeCreateSymbolicLinkPrivilege privilege
+symlink_exception = (AttributeError, NotImplementedError, OSError)
+
+# from tarfile import *
+__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError", "ReadError",
+ "CompressionError", "StreamError", "ExtractError", "HeaderError",
+ "ENCODING", "USTAR_FORMAT", "GNU_FORMAT", "PAX_FORMAT",
+ "DEFAULT_FORMAT", "open","fully_trusted_filter", "data_filter",
+ "tar_filter", "FilterError", "AbsoluteLinkError",
+ "OutsideDestinationError", "SpecialFileError", "AbsolutePathError",
+ "LinkOutsideDestinationError"]
+
+
+#---------------------------------------------------------
+# tar constants
+#---------------------------------------------------------
+NUL = b"\0" # the null character
+BLOCKSIZE = 512 # length of processing blocks
+RECORDSIZE = BLOCKSIZE * 20 # length of records
+GNU_MAGIC = b"ustar \0" # magic gnu tar string
+POSIX_MAGIC = b"ustar\x0000" # magic posix tar string
+
+LENGTH_NAME = 100 # maximum length of a filename
+LENGTH_LINK = 100 # maximum length of a linkname
+LENGTH_PREFIX = 155 # maximum length of the prefix field
+
+REGTYPE = b"0" # regular file
+AREGTYPE = b"\0" # regular file
+LNKTYPE = b"1" # link (inside tarfile)
+SYMTYPE = b"2" # symbolic link
+CHRTYPE = b"3" # character special device
+BLKTYPE = b"4" # block special device
+DIRTYPE = b"5" # directory
+FIFOTYPE = b"6" # fifo special device
+CONTTYPE = b"7" # contiguous file
+
+GNUTYPE_LONGNAME = b"L" # GNU tar longname
+GNUTYPE_LONGLINK = b"K" # GNU tar longlink
+GNUTYPE_SPARSE = b"S" # GNU tar sparse file
+
+XHDTYPE = b"x" # POSIX.1-2001 extended header
+XGLTYPE = b"g" # POSIX.1-2001 global header
+SOLARIS_XHDTYPE = b"X" # Solaris extended header
+
+USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format
+GNU_FORMAT = 1 # GNU tar format
+PAX_FORMAT = 2 # POSIX.1-2001 (pax) format
+DEFAULT_FORMAT = PAX_FORMAT
+
+#---------------------------------------------------------
+# tarfile constants
+#---------------------------------------------------------
+# File types that tarfile supports:
+SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE,
+ SYMTYPE, DIRTYPE, FIFOTYPE,
+ CONTTYPE, CHRTYPE, BLKTYPE,
+ GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
+ GNUTYPE_SPARSE)
+
+# File types that will be treated as a regular file.
+REGULAR_TYPES = (REGTYPE, AREGTYPE,
+ CONTTYPE, GNUTYPE_SPARSE)
+
+# File types that are part of the GNU tar format.
+GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK,
+ GNUTYPE_SPARSE)
+
+# Fields from a pax header that override a TarInfo attribute.
+PAX_FIELDS = ("path", "linkpath", "size", "mtime",
+ "uid", "gid", "uname", "gname")
+
+# Fields from a pax header that are affected by hdrcharset.
+PAX_NAME_FIELDS = {"path", "linkpath", "uname", "gname"}
+
+# Fields in a pax header that are numbers, all other fields
+# are treated as strings.
+PAX_NUMBER_FIELDS = {
+ "atime": float,
+ "ctime": float,
+ "mtime": float,
+ "uid": int,
+ "gid": int,
+ "size": int
+}
+
+#---------------------------------------------------------
+# initialization
+#---------------------------------------------------------
+if os.name == "nt":
+ ENCODING = "utf-8"
+else:
+ ENCODING = sys.getfilesystemencoding()
+
+#---------------------------------------------------------
+# Some useful functions
+#---------------------------------------------------------
+
+def stn(s, length, encoding, errors):
+ """Convert a string to a null-terminated bytes object.
+ """
+ if s is None:
+ raise ValueError("metadata cannot contain None")
+ s = s.encode(encoding, errors)
+ return s[:length] + (length - len(s)) * NUL
+
+def nts(s, encoding, errors):
+ """Convert a null-terminated bytes object to a string.
+ """
+ p = s.find(b"\0")
+ if p != -1:
+ s = s[:p]
+ return s.decode(encoding, errors)
+
+def nti(s):
+ """Convert a number field to a python number.
+ """
+ # There are two possible encodings for a number field, see
+ # itn() below.
+ if s[0] in (0o200, 0o377):
+ n = 0
+ for i in range(len(s) - 1):
+ n <<= 8
+ n += s[i + 1]
+ if s[0] == 0o377:
+ n = -(256 ** (len(s) - 1) - n)
+ else:
+ try:
+ s = nts(s, "ascii", "strict")
+ n = int(s.strip() or "0", 8)
+ except ValueError:
+ raise InvalidHeaderError("invalid header")
+ return n
+
+def itn(n, digits=8, format=DEFAULT_FORMAT):
+ """Convert a python number to a number field.
+ """
+ # POSIX 1003.1-1988 requires numbers to be encoded as a string of
+ # octal digits followed by a null-byte, this allows values up to
+ # (8**(digits-1))-1. GNU tar allows storing numbers greater than
+ # that if necessary. A leading 0o200 or 0o377 byte indicate this
+ # particular encoding, the following digits-1 bytes are a big-endian
+ # base-256 representation. This allows values up to (256**(digits-1))-1.
+ # A 0o200 byte indicates a positive number, a 0o377 byte a negative
+ # number.
+ original_n = n
+ n = int(n)
+ if 0 <= n < 8 ** (digits - 1):
+ s = bytes("%0*o" % (digits - 1, n), "ascii") + NUL
+ elif format == GNU_FORMAT and -256 ** (digits - 1) <= n < 256 ** (digits - 1):
+ if n >= 0:
+ s = bytearray([0o200])
+ else:
+ s = bytearray([0o377])
+ n = 256 ** digits + n
+
+ for i in range(digits - 1):
+ s.insert(1, n & 0o377)
+ n >>= 8
+ else:
+ raise ValueError("overflow in number field")
+
+ return s
+
+def calc_chksums(buf):
+ """Calculate the checksum for a member's header by summing up all
+ characters except for the chksum field which is treated as if
+ it was filled with spaces. According to the GNU tar sources,
+ some tars (Sun and NeXT) calculate chksum with signed char,
+ which will be different if there are chars in the buffer with
+ the high bit set. So we calculate two checksums, unsigned and
+ signed.
+ """
+ unsigned_chksum = 256 + sum(struct.unpack_from("148B8x356B", buf))
+ signed_chksum = 256 + sum(struct.unpack_from("148b8x356b", buf))
+ return unsigned_chksum, signed_chksum
+
+def copyfileobj(src, dst, length=None, exception=OSError, bufsize=None):
+ """Copy length bytes from fileobj src to fileobj dst.
+ If length is None, copy the entire content.
+ """
+ bufsize = bufsize or 16 * 1024
+ if length == 0:
+ return
+ if length is None:
+ shutil.copyfileobj(src, dst, bufsize)
+ return
+
+ blocks, remainder = divmod(length, bufsize)
+ for b in range(blocks):
+ buf = src.read(bufsize)
+ if len(buf) < bufsize:
+ raise exception("unexpected end of data")
+ dst.write(buf)
+
+ if remainder != 0:
+ buf = src.read(remainder)
+ if len(buf) < remainder:
+ raise exception("unexpected end of data")
+ dst.write(buf)
+ return
+
+def _safe_print(s):
+ encoding = getattr(sys.stdout, 'encoding', None)
+ if encoding is not None:
+ s = s.encode(encoding, 'backslashreplace').decode(encoding)
+ print(s, end=' ')
+
+
+class TarError(Exception):
+ """Base exception."""
+ pass
+class ExtractError(TarError):
+ """General exception for extract errors."""
+ pass
+class ReadError(TarError):
+ """Exception for unreadable tar archives."""
+ pass
+class CompressionError(TarError):
+ """Exception for unavailable compression methods."""
+ pass
+class StreamError(TarError):
+ """Exception for unsupported operations on stream-like TarFiles."""
+ pass
+class HeaderError(TarError):
+ """Base exception for header errors."""
+ pass
+class EmptyHeaderError(HeaderError):
+ """Exception for empty headers."""
+ pass
+class TruncatedHeaderError(HeaderError):
+ """Exception for truncated headers."""
+ pass
+class EOFHeaderError(HeaderError):
+ """Exception for end of file headers."""
+ pass
+class InvalidHeaderError(HeaderError):
+ """Exception for invalid headers."""
+ pass
+class SubsequentHeaderError(HeaderError):
+ """Exception for missing and invalid extended headers."""
+ pass
+
+#---------------------------
+# internal stream interface
+#---------------------------
+class _LowLevelFile:
+ """Low-level file object. Supports reading and writing.
+ It is used instead of a regular file object for streaming
+ access.
+ """
+
+ def __init__(self, name, mode):
+ mode = {
+ "r": os.O_RDONLY,
+ "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
+ }[mode]
+ if hasattr(os, "O_BINARY"):
+ mode |= os.O_BINARY
+ self.fd = os.open(name, mode, 0o666)
+
+ def close(self):
+ os.close(self.fd)
+
+ def read(self, size):
+ return os.read(self.fd, size)
+
+ def write(self, s):
+ os.write(self.fd, s)
+
+class _Stream:
+ """Class that serves as an adapter between TarFile and
+ a stream-like object. The stream-like object only
+ needs to have a read() or write() method that works with bytes,
+ and the method is accessed blockwise.
+ Use of gzip or bzip2 compression is possible.
+ A stream-like object could be for example: sys.stdin.buffer,
+ sys.stdout.buffer, a socket, a tape device etc.
+
+ _Stream is intended to be used only internally.
+ """
+
+ def __init__(self, name, mode, comptype, fileobj, bufsize,
+ compresslevel):
+ """Construct a _Stream object.
+ """
+ self._extfileobj = True
+ if fileobj is None:
+ fileobj = _LowLevelFile(name, mode)
+ self._extfileobj = False
+
+ if comptype == '*':
+ # Enable transparent compression detection for the
+ # stream interface
+ fileobj = _StreamProxy(fileobj)
+ comptype = fileobj.getcomptype()
+
+ self.name = name or ""
+ self.mode = mode
+ self.comptype = comptype
+ self.fileobj = fileobj
+ self.bufsize = bufsize
+ self.buf = b""
+ self.pos = 0
+ self.closed = False
+
+ try:
+ if comptype == "gz":
+ try:
+ import zlib
+ except ImportError:
+ raise CompressionError("zlib module is not available") from None
+ self.zlib = zlib
+ self.crc = zlib.crc32(b"")
+ if mode == "r":
+ self.exception = zlib.error
+ self._init_read_gz()
+ else:
+ self._init_write_gz(compresslevel)
+
+ elif comptype == "bz2":
+ try:
+ import bz2
+ except ImportError:
+ raise CompressionError("bz2 module is not available") from None
+ if mode == "r":
+ self.dbuf = b""
+ self.cmp = bz2.BZ2Decompressor()
+ self.exception = OSError
+ else:
+ self.cmp = bz2.BZ2Compressor(compresslevel)
+
+ elif comptype == "xz":
+ try:
+ import lzma
+ except ImportError:
+ raise CompressionError("lzma module is not available") from None
+ if mode == "r":
+ self.dbuf = b""
+ self.cmp = lzma.LZMADecompressor()
+ self.exception = lzma.LZMAError
+ else:
+ self.cmp = lzma.LZMACompressor()
+
+ elif comptype != "tar":
+ raise CompressionError("unknown compression type %r" % comptype)
+
+ except:
+ if not self._extfileobj:
+ self.fileobj.close()
+ self.closed = True
+ raise
+
+ def __del__(self):
+ if hasattr(self, "closed") and not self.closed:
+ self.close()
+
+ def _init_write_gz(self, compresslevel):
+ """Initialize for writing with gzip compression.
+ """
+ self.cmp = self.zlib.compressobj(compresslevel,
+ self.zlib.DEFLATED,
+ -self.zlib.MAX_WBITS,
+ self.zlib.DEF_MEM_LEVEL,
+ 0)
+ timestamp = struct.pack(" self.bufsize:
+ self.fileobj.write(self.buf[:self.bufsize])
+ self.buf = self.buf[self.bufsize:]
+
+ def close(self):
+ """Close the _Stream object. No operation should be
+ done on it afterwards.
+ """
+ if self.closed:
+ return
+
+ self.closed = True
+ try:
+ if self.mode == "w" and self.comptype != "tar":
+ self.buf += self.cmp.flush()
+
+ if self.mode == "w" and self.buf:
+ self.fileobj.write(self.buf)
+ self.buf = b""
+ if self.comptype == "gz":
+ self.fileobj.write(struct.pack("= 0:
+ blocks, remainder = divmod(pos - self.pos, self.bufsize)
+ for i in range(blocks):
+ self.read(self.bufsize)
+ self.read(remainder)
+ else:
+ raise StreamError("seeking backwards is not allowed")
+ return self.pos
+
+ def read(self, size):
+ """Return the next size number of bytes from the stream."""
+ assert size is not None
+ buf = self._read(size)
+ self.pos += len(buf)
+ return buf
+
+ def _read(self, size):
+ """Return size bytes from the stream.
+ """
+ if self.comptype == "tar":
+ return self.__read(size)
+
+ c = len(self.dbuf)
+ t = [self.dbuf]
+ while c < size:
+ # Skip underlying buffer to avoid unaligned double buffering.
+ if self.buf:
+ buf = self.buf
+ self.buf = b""
+ else:
+ buf = self.fileobj.read(self.bufsize)
+ if not buf:
+ break
+ try:
+ buf = self.cmp.decompress(buf)
+ except self.exception as e:
+ raise ReadError("invalid compressed data") from e
+ t.append(buf)
+ c += len(buf)
+ t = b"".join(t)
+ self.dbuf = t[size:]
+ return t[:size]
+
+ def __read(self, size):
+ """Return size bytes from stream. If internal buffer is empty,
+ read another block from the stream.
+ """
+ c = len(self.buf)
+ t = [self.buf]
+ while c < size:
+ buf = self.fileobj.read(self.bufsize)
+ if not buf:
+ break
+ t.append(buf)
+ c += len(buf)
+ t = b"".join(t)
+ self.buf = t[size:]
+ return t[:size]
+# class _Stream
+
+class _StreamProxy(object):
+ """Small proxy class that enables transparent compression
+ detection for the Stream interface (mode 'r|*').
+ """
+
+ def __init__(self, fileobj):
+ self.fileobj = fileobj
+ self.buf = self.fileobj.read(BLOCKSIZE)
+
+ def read(self, size):
+ self.read = self.fileobj.read
+ return self.buf
+
+ def getcomptype(self):
+ if self.buf.startswith(b"\x1f\x8b\x08"):
+ return "gz"
+ elif self.buf[0:3] == b"BZh" and self.buf[4:10] == b"1AY&SY":
+ return "bz2"
+ elif self.buf.startswith((b"\x5d\x00\x00\x80", b"\xfd7zXZ")):
+ return "xz"
+ else:
+ return "tar"
+
+ def close(self):
+ self.fileobj.close()
+# class StreamProxy
+
+#------------------------
+# Extraction file object
+#------------------------
+class _FileInFile(object):
+ """A thin wrapper around an existing file object that
+ provides a part of its data as an individual file
+ object.
+ """
+
+ def __init__(self, fileobj, offset, size, name, blockinfo=None):
+ self.fileobj = fileobj
+ self.offset = offset
+ self.size = size
+ self.position = 0
+ self.name = name
+ self.closed = False
+
+ if blockinfo is None:
+ blockinfo = [(0, size)]
+
+ # Construct a map with data and zero blocks.
+ self.map_index = 0
+ self.map = []
+ lastpos = 0
+ realpos = self.offset
+ for offset, size in blockinfo:
+ if offset > lastpos:
+ self.map.append((False, lastpos, offset, None))
+ self.map.append((True, offset, offset + size, realpos))
+ realpos += size
+ lastpos = offset + size
+ if lastpos < self.size:
+ self.map.append((False, lastpos, self.size, None))
+
+ def flush(self):
+ pass
+
+ @property
+ def mode(self):
+ return 'rb'
+
+ def readable(self):
+ return True
+
+ def writable(self):
+ return False
+
+ def seekable(self):
+ return self.fileobj.seekable()
+
+ def tell(self):
+ """Return the current file position.
+ """
+ return self.position
+
+ def seek(self, position, whence=io.SEEK_SET):
+ """Seek to a position in the file.
+ """
+ if whence == io.SEEK_SET:
+ self.position = min(max(position, 0), self.size)
+ elif whence == io.SEEK_CUR:
+ if position < 0:
+ self.position = max(self.position + position, 0)
+ else:
+ self.position = min(self.position + position, self.size)
+ elif whence == io.SEEK_END:
+ self.position = max(min(self.size + position, self.size), 0)
+ else:
+ raise ValueError("Invalid argument")
+ return self.position
+
+ def read(self, size=None):
+ """Read data from the file.
+ """
+ if size is None:
+ size = self.size - self.position
+ else:
+ size = min(size, self.size - self.position)
+
+ buf = b""
+ while size > 0:
+ while True:
+ data, start, stop, offset = self.map[self.map_index]
+ if start <= self.position < stop:
+ break
+ else:
+ self.map_index += 1
+ if self.map_index == len(self.map):
+ self.map_index = 0
+ length = min(size, stop - self.position)
+ if data:
+ self.fileobj.seek(offset + (self.position - start))
+ b = self.fileobj.read(length)
+ if len(b) != length:
+ raise ReadError("unexpected end of data")
+ buf += b
+ else:
+ buf += NUL * length
+ size -= length
+ self.position += length
+ return buf
+
+ def readinto(self, b):
+ buf = self.read(len(b))
+ b[:len(buf)] = buf
+ return len(buf)
+
+ def close(self):
+ self.closed = True
+#class _FileInFile
+
+class ExFileObject(io.BufferedReader):
+
+ def __init__(self, tarfile, tarinfo):
+ fileobj = _FileInFile(tarfile.fileobj, tarinfo.offset_data,
+ tarinfo.size, tarinfo.name, tarinfo.sparse)
+ super().__init__(fileobj)
+#class ExFileObject
+
+
+#-----------------------------
+# extraction filters (PEP 706)
+#-----------------------------
+
+class FilterError(TarError):
+ pass
+
+class AbsolutePathError(FilterError):
+ def __init__(self, tarinfo):
+ self.tarinfo = tarinfo
+ super().__init__(f'member {tarinfo.name!r} has an absolute path')
+
+class OutsideDestinationError(FilterError):
+ def __init__(self, tarinfo, path):
+ self.tarinfo = tarinfo
+ self._path = path
+ super().__init__(f'{tarinfo.name!r} would be extracted to {path!r}, '
+ + 'which is outside the destination')
+
+class SpecialFileError(FilterError):
+ def __init__(self, tarinfo):
+ self.tarinfo = tarinfo
+ super().__init__(f'{tarinfo.name!r} is a special file')
+
+class AbsoluteLinkError(FilterError):
+ def __init__(self, tarinfo):
+ self.tarinfo = tarinfo
+ super().__init__(f'{tarinfo.name!r} is a link to an absolute path')
+
+class LinkOutsideDestinationError(FilterError):
+ def __init__(self, tarinfo, path):
+ self.tarinfo = tarinfo
+ self._path = path
+ super().__init__(f'{tarinfo.name!r} would link to {path!r}, '
+ + 'which is outside the destination')
+
+def _get_filtered_attrs(member, dest_path, for_data=True):
+ new_attrs = {}
+ name = member.name
+ dest_path = os.path.realpath(dest_path)
+ # Strip leading / (tar's directory separator) from filenames.
+ # Include os.sep (target OS directory separator) as well.
+ if name.startswith(('/', os.sep)):
+ name = new_attrs['name'] = member.path.lstrip('/' + os.sep)
+ if os.path.isabs(name):
+ # Path is absolute even after stripping.
+ # For example, 'C:/foo' on Windows.
+ raise AbsolutePathError(member)
+ # Ensure we stay in the destination
+ target_path = os.path.realpath(os.path.join(dest_path, name))
+ if os.path.commonpath([target_path, dest_path]) != dest_path:
+ raise OutsideDestinationError(member, target_path)
+ # Limit permissions (no high bits, and go-w)
+ mode = member.mode
+ if mode is not None:
+ # Strip high bits & group/other write bits
+ mode = mode & 0o755
+ if for_data:
+ # For data, handle permissions & file types
+ if member.isreg() or member.islnk():
+ if not mode & 0o100:
+ # Clear executable bits if not executable by user
+ mode &= ~0o111
+ # Ensure owner can read & write
+ mode |= 0o600
+ elif member.isdir() or member.issym():
+ # Ignore mode for directories & symlinks
+ mode = None
+ else:
+ # Reject special files
+ raise SpecialFileError(member)
+ if mode != member.mode:
+ new_attrs['mode'] = mode
+ if for_data:
+ # Ignore ownership for 'data'
+ if member.uid is not None:
+ new_attrs['uid'] = None
+ if member.gid is not None:
+ new_attrs['gid'] = None
+ if member.uname is not None:
+ new_attrs['uname'] = None
+ if member.gname is not None:
+ new_attrs['gname'] = None
+ # Check link destination for 'data'
+ if member.islnk() or member.issym():
+ if os.path.isabs(member.linkname):
+ raise AbsoluteLinkError(member)
+ if member.issym():
+ target_path = os.path.join(dest_path,
+ os.path.dirname(name),
+ member.linkname)
+ else:
+ target_path = os.path.join(dest_path,
+ member.linkname)
+ target_path = os.path.realpath(target_path)
+ if os.path.commonpath([target_path, dest_path]) != dest_path:
+ raise LinkOutsideDestinationError(member, target_path)
+ return new_attrs
+
+def fully_trusted_filter(member, dest_path):
+ return member
+
+def tar_filter(member, dest_path):
+ new_attrs = _get_filtered_attrs(member, dest_path, False)
+ if new_attrs:
+ return member.replace(**new_attrs, deep=False)
+ return member
+
+def data_filter(member, dest_path):
+ new_attrs = _get_filtered_attrs(member, dest_path, True)
+ if new_attrs:
+ return member.replace(**new_attrs, deep=False)
+ return member
+
+_NAMED_FILTERS = {
+ "fully_trusted": fully_trusted_filter,
+ "tar": tar_filter,
+ "data": data_filter,
+}
+
+#------------------
+# Exported Classes
+#------------------
+
+# Sentinel for replace() defaults, meaning "don't change the attribute"
+_KEEP = object()
+
+class TarInfo(object):
+ """Informational class which holds the details about an
+ archive member given by a tar header block.
+ TarInfo objects are returned by TarFile.getmember(),
+ TarFile.getmembers() and TarFile.gettarinfo() and are
+ usually created internally.
+ """
+
+ __slots__ = dict(
+ name = 'Name of the archive member.',
+ mode = 'Permission bits.',
+ uid = 'User ID of the user who originally stored this member.',
+ gid = 'Group ID of the user who originally stored this member.',
+ size = 'Size in bytes.',
+ mtime = 'Time of last modification.',
+ chksum = 'Header checksum.',
+ type = ('File type. type is usually one of these constants: '
+ 'REGTYPE, AREGTYPE, LNKTYPE, SYMTYPE, DIRTYPE, FIFOTYPE, '
+ 'CONTTYPE, CHRTYPE, BLKTYPE, GNUTYPE_SPARSE.'),
+ linkname = ('Name of the target file name, which is only present '
+ 'in TarInfo objects of type LNKTYPE and SYMTYPE.'),
+ uname = 'User name.',
+ gname = 'Group name.',
+ devmajor = 'Device major number.',
+ devminor = 'Device minor number.',
+ offset = 'The tar header starts here.',
+ offset_data = "The file's data starts here.",
+ pax_headers = ('A dictionary containing key-value pairs of an '
+ 'associated pax extended header.'),
+ sparse = 'Sparse member information.',
+ _tarfile = None,
+ _sparse_structs = None,
+ _link_target = None,
+ )
+
+ def __init__(self, name=""):
+ """Construct a TarInfo object. name is the optional name
+ of the member.
+ """
+ self.name = name # member name
+ self.mode = 0o644 # file permissions
+ self.uid = 0 # user id
+ self.gid = 0 # group id
+ self.size = 0 # file size
+ self.mtime = 0 # modification time
+ self.chksum = 0 # header checksum
+ self.type = REGTYPE # member type
+ self.linkname = "" # link name
+ self.uname = "" # user name
+ self.gname = "" # group name
+ self.devmajor = 0 # device major number
+ self.devminor = 0 # device minor number
+
+ self.offset = 0 # the tar header starts here
+ self.offset_data = 0 # the file's data starts here
+
+ self.sparse = None # sparse member information
+ self.pax_headers = {} # pax header information
+
+ @property
+ def tarfile(self):
+ import warnings
+ warnings.warn(
+ 'The undocumented "tarfile" attribute of TarInfo objects '
+ + 'is deprecated and will be removed in Python 3.16',
+ DeprecationWarning, stacklevel=2)
+ return self._tarfile
+
+ @tarfile.setter
+ def tarfile(self, tarfile):
+ import warnings
+ warnings.warn(
+ 'The undocumented "tarfile" attribute of TarInfo objects '
+ + 'is deprecated and will be removed in Python 3.16',
+ DeprecationWarning, stacklevel=2)
+ self._tarfile = tarfile
+
+ @property
+ def path(self):
+ 'In pax headers, "name" is called "path".'
+ return self.name
+
+ @path.setter
+ def path(self, name):
+ self.name = name
+
+ @property
+ def linkpath(self):
+ 'In pax headers, "linkname" is called "linkpath".'
+ return self.linkname
+
+ @linkpath.setter
+ def linkpath(self, linkname):
+ self.linkname = linkname
+
+ def __repr__(self):
+ return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self))
+
+ def replace(self, *,
+ name=_KEEP, mtime=_KEEP, mode=_KEEP, linkname=_KEEP,
+ uid=_KEEP, gid=_KEEP, uname=_KEEP, gname=_KEEP,
+ deep=True, _KEEP=_KEEP):
+ """Return a deep copy of self with the given attributes replaced.
+ """
+ if deep:
+ result = copy.deepcopy(self)
+ else:
+ result = copy.copy(self)
+ if name is not _KEEP:
+ result.name = name
+ if mtime is not _KEEP:
+ result.mtime = mtime
+ if mode is not _KEEP:
+ result.mode = mode
+ if linkname is not _KEEP:
+ result.linkname = linkname
+ if uid is not _KEEP:
+ result.uid = uid
+ if gid is not _KEEP:
+ result.gid = gid
+ if uname is not _KEEP:
+ result.uname = uname
+ if gname is not _KEEP:
+ result.gname = gname
+ return result
+
+ def get_info(self):
+ """Return the TarInfo's attributes as a dictionary.
+ """
+ if self.mode is None:
+ mode = None
+ else:
+ mode = self.mode & 0o7777
+ info = {
+ "name": self.name,
+ "mode": mode,
+ "uid": self.uid,
+ "gid": self.gid,
+ "size": self.size,
+ "mtime": self.mtime,
+ "chksum": self.chksum,
+ "type": self.type,
+ "linkname": self.linkname,
+ "uname": self.uname,
+ "gname": self.gname,
+ "devmajor": self.devmajor,
+ "devminor": self.devminor
+ }
+
+ if info["type"] == DIRTYPE and not info["name"].endswith("/"):
+ info["name"] += "/"
+
+ return info
+
+ def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="surrogateescape"):
+ """Return a tar header as a string of 512 byte blocks.
+ """
+ info = self.get_info()
+ for name, value in info.items():
+ if value is None:
+ raise ValueError("%s may not be None" % name)
+
+ if format == USTAR_FORMAT:
+ return self.create_ustar_header(info, encoding, errors)
+ elif format == GNU_FORMAT:
+ return self.create_gnu_header(info, encoding, errors)
+ elif format == PAX_FORMAT:
+ return self.create_pax_header(info, encoding)
+ else:
+ raise ValueError("invalid format")
+
+ def create_ustar_header(self, info, encoding, errors):
+ """Return the object as a ustar header block.
+ """
+ info["magic"] = POSIX_MAGIC
+
+ if len(info["linkname"].encode(encoding, errors)) > LENGTH_LINK:
+ raise ValueError("linkname is too long")
+
+ if len(info["name"].encode(encoding, errors)) > LENGTH_NAME:
+ info["prefix"], info["name"] = self._posix_split_name(info["name"], encoding, errors)
+
+ return self._create_header(info, USTAR_FORMAT, encoding, errors)
+
+ def create_gnu_header(self, info, encoding, errors):
+ """Return the object as a GNU header block sequence.
+ """
+ info["magic"] = GNU_MAGIC
+
+ buf = b""
+ if len(info["linkname"].encode(encoding, errors)) > LENGTH_LINK:
+ buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors)
+
+ if len(info["name"].encode(encoding, errors)) > LENGTH_NAME:
+ buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors)
+
+ return buf + self._create_header(info, GNU_FORMAT, encoding, errors)
+
+ def create_pax_header(self, info, encoding):
+ """Return the object as a ustar header block. If it cannot be
+ represented this way, prepend a pax extended header sequence
+ with supplement information.
+ """
+ info["magic"] = POSIX_MAGIC
+ pax_headers = self.pax_headers.copy()
+
+ # Test string fields for values that exceed the field length or cannot
+ # be represented in ASCII encoding.
+ for name, hname, length in (
+ ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK),
+ ("uname", "uname", 32), ("gname", "gname", 32)):
+
+ if hname in pax_headers:
+ # The pax header has priority.
+ continue
+
+ # Try to encode the string as ASCII.
+ try:
+ info[name].encode("ascii", "strict")
+ except UnicodeEncodeError:
+ pax_headers[hname] = info[name]
+ continue
+
+ if len(info[name]) > length:
+ pax_headers[hname] = info[name]
+
+ # Test number fields for values that exceed the field limit or values
+ # that like to be stored as float.
+ for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)):
+ needs_pax = False
+
+ val = info[name]
+ val_is_float = isinstance(val, float)
+ val_int = round(val) if val_is_float else val
+ if not 0 <= val_int < 8 ** (digits - 1):
+ # Avoid overflow.
+ info[name] = 0
+ needs_pax = True
+ elif val_is_float:
+ # Put rounded value in ustar header, and full
+ # precision value in pax header.
+ info[name] = val_int
+ needs_pax = True
+
+ # The existing pax header has priority.
+ if needs_pax and name not in pax_headers:
+ pax_headers[name] = str(val)
+
+ # Create a pax extended header if necessary.
+ if pax_headers:
+ buf = self._create_pax_generic_header(pax_headers, XHDTYPE, encoding)
+ else:
+ buf = b""
+
+ return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace")
+
+ @classmethod
+ def create_pax_global_header(cls, pax_headers):
+ """Return the object as a pax global header block sequence.
+ """
+ return cls._create_pax_generic_header(pax_headers, XGLTYPE, "utf-8")
+
+ def _posix_split_name(self, name, encoding, errors):
+ """Split a name longer than 100 chars into a prefix
+ and a name part.
+ """
+ components = name.split("/")
+ for i in range(1, len(components)):
+ prefix = "/".join(components[:i])
+ name = "/".join(components[i:])
+ if len(prefix.encode(encoding, errors)) <= LENGTH_PREFIX and \
+ len(name.encode(encoding, errors)) <= LENGTH_NAME:
+ break
+ else:
+ raise ValueError("name is too long")
+
+ return prefix, name
+
+ @staticmethod
+ def _create_header(info, format, encoding, errors):
+ """Return a header block. info is a dictionary with file
+ information, format must be one of the *_FORMAT constants.
+ """
+ has_device_fields = info.get("type") in (CHRTYPE, BLKTYPE)
+ if has_device_fields:
+ devmajor = itn(info.get("devmajor", 0), 8, format)
+ devminor = itn(info.get("devminor", 0), 8, format)
+ else:
+ devmajor = stn("", 8, encoding, errors)
+ devminor = stn("", 8, encoding, errors)
+
+ # None values in metadata should cause ValueError.
+ # itn()/stn() do this for all fields except type.
+ filetype = info.get("type", REGTYPE)
+ if filetype is None:
+ raise ValueError("TarInfo.type must not be None")
+
+ parts = [
+ stn(info.get("name", ""), 100, encoding, errors),
+ itn(info.get("mode", 0) & 0o7777, 8, format),
+ itn(info.get("uid", 0), 8, format),
+ itn(info.get("gid", 0), 8, format),
+ itn(info.get("size", 0), 12, format),
+ itn(info.get("mtime", 0), 12, format),
+ b" ", # checksum field
+ filetype,
+ stn(info.get("linkname", ""), 100, encoding, errors),
+ info.get("magic", POSIX_MAGIC),
+ stn(info.get("uname", ""), 32, encoding, errors),
+ stn(info.get("gname", ""), 32, encoding, errors),
+ devmajor,
+ devminor,
+ stn(info.get("prefix", ""), 155, encoding, errors)
+ ]
+
+ buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts))
+ chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
+ buf = buf[:-364] + bytes("%06o\0" % chksum, "ascii") + buf[-357:]
+ return buf
+
+ @staticmethod
+ def _create_payload(payload):
+ """Return the string payload filled with zero bytes
+ up to the next 512 byte border.
+ """
+ blocks, remainder = divmod(len(payload), BLOCKSIZE)
+ if remainder > 0:
+ payload += (BLOCKSIZE - remainder) * NUL
+ return payload
+
+ @classmethod
+ def _create_gnu_long_header(cls, name, type, encoding, errors):
+ """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence
+ for name.
+ """
+ name = name.encode(encoding, errors) + NUL
+
+ info = {}
+ info["name"] = "././@LongLink"
+ info["type"] = type
+ info["size"] = len(name)
+ info["magic"] = GNU_MAGIC
+
+ # create extended header + name blocks.
+ return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \
+ cls._create_payload(name)
+
+ @classmethod
+ def _create_pax_generic_header(cls, pax_headers, type, encoding):
+ """Return a POSIX.1-2008 extended or global header sequence
+ that contains a list of keyword, value pairs. The values
+ must be strings.
+ """
+ # Check if one of the fields contains surrogate characters and thereby
+ # forces hdrcharset=BINARY, see _proc_pax() for more information.
+ binary = False
+ for keyword, value in pax_headers.items():
+ try:
+ value.encode("utf-8", "strict")
+ except UnicodeEncodeError:
+ binary = True
+ break
+
+ records = b""
+ if binary:
+ # Put the hdrcharset field at the beginning of the header.
+ records += b"21 hdrcharset=BINARY\n"
+
+ for keyword, value in pax_headers.items():
+ keyword = keyword.encode("utf-8")
+ if binary:
+ # Try to restore the original byte representation of 'value'.
+ # Needless to say, that the encoding must match the string.
+ value = value.encode(encoding, "surrogateescape")
+ else:
+ value = value.encode("utf-8")
+
+ l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n'
+ n = p = 0
+ while True:
+ n = l + len(str(p))
+ if n == p:
+ break
+ p = n
+ records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n"
+
+ # We use a hardcoded "././@PaxHeader" name like star does
+ # instead of the one that POSIX recommends.
+ info = {}
+ info["name"] = "././@PaxHeader"
+ info["type"] = type
+ info["size"] = len(records)
+ info["magic"] = POSIX_MAGIC
+
+ # Create pax header + record blocks.
+ return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \
+ cls._create_payload(records)
+
+ @classmethod
+ def frombuf(cls, buf, encoding, errors):
+ """Construct a TarInfo object from a 512 byte bytes object.
+ """
+ if len(buf) == 0:
+ raise EmptyHeaderError("empty header")
+ if len(buf) != BLOCKSIZE:
+ raise TruncatedHeaderError("truncated header")
+ if buf.count(NUL) == BLOCKSIZE:
+ raise EOFHeaderError("end of file header")
+
+ chksum = nti(buf[148:156])
+ if chksum not in calc_chksums(buf):
+ raise InvalidHeaderError("bad checksum")
+
+ obj = cls()
+ obj.name = nts(buf[0:100], encoding, errors)
+ obj.mode = nti(buf[100:108])
+ obj.uid = nti(buf[108:116])
+ obj.gid = nti(buf[116:124])
+ obj.size = nti(buf[124:136])
+ obj.mtime = nti(buf[136:148])
+ obj.chksum = chksum
+ obj.type = buf[156:157]
+ obj.linkname = nts(buf[157:257], encoding, errors)
+ obj.uname = nts(buf[265:297], encoding, errors)
+ obj.gname = nts(buf[297:329], encoding, errors)
+ obj.devmajor = nti(buf[329:337])
+ obj.devminor = nti(buf[337:345])
+ prefix = nts(buf[345:500], encoding, errors)
+
+ # Old V7 tar format represents a directory as a regular
+ # file with a trailing slash.
+ if obj.type == AREGTYPE and obj.name.endswith("/"):
+ obj.type = DIRTYPE
+
+ # The old GNU sparse format occupies some of the unused
+ # space in the buffer for up to 4 sparse structures.
+ # Save them for later processing in _proc_sparse().
+ if obj.type == GNUTYPE_SPARSE:
+ pos = 386
+ structs = []
+ for i in range(4):
+ try:
+ offset = nti(buf[pos:pos + 12])
+ numbytes = nti(buf[pos + 12:pos + 24])
+ except ValueError:
+ break
+ structs.append((offset, numbytes))
+ pos += 24
+ isextended = bool(buf[482])
+ origsize = nti(buf[483:495])
+ obj._sparse_structs = (structs, isextended, origsize)
+
+ # Remove redundant slashes from directories.
+ if obj.isdir():
+ obj.name = obj.name.rstrip("/")
+
+ # Reconstruct a ustar longname.
+ if prefix and obj.type not in GNU_TYPES:
+ obj.name = prefix + "/" + obj.name
+ return obj
+
+ @classmethod
+ def fromtarfile(cls, tarfile):
+ """Return the next TarInfo object from TarFile object
+ tarfile.
+ """
+ buf = tarfile.fileobj.read(BLOCKSIZE)
+ obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors)
+ obj.offset = tarfile.fileobj.tell() - BLOCKSIZE
+ return obj._proc_member(tarfile)
+
+ #--------------------------------------------------------------------------
+ # The following are methods that are called depending on the type of a
+ # member. The entry point is _proc_member() which can be overridden in a
+ # subclass to add custom _proc_*() methods. A _proc_*() method MUST
+ # implement the following
+ # operations:
+ # 1. Set self.offset_data to the position where the data blocks begin,
+ # if there is data that follows.
+ # 2. Set tarfile.offset to the position where the next member's header will
+ # begin.
+ # 3. Return self or another valid TarInfo object.
+ def _proc_member(self, tarfile):
+ """Choose the right processing method depending on
+ the type and call it.
+ """
+ if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
+ return self._proc_gnulong(tarfile)
+ elif self.type == GNUTYPE_SPARSE:
+ return self._proc_sparse(tarfile)
+ elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE):
+ return self._proc_pax(tarfile)
+ else:
+ return self._proc_builtin(tarfile)
+
+ def _proc_builtin(self, tarfile):
+ """Process a builtin type or an unknown type which
+ will be treated as a regular file.
+ """
+ self.offset_data = tarfile.fileobj.tell()
+ offset = self.offset_data
+ if self.isreg() or self.type not in SUPPORTED_TYPES:
+ # Skip the following data blocks.
+ offset += self._block(self.size)
+ tarfile.offset = offset
+
+ # Patch the TarInfo object with saved global
+ # header information.
+ self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors)
+
+ # Remove redundant slashes from directories. This is to be consistent
+ # with frombuf().
+ if self.isdir():
+ self.name = self.name.rstrip("/")
+
+ return self
+
+ def _proc_gnulong(self, tarfile):
+ """Process the blocks that hold a GNU longname
+ or longlink member.
+ """
+ buf = tarfile.fileobj.read(self._block(self.size))
+
+ # Fetch the next header and process it.
+ try:
+ next = self.fromtarfile(tarfile)
+ except HeaderError as e:
+ raise SubsequentHeaderError(str(e)) from None
+
+ # Patch the TarInfo object from the next header with
+ # the longname information.
+ next.offset = self.offset
+ if self.type == GNUTYPE_LONGNAME:
+ next.name = nts(buf, tarfile.encoding, tarfile.errors)
+ elif self.type == GNUTYPE_LONGLINK:
+ next.linkname = nts(buf, tarfile.encoding, tarfile.errors)
+
+ # Remove redundant slashes from directories. This is to be consistent
+ # with frombuf().
+ if next.isdir():
+ next.name = removesuffix(next.name, "/")
+
+ return next
+
+ def _proc_sparse(self, tarfile):
+ """Process a GNU sparse header plus extra headers.
+ """
+ # We already collected some sparse structures in frombuf().
+ structs, isextended, origsize = self._sparse_structs
+ del self._sparse_structs
+
+ # Collect sparse structures from extended header blocks.
+ while isextended:
+ buf = tarfile.fileobj.read(BLOCKSIZE)
+ pos = 0
+ for i in range(21):
+ try:
+ offset = nti(buf[pos:pos + 12])
+ numbytes = nti(buf[pos + 12:pos + 24])
+ except ValueError:
+ break
+ if offset and numbytes:
+ structs.append((offset, numbytes))
+ pos += 24
+ isextended = bool(buf[504])
+ self.sparse = structs
+
+ self.offset_data = tarfile.fileobj.tell()
+ tarfile.offset = self.offset_data + self._block(self.size)
+ self.size = origsize
+ return self
+
+ def _proc_pax(self, tarfile):
+ """Process an extended or global header as described in
+ POSIX.1-2008.
+ """
+ # Read the header information.
+ buf = tarfile.fileobj.read(self._block(self.size))
+
+ # A pax header stores supplemental information for either
+ # the following file (extended) or all following files
+ # (global).
+ if self.type == XGLTYPE:
+ pax_headers = tarfile.pax_headers
+ else:
+ pax_headers = tarfile.pax_headers.copy()
+
+ # Check if the pax header contains a hdrcharset field. This tells us
+ # the encoding of the path, linkpath, uname and gname fields. Normally,
+ # these fields are UTF-8 encoded but since POSIX.1-2008 tar
+ # implementations are allowed to store them as raw binary strings if
+ # the translation to UTF-8 fails.
+ match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf)
+ if match is not None:
+ pax_headers["hdrcharset"] = match.group(1).decode("utf-8")
+
+ # For the time being, we don't care about anything other than "BINARY".
+ # The only other value that is currently allowed by the standard is
+ # "ISO-IR 10646 2000 UTF-8" in other words UTF-8.
+ hdrcharset = pax_headers.get("hdrcharset")
+ if hdrcharset == "BINARY":
+ encoding = tarfile.encoding
+ else:
+ encoding = "utf-8"
+
+ # Parse pax header information. A record looks like that:
+ # "%d %s=%s\n" % (length, keyword, value). length is the size
+ # of the complete record including the length field itself and
+ # the newline. keyword and value are both UTF-8 encoded strings.
+ regex = re.compile(br"(\d+) ([^=]+)=")
+ pos = 0
+ while match := regex.match(buf, pos):
+ length, keyword = match.groups()
+ length = int(length)
+ if length == 0:
+ raise InvalidHeaderError("invalid header")
+ value = buf[match.end(2) + 1:match.start(1) + length - 1]
+
+ # Normally, we could just use "utf-8" as the encoding and "strict"
+ # as the error handler, but we better not take the risk. For
+ # example, GNU tar <= 1.23 is known to store filenames it cannot
+ # translate to UTF-8 as raw strings (unfortunately without a
+ # hdrcharset=BINARY header).
+ # We first try the strict standard encoding, and if that fails we
+ # fall back on the user's encoding and error handler.
+ keyword = self._decode_pax_field(keyword, "utf-8", "utf-8",
+ tarfile.errors)
+ if keyword in PAX_NAME_FIELDS:
+ value = self._decode_pax_field(value, encoding, tarfile.encoding,
+ tarfile.errors)
+ else:
+ value = self._decode_pax_field(value, "utf-8", "utf-8",
+ tarfile.errors)
+
+ pax_headers[keyword] = value
+ pos += length
+
+ # Fetch the next header.
+ try:
+ next = self.fromtarfile(tarfile)
+ except HeaderError as e:
+ raise SubsequentHeaderError(str(e)) from None
+
+ # Process GNU sparse information.
+ if "GNU.sparse.map" in pax_headers:
+ # GNU extended sparse format version 0.1.
+ self._proc_gnusparse_01(next, pax_headers)
+
+ elif "GNU.sparse.size" in pax_headers:
+ # GNU extended sparse format version 0.0.
+ self._proc_gnusparse_00(next, pax_headers, buf)
+
+ elif pax_headers.get("GNU.sparse.major") == "1" and pax_headers.get("GNU.sparse.minor") == "0":
+ # GNU extended sparse format version 1.0.
+ self._proc_gnusparse_10(next, pax_headers, tarfile)
+
+ if self.type in (XHDTYPE, SOLARIS_XHDTYPE):
+ # Patch the TarInfo object with the extended header info.
+ next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors)
+ next.offset = self.offset
+
+ if "size" in pax_headers:
+ # If the extended header replaces the size field,
+ # we need to recalculate the offset where the next
+ # header starts.
+ offset = next.offset_data
+ if next.isreg() or next.type not in SUPPORTED_TYPES:
+ offset += next._block(next.size)
+ tarfile.offset = offset
+
+ return next
+
+ def _proc_gnusparse_00(self, next, pax_headers, buf):
+ """Process a GNU tar extended sparse header, version 0.0.
+ """
+ offsets = []
+ for match in re.finditer(br"\d+ GNU.sparse.offset=(\d+)\n", buf):
+ offsets.append(int(match.group(1)))
+ numbytes = []
+ for match in re.finditer(br"\d+ GNU.sparse.numbytes=(\d+)\n", buf):
+ numbytes.append(int(match.group(1)))
+ next.sparse = list(zip(offsets, numbytes))
+
+ def _proc_gnusparse_01(self, next, pax_headers):
+ """Process a GNU tar extended sparse header, version 0.1.
+ """
+ sparse = [int(x) for x in pax_headers["GNU.sparse.map"].split(",")]
+ next.sparse = list(zip(sparse[::2], sparse[1::2]))
+
+ def _proc_gnusparse_10(self, next, pax_headers, tarfile):
+ """Process a GNU tar extended sparse header, version 1.0.
+ """
+ fields = None
+ sparse = []
+ buf = tarfile.fileobj.read(BLOCKSIZE)
+ fields, buf = buf.split(b"\n", 1)
+ fields = int(fields)
+ while len(sparse) < fields * 2:
+ if b"\n" not in buf:
+ buf += tarfile.fileobj.read(BLOCKSIZE)
+ number, buf = buf.split(b"\n", 1)
+ sparse.append(int(number))
+ next.offset_data = tarfile.fileobj.tell()
+ next.sparse = list(zip(sparse[::2], sparse[1::2]))
+
+ def _apply_pax_info(self, pax_headers, encoding, errors):
+ """Replace fields with supplemental information from a previous
+ pax extended or global header.
+ """
+ for keyword, value in pax_headers.items():
+ if keyword == "GNU.sparse.name":
+ setattr(self, "path", value)
+ elif keyword == "GNU.sparse.size":
+ setattr(self, "size", int(value))
+ elif keyword == "GNU.sparse.realsize":
+ setattr(self, "size", int(value))
+ elif keyword in PAX_FIELDS:
+ if keyword in PAX_NUMBER_FIELDS:
+ try:
+ value = PAX_NUMBER_FIELDS[keyword](value)
+ except ValueError:
+ value = 0
+ if keyword == "path":
+ value = value.rstrip("/")
+ setattr(self, keyword, value)
+
+ self.pax_headers = pax_headers.copy()
+
+ def _decode_pax_field(self, value, encoding, fallback_encoding, fallback_errors):
+ """Decode a single field from a pax record.
+ """
+ try:
+ return value.decode(encoding, "strict")
+ except UnicodeDecodeError:
+ return value.decode(fallback_encoding, fallback_errors)
+
+ def _block(self, count):
+ """Round up a byte count by BLOCKSIZE and return it,
+ e.g. _block(834) => 1024.
+ """
+ blocks, remainder = divmod(count, BLOCKSIZE)
+ if remainder:
+ blocks += 1
+ return blocks * BLOCKSIZE
+
+ def isreg(self):
+ 'Return True if the Tarinfo object is a regular file.'
+ return self.type in REGULAR_TYPES
+
+ def isfile(self):
+ 'Return True if the Tarinfo object is a regular file.'
+ return self.isreg()
+
+ def isdir(self):
+ 'Return True if it is a directory.'
+ return self.type == DIRTYPE
+
+ def issym(self):
+ 'Return True if it is a symbolic link.'
+ return self.type == SYMTYPE
+
+ def islnk(self):
+ 'Return True if it is a hard link.'
+ return self.type == LNKTYPE
+
+ def ischr(self):
+ 'Return True if it is a character device.'
+ return self.type == CHRTYPE
+
+ def isblk(self):
+ 'Return True if it is a block device.'
+ return self.type == BLKTYPE
+
+ def isfifo(self):
+ 'Return True if it is a FIFO.'
+ return self.type == FIFOTYPE
+
+ def issparse(self):
+ return self.sparse is not None
+
+ def isdev(self):
+ 'Return True if it is one of character device, block device or FIFO.'
+ return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
+# class TarInfo
+
+class TarFile(object):
+ """The TarFile Class provides an interface to tar archives.
+ """
+
+ debug = 0 # May be set from 0 (no msgs) to 3 (all msgs)
+
+ dereference = False # If true, add content of linked file to the
+ # tar file, else the link.
+
+ ignore_zeros = False # If true, skips empty or invalid blocks and
+ # continues processing.
+
+ errorlevel = 1 # If 0, fatal errors only appear in debug
+ # messages (if debug >= 0). If > 0, errors
+ # are passed to the caller as exceptions.
+
+ format = DEFAULT_FORMAT # The format to use when creating an archive.
+
+ encoding = ENCODING # Encoding for 8-bit character strings.
+
+ errors = None # Error handler for unicode conversion.
+
+ tarinfo = TarInfo # The default TarInfo class to use.
+
+ fileobject = ExFileObject # The file-object for extractfile().
+
+ extraction_filter = None # The default filter for extraction.
+
+ def __init__(self, name=None, mode="r", fileobj=None, format=None,
+ tarinfo=None, dereference=None, ignore_zeros=None, encoding=None,
+ errors="surrogateescape", pax_headers=None, debug=None,
+ errorlevel=None, copybufsize=None, stream=False):
+ """Open an (uncompressed) tar archive 'name'. 'mode' is either 'r' to
+ read from an existing archive, 'a' to append data to an existing
+ file or 'w' to create a new file overwriting an existing one. 'mode'
+ defaults to 'r'.
+ If 'fileobj' is given, it is used for reading or writing data. If it
+ can be determined, 'mode' is overridden by 'fileobj's mode.
+ 'fileobj' is not closed, when TarFile is closed.
+ """
+ modes = {"r": "rb", "a": "r+b", "w": "wb", "x": "xb"}
+ if mode not in modes:
+ raise ValueError("mode must be 'r', 'a', 'w' or 'x'")
+ self.mode = mode
+ self._mode = modes[mode]
+
+ if not fileobj:
+ if self.mode == "a" and not os.path.exists(name):
+ # Create nonexistent files in append mode.
+ self.mode = "w"
+ self._mode = "wb"
+ fileobj = bltn_open(name, self._mode)
+ self._extfileobj = False
+ else:
+ if (name is None and hasattr(fileobj, "name") and
+ isinstance(fileobj.name, (str, bytes))):
+ name = fileobj.name
+ if hasattr(fileobj, "mode"):
+ self._mode = fileobj.mode
+ self._extfileobj = True
+ self.name = os.path.abspath(name) if name else None
+ self.fileobj = fileobj
+
+ self.stream = stream
+
+ # Init attributes.
+ if format is not None:
+ self.format = format
+ if tarinfo is not None:
+ self.tarinfo = tarinfo
+ if dereference is not None:
+ self.dereference = dereference
+ if ignore_zeros is not None:
+ self.ignore_zeros = ignore_zeros
+ if encoding is not None:
+ self.encoding = encoding
+ self.errors = errors
+
+ if pax_headers is not None and self.format == PAX_FORMAT:
+ self.pax_headers = pax_headers
+ else:
+ self.pax_headers = {}
+
+ if debug is not None:
+ self.debug = debug
+ if errorlevel is not None:
+ self.errorlevel = errorlevel
+
+ # Init datastructures.
+ self.copybufsize = copybufsize
+ self.closed = False
+ self.members = [] # list of members as TarInfo objects
+ self._loaded = False # flag if all members have been read
+ self.offset = self.fileobj.tell()
+ # current position in the archive file
+ self.inodes = {} # dictionary caching the inodes of
+ # archive members already added
+
+ try:
+ if self.mode == "r":
+ self.firstmember = None
+ self.firstmember = self.next()
+
+ if self.mode == "a":
+ # Move to the end of the archive,
+ # before the first empty block.
+ while True:
+ self.fileobj.seek(self.offset)
+ try:
+ tarinfo = self.tarinfo.fromtarfile(self)
+ self.members.append(tarinfo)
+ except EOFHeaderError:
+ self.fileobj.seek(self.offset)
+ break
+ except HeaderError as e:
+ raise ReadError(str(e)) from None
+
+ if self.mode in ("a", "w", "x"):
+ self._loaded = True
+
+ if self.pax_headers:
+ buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy())
+ self.fileobj.write(buf)
+ self.offset += len(buf)
+ except:
+ if not self._extfileobj:
+ self.fileobj.close()
+ self.closed = True
+ raise
+
+ #--------------------------------------------------------------------------
+ # Below are the classmethods which act as alternate constructors to the
+ # TarFile class. The open() method is the only one that is needed for
+ # public use; it is the "super"-constructor and is able to select an
+ # adequate "sub"-constructor for a particular compression using the mapping
+ # from OPEN_METH.
+ #
+ # This concept allows one to subclass TarFile without losing the comfort of
+ # the super-constructor. A sub-constructor is registered and made available
+ # by adding it to the mapping in OPEN_METH.
+
+ @classmethod
+ def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs):
+ r"""Open a tar archive for reading, writing or appending. Return
+ an appropriate TarFile class.
+
+ mode:
+ 'r' or 'r:\*' open for reading with transparent compression
+ 'r:' open for reading exclusively uncompressed
+ 'r:gz' open for reading with gzip compression
+ 'r:bz2' open for reading with bzip2 compression
+ 'r:xz' open for reading with lzma compression
+ 'a' or 'a:' open for appending, creating the file if necessary
+ 'w' or 'w:' open for writing without compression
+ 'w:gz' open for writing with gzip compression
+ 'w:bz2' open for writing with bzip2 compression
+ 'w:xz' open for writing with lzma compression
+
+ 'x' or 'x:' create a tarfile exclusively without compression, raise
+ an exception if the file is already created
+ 'x:gz' create a gzip compressed tarfile, raise an exception
+ if the file is already created
+ 'x:bz2' create a bzip2 compressed tarfile, raise an exception
+ if the file is already created
+ 'x:xz' create an lzma compressed tarfile, raise an exception
+ if the file is already created
+
+ 'r|\*' open a stream of tar blocks with transparent compression
+ 'r|' open an uncompressed stream of tar blocks for reading
+ 'r|gz' open a gzip compressed stream of tar blocks
+ 'r|bz2' open a bzip2 compressed stream of tar blocks
+ 'r|xz' open an lzma compressed stream of tar blocks
+ 'w|' open an uncompressed stream for writing
+ 'w|gz' open a gzip compressed stream for writing
+ 'w|bz2' open a bzip2 compressed stream for writing
+ 'w|xz' open an lzma compressed stream for writing
+ """
+
+ if not name and not fileobj:
+ raise ValueError("nothing to open")
+
+ if mode in ("r", "r:*"):
+ # Find out which *open() is appropriate for opening the file.
+ def not_compressed(comptype):
+ return cls.OPEN_METH[comptype] == 'taropen'
+ error_msgs = []
+ for comptype in sorted(cls.OPEN_METH, key=not_compressed):
+ func = getattr(cls, cls.OPEN_METH[comptype])
+ if fileobj is not None:
+ saved_pos = fileobj.tell()
+ try:
+ return func(name, "r", fileobj, **kwargs)
+ except (ReadError, CompressionError) as e:
+ error_msgs.append(f'- method {comptype}: {e!r}')
+ if fileobj is not None:
+ fileobj.seek(saved_pos)
+ continue
+ error_msgs_summary = '\n'.join(error_msgs)
+ raise ReadError(f"file could not be opened successfully:\n{error_msgs_summary}")
+
+ elif ":" in mode:
+ filemode, comptype = mode.split(":", 1)
+ filemode = filemode or "r"
+ comptype = comptype or "tar"
+
+ # Select the *open() function according to
+ # given compression.
+ if comptype in cls.OPEN_METH:
+ func = getattr(cls, cls.OPEN_METH[comptype])
+ else:
+ raise CompressionError("unknown compression type %r" % comptype)
+ return func(name, filemode, fileobj, **kwargs)
+
+ elif "|" in mode:
+ filemode, comptype = mode.split("|", 1)
+ filemode = filemode or "r"
+ comptype = comptype or "tar"
+
+ if filemode not in ("r", "w"):
+ raise ValueError("mode must be 'r' or 'w'")
+
+ compresslevel = kwargs.pop("compresslevel", 9)
+ stream = _Stream(name, filemode, comptype, fileobj, bufsize,
+ compresslevel)
+ try:
+ t = cls(name, filemode, stream, **kwargs)
+ except:
+ stream.close()
+ raise
+ t._extfileobj = False
+ return t
+
+ elif mode in ("a", "w", "x"):
+ return cls.taropen(name, mode, fileobj, **kwargs)
+
+ raise ValueError("undiscernible mode")
+
+ @classmethod
+ def taropen(cls, name, mode="r", fileobj=None, **kwargs):
+ """Open uncompressed tar archive name for reading or writing.
+ """
+ if mode not in ("r", "a", "w", "x"):
+ raise ValueError("mode must be 'r', 'a', 'w' or 'x'")
+ return cls(name, mode, fileobj, **kwargs)
+
+ @classmethod
+ def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
+ """Open gzip compressed tar archive name for reading or writing.
+ Appending is not allowed.
+ """
+ if mode not in ("r", "w", "x"):
+ raise ValueError("mode must be 'r', 'w' or 'x'")
+
+ try:
+ from gzip import GzipFile
+ except ImportError:
+ raise CompressionError("gzip module is not available") from None
+
+ try:
+ fileobj = GzipFile(name, mode + "b", compresslevel, fileobj)
+ except OSError as e:
+ if fileobj is not None and mode == 'r':
+ raise ReadError("not a gzip file") from e
+ raise
+
+ try:
+ t = cls.taropen(name, mode, fileobj, **kwargs)
+ except OSError as e:
+ fileobj.close()
+ if mode == 'r':
+ raise ReadError("not a gzip file") from e
+ raise
+ except:
+ fileobj.close()
+ raise
+ t._extfileobj = False
+ return t
+
+ @classmethod
+ def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
+ """Open bzip2 compressed tar archive name for reading or writing.
+ Appending is not allowed.
+ """
+ if mode not in ("r", "w", "x"):
+ raise ValueError("mode must be 'r', 'w' or 'x'")
+
+ try:
+ from bz2 import BZ2File
+ except ImportError:
+ raise CompressionError("bz2 module is not available") from None
+
+ fileobj = BZ2File(fileobj or name, mode, compresslevel=compresslevel)
+
+ try:
+ t = cls.taropen(name, mode, fileobj, **kwargs)
+ except (OSError, EOFError) as e:
+ fileobj.close()
+ if mode == 'r':
+ raise ReadError("not a bzip2 file") from e
+ raise
+ except:
+ fileobj.close()
+ raise
+ t._extfileobj = False
+ return t
+
+ @classmethod
+ def xzopen(cls, name, mode="r", fileobj=None, preset=None, **kwargs):
+ """Open lzma compressed tar archive name for reading or writing.
+ Appending is not allowed.
+ """
+ if mode not in ("r", "w", "x"):
+ raise ValueError("mode must be 'r', 'w' or 'x'")
+
+ try:
+ from lzma import LZMAFile, LZMAError
+ except ImportError:
+ raise CompressionError("lzma module is not available") from None
+
+ fileobj = LZMAFile(fileobj or name, mode, preset=preset)
+
+ try:
+ t = cls.taropen(name, mode, fileobj, **kwargs)
+ except (LZMAError, EOFError) as e:
+ fileobj.close()
+ if mode == 'r':
+ raise ReadError("not an lzma file") from e
+ raise
+ except:
+ fileobj.close()
+ raise
+ t._extfileobj = False
+ return t
+
+ # All *open() methods are registered here.
+ OPEN_METH = {
+ "tar": "taropen", # uncompressed tar
+ "gz": "gzopen", # gzip compressed tar
+ "bz2": "bz2open", # bzip2 compressed tar
+ "xz": "xzopen" # lzma compressed tar
+ }
+
+ #--------------------------------------------------------------------------
+ # The public methods which TarFile provides:
+
+ def close(self):
+ """Close the TarFile. In write-mode, two finishing zero blocks are
+ appended to the archive.
+ """
+ if self.closed:
+ return
+
+ self.closed = True
+ try:
+ if self.mode in ("a", "w", "x"):
+ self.fileobj.write(NUL * (BLOCKSIZE * 2))
+ self.offset += (BLOCKSIZE * 2)
+ # fill up the end with zero-blocks
+ # (like option -b20 for tar does)
+ blocks, remainder = divmod(self.offset, RECORDSIZE)
+ if remainder > 0:
+ self.fileobj.write(NUL * (RECORDSIZE - remainder))
+ finally:
+ if not self._extfileobj:
+ self.fileobj.close()
+
+ def getmember(self, name):
+ """Return a TarInfo object for member 'name'. If 'name' can not be
+ found in the archive, KeyError is raised. If a member occurs more
+ than once in the archive, its last occurrence is assumed to be the
+ most up-to-date version.
+ """
+ tarinfo = self._getmember(name.rstrip('/'))
+ if tarinfo is None:
+ raise KeyError("filename %r not found" % name)
+ return tarinfo
+
+ def getmembers(self):
+ """Return the members of the archive as a list of TarInfo objects. The
+ list has the same order as the members in the archive.
+ """
+ self._check()
+ if not self._loaded: # if we want to obtain a list of
+ self._load() # all members, we first have to
+ # scan the whole archive.
+ return self.members
+
+ def getnames(self):
+ """Return the members of the archive as a list of their names. It has
+ the same order as the list returned by getmembers().
+ """
+ return [tarinfo.name for tarinfo in self.getmembers()]
+
+ def gettarinfo(self, name=None, arcname=None, fileobj=None):
+ """Create a TarInfo object from the result of os.stat or equivalent
+ on an existing file. The file is either named by 'name', or
+ specified as a file object 'fileobj' with a file descriptor. If
+ given, 'arcname' specifies an alternative name for the file in the
+ archive, otherwise, the name is taken from the 'name' attribute of
+ 'fileobj', or the 'name' argument. The name should be a text
+ string.
+ """
+ self._check("awx")
+
+ # When fileobj is given, replace name by
+ # fileobj's real name.
+ if fileobj is not None:
+ name = fileobj.name
+
+ # Building the name of the member in the archive.
+ # Backward slashes are converted to forward slashes,
+ # Absolute paths are turned to relative paths.
+ if arcname is None:
+ arcname = name
+ drv, arcname = os.path.splitdrive(arcname)
+ arcname = arcname.replace(os.sep, "/")
+ arcname = arcname.lstrip("/")
+
+ # Now, fill the TarInfo object with
+ # information specific for the file.
+ tarinfo = self.tarinfo()
+ tarinfo._tarfile = self # To be removed in 3.16.
+
+ # Use os.stat or os.lstat, depending on if symlinks shall be resolved.
+ if fileobj is None:
+ if not self.dereference:
+ statres = os.lstat(name)
+ else:
+ statres = os.stat(name)
+ else:
+ statres = os.fstat(fileobj.fileno())
+ linkname = ""
+
+ stmd = statres.st_mode
+ if stat.S_ISREG(stmd):
+ inode = (statres.st_ino, statres.st_dev)
+ if not self.dereference and statres.st_nlink > 1 and \
+ inode in self.inodes and arcname != self.inodes[inode]:
+ # Is it a hardlink to an already
+ # archived file?
+ type = LNKTYPE
+ linkname = self.inodes[inode]
+ else:
+ # The inode is added only if its valid.
+ # For win32 it is always 0.
+ type = REGTYPE
+ if inode[0]:
+ self.inodes[inode] = arcname
+ elif stat.S_ISDIR(stmd):
+ type = DIRTYPE
+ elif stat.S_ISFIFO(stmd):
+ type = FIFOTYPE
+ elif stat.S_ISLNK(stmd):
+ type = SYMTYPE
+ linkname = os.readlink(name)
+ elif stat.S_ISCHR(stmd):
+ type = CHRTYPE
+ elif stat.S_ISBLK(stmd):
+ type = BLKTYPE
+ else:
+ return None
+
+ # Fill the TarInfo object with all
+ # information we can get.
+ tarinfo.name = arcname
+ tarinfo.mode = stmd
+ tarinfo.uid = statres.st_uid
+ tarinfo.gid = statres.st_gid
+ if type == REGTYPE:
+ tarinfo.size = statres.st_size
+ else:
+ tarinfo.size = 0
+ tarinfo.mtime = statres.st_mtime
+ tarinfo.type = type
+ tarinfo.linkname = linkname
+ if pwd:
+ try:
+ tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
+ except KeyError:
+ pass
+ if grp:
+ try:
+ tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
+ except KeyError:
+ pass
+
+ if type in (CHRTYPE, BLKTYPE):
+ if hasattr(os, "major") and hasattr(os, "minor"):
+ tarinfo.devmajor = os.major(statres.st_rdev)
+ tarinfo.devminor = os.minor(statres.st_rdev)
+ return tarinfo
+
+ def list(self, verbose=True, *, members=None):
+ """Print a table of contents to sys.stdout. If 'verbose' is False, only
+ the names of the members are printed. If it is True, an 'ls -l'-like
+ output is produced. 'members' is optional and must be a subset of the
+ list returned by getmembers().
+ """
+ # Convert tarinfo type to stat type.
+ type2mode = {REGTYPE: stat.S_IFREG, SYMTYPE: stat.S_IFLNK,
+ FIFOTYPE: stat.S_IFIFO, CHRTYPE: stat.S_IFCHR,
+ DIRTYPE: stat.S_IFDIR, BLKTYPE: stat.S_IFBLK}
+ self._check()
+
+ if members is None:
+ members = self
+ for tarinfo in members:
+ if verbose:
+ if tarinfo.mode is None:
+ _safe_print("??????????")
+ else:
+ modetype = type2mode.get(tarinfo.type, 0)
+ _safe_print(stat.filemode(modetype | tarinfo.mode))
+ _safe_print("%s/%s" % (tarinfo.uname or tarinfo.uid,
+ tarinfo.gname or tarinfo.gid))
+ if tarinfo.ischr() or tarinfo.isblk():
+ _safe_print("%10s" %
+ ("%d,%d" % (tarinfo.devmajor, tarinfo.devminor)))
+ else:
+ _safe_print("%10d" % tarinfo.size)
+ if tarinfo.mtime is None:
+ _safe_print("????-??-?? ??:??:??")
+ else:
+ _safe_print("%d-%02d-%02d %02d:%02d:%02d" \
+ % time.localtime(tarinfo.mtime)[:6])
+
+ _safe_print(tarinfo.name + ("/" if tarinfo.isdir() else ""))
+
+ if verbose:
+ if tarinfo.issym():
+ _safe_print("-> " + tarinfo.linkname)
+ if tarinfo.islnk():
+ _safe_print("link to " + tarinfo.linkname)
+ print()
+
+ def add(self, name, arcname=None, recursive=True, *, filter=None):
+ """Add the file 'name' to the archive. 'name' may be any type of file
+ (directory, fifo, symbolic link, etc.). If given, 'arcname'
+ specifies an alternative name for the file in the archive.
+ Directories are added recursively by default. This can be avoided by
+ setting 'recursive' to False. 'filter' is a function
+ that expects a TarInfo object argument and returns the changed
+ TarInfo object, if it returns None the TarInfo object will be
+ excluded from the archive.
+ """
+ self._check("awx")
+
+ if arcname is None:
+ arcname = name
+
+ # Skip if somebody tries to archive the archive...
+ if self.name is not None and os.path.abspath(name) == self.name:
+ self._dbg(2, "tarfile: Skipped %r" % name)
+ return
+
+ self._dbg(1, name)
+
+ # Create a TarInfo object from the file.
+ tarinfo = self.gettarinfo(name, arcname)
+
+ if tarinfo is None:
+ self._dbg(1, "tarfile: Unsupported type %r" % name)
+ return
+
+ # Change or exclude the TarInfo object.
+ if filter is not None:
+ tarinfo = filter(tarinfo)
+ if tarinfo is None:
+ self._dbg(2, "tarfile: Excluded %r" % name)
+ return
+
+ # Append the tar header and data to the archive.
+ if tarinfo.isreg():
+ with bltn_open(name, "rb") as f:
+ self.addfile(tarinfo, f)
+
+ elif tarinfo.isdir():
+ self.addfile(tarinfo)
+ if recursive:
+ for f in sorted(os.listdir(name)):
+ self.add(os.path.join(name, f), os.path.join(arcname, f),
+ recursive, filter=filter)
+
+ else:
+ self.addfile(tarinfo)
+
+ def addfile(self, tarinfo, fileobj=None):
+ """Add the TarInfo object 'tarinfo' to the archive. If 'tarinfo' represents
+ a non zero-size regular file, the 'fileobj' argument should be a binary file,
+ and tarinfo.size bytes are read from it and added to the archive.
+ You can create TarInfo objects directly, or by using gettarinfo().
+ """
+ self._check("awx")
+
+ if fileobj is None and tarinfo.isreg() and tarinfo.size != 0:
+ raise ValueError("fileobj not provided for non zero-size regular file")
+
+ tarinfo = copy.copy(tarinfo)
+
+ buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
+ self.fileobj.write(buf)
+ self.offset += len(buf)
+ bufsize=self.copybufsize
+ # If there's data to follow, append it.
+ if fileobj is not None:
+ copyfileobj(fileobj, self.fileobj, tarinfo.size, bufsize=bufsize)
+ blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
+ if remainder > 0:
+ self.fileobj.write(NUL * (BLOCKSIZE - remainder))
+ blocks += 1
+ self.offset += blocks * BLOCKSIZE
+
+ self.members.append(tarinfo)
+
+ def _get_filter_function(self, filter):
+ if filter is None:
+ filter = self.extraction_filter
+ if filter is None:
+ import warnings
+ warnings.warn(
+ 'Python 3.14 will, by default, filter extracted tar '
+ + 'archives and reject files or modify their metadata. '
+ + 'Use the filter argument to control this behavior.',
+ DeprecationWarning, stacklevel=3)
+ return fully_trusted_filter
+ if isinstance(filter, str):
+ raise TypeError(
+ 'String names are not supported for '
+ + 'TarFile.extraction_filter. Use a function such as '
+ + 'tarfile.data_filter directly.')
+ return filter
+ if callable(filter):
+ return filter
+ try:
+ return _NAMED_FILTERS[filter]
+ except KeyError:
+ raise ValueError(f"filter {filter!r} not found") from None
+
+ def extractall(self, path=".", members=None, *, numeric_owner=False,
+ filter=None):
+ """Extract all members from the archive to the current working
+ directory and set owner, modification time and permissions on
+ directories afterwards. 'path' specifies a different directory
+ to extract to. 'members' is optional and must be a subset of the
+ list returned by getmembers(). If 'numeric_owner' is True, only
+ the numbers for user/group names are used and not the names.
+
+ The 'filter' function will be called on each member just
+ before extraction.
+ It can return a changed TarInfo or None to skip the member.
+ String names of common filters are accepted.
+ """
+ directories = []
+
+ filter_function = self._get_filter_function(filter)
+ if members is None:
+ members = self
+
+ for member in members:
+ tarinfo = self._get_extract_tarinfo(member, filter_function, path)
+ if tarinfo is None:
+ continue
+ if tarinfo.isdir():
+ # For directories, delay setting attributes until later,
+ # since permissions can interfere with extraction and
+ # extracting contents can reset mtime.
+ directories.append(tarinfo)
+ self._extract_one(tarinfo, path, set_attrs=not tarinfo.isdir(),
+ numeric_owner=numeric_owner)
+
+ # Reverse sort directories.
+ directories.sort(key=lambda a: a.name, reverse=True)
+
+ # Set correct owner, mtime and filemode on directories.
+ for tarinfo in directories:
+ dirpath = os.path.join(path, tarinfo.name)
+ try:
+ self.chown(tarinfo, dirpath, numeric_owner=numeric_owner)
+ self.utime(tarinfo, dirpath)
+ self.chmod(tarinfo, dirpath)
+ except ExtractError as e:
+ self._handle_nonfatal_error(e)
+
+ def extract(self, member, path="", set_attrs=True, *, numeric_owner=False,
+ filter=None):
+ """Extract a member from the archive to the current working directory,
+ using its full name. Its file information is extracted as accurately
+ as possible. 'member' may be a filename or a TarInfo object. You can
+ specify a different directory using 'path'. File attributes (owner,
+ mtime, mode) are set unless 'set_attrs' is False. If 'numeric_owner'
+ is True, only the numbers for user/group names are used and not
+ the names.
+
+ The 'filter' function will be called before extraction.
+ It can return a changed TarInfo or None to skip the member.
+ String names of common filters are accepted.
+ """
+ filter_function = self._get_filter_function(filter)
+ tarinfo = self._get_extract_tarinfo(member, filter_function, path)
+ if tarinfo is not None:
+ self._extract_one(tarinfo, path, set_attrs, numeric_owner)
+
+ def _get_extract_tarinfo(self, member, filter_function, path):
+ """Get filtered TarInfo (or None) from member, which might be a str"""
+ if isinstance(member, str):
+ tarinfo = self.getmember(member)
+ else:
+ tarinfo = member
+
+ unfiltered = tarinfo
+ try:
+ tarinfo = filter_function(tarinfo, path)
+ except (OSError, FilterError) as e:
+ self._handle_fatal_error(e)
+ except ExtractError as e:
+ self._handle_nonfatal_error(e)
+ if tarinfo is None:
+ self._dbg(2, "tarfile: Excluded %r" % unfiltered.name)
+ return None
+ # Prepare the link target for makelink().
+ if tarinfo.islnk():
+ tarinfo = copy.copy(tarinfo)
+ tarinfo._link_target = os.path.join(path, tarinfo.linkname)
+ return tarinfo
+
+ def _extract_one(self, tarinfo, path, set_attrs, numeric_owner):
+ """Extract from filtered tarinfo to disk"""
+ self._check("r")
+
+ try:
+ self._extract_member(tarinfo, os.path.join(path, tarinfo.name),
+ set_attrs=set_attrs,
+ numeric_owner=numeric_owner)
+ except OSError as e:
+ self._handle_fatal_error(e)
+ except ExtractError as e:
+ self._handle_nonfatal_error(e)
+
+ def _handle_nonfatal_error(self, e):
+ """Handle non-fatal error (ExtractError) according to errorlevel"""
+ if self.errorlevel > 1:
+ raise
+ else:
+ self._dbg(1, "tarfile: %s" % e)
+
+ def _handle_fatal_error(self, e):
+ """Handle "fatal" error according to self.errorlevel"""
+ if self.errorlevel > 0:
+ raise
+ elif isinstance(e, OSError):
+ if e.filename is None:
+ self._dbg(1, "tarfile: %s" % e.strerror)
+ else:
+ self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename))
+ else:
+ self._dbg(1, "tarfile: %s %s" % (type(e).__name__, e))
+
+ def extractfile(self, member):
+ """Extract a member from the archive as a file object. 'member' may be
+ a filename or a TarInfo object. If 'member' is a regular file or
+ a link, an io.BufferedReader object is returned. For all other
+ existing members, None is returned. If 'member' does not appear
+ in the archive, KeyError is raised.
+ """
+ self._check("r")
+
+ if isinstance(member, str):
+ tarinfo = self.getmember(member)
+ else:
+ tarinfo = member
+
+ if tarinfo.isreg() or tarinfo.type not in SUPPORTED_TYPES:
+ # Members with unknown types are treated as regular files.
+ return self.fileobject(self, tarinfo)
+
+ elif tarinfo.islnk() or tarinfo.issym():
+ if isinstance(self.fileobj, _Stream):
+ # A small but ugly workaround for the case that someone tries
+ # to extract a (sym)link as a file-object from a non-seekable
+ # stream of tar blocks.
+ raise StreamError("cannot extract (sym)link as file object")
+ else:
+ # A (sym)link's file object is its target's file object.
+ return self.extractfile(self._find_link_target(tarinfo))
+ else:
+ # If there's no data associated with the member (directory, chrdev,
+ # blkdev, etc.), return None instead of a file object.
+ return None
+
+ def _extract_member(self, tarinfo, targetpath, set_attrs=True,
+ numeric_owner=False):
+ """Extract the TarInfo object tarinfo to a physical
+ file called targetpath.
+ """
+ # Fetch the TarInfo object for the given name
+ # and build the destination pathname, replacing
+ # forward slashes to platform specific separators.
+ targetpath = targetpath.rstrip("/")
+ targetpath = targetpath.replace("/", os.sep)
+
+ # Create all upper directories.
+ upperdirs = os.path.dirname(targetpath)
+ if upperdirs and not os.path.exists(upperdirs):
+ # Create directories that are not part of the archive with
+ # default permissions.
+ os.makedirs(upperdirs, exist_ok=True)
+
+ if tarinfo.islnk() or tarinfo.issym():
+ self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
+ else:
+ self._dbg(1, tarinfo.name)
+
+ if tarinfo.isreg():
+ self.makefile(tarinfo, targetpath)
+ elif tarinfo.isdir():
+ self.makedir(tarinfo, targetpath)
+ elif tarinfo.isfifo():
+ self.makefifo(tarinfo, targetpath)
+ elif tarinfo.ischr() or tarinfo.isblk():
+ self.makedev(tarinfo, targetpath)
+ elif tarinfo.islnk() or tarinfo.issym():
+ self.makelink(tarinfo, targetpath)
+ elif tarinfo.type not in SUPPORTED_TYPES:
+ self.makeunknown(tarinfo, targetpath)
+ else:
+ self.makefile(tarinfo, targetpath)
+
+ if set_attrs:
+ self.chown(tarinfo, targetpath, numeric_owner)
+ if not tarinfo.issym():
+ self.chmod(tarinfo, targetpath)
+ self.utime(tarinfo, targetpath)
+
+ #--------------------------------------------------------------------------
+ # Below are the different file methods. They are called via
+ # _extract_member() when extract() is called. They can be replaced in a
+ # subclass to implement other functionality.
+
+ def makedir(self, tarinfo, targetpath):
+ """Make a directory called targetpath.
+ """
+ try:
+ if tarinfo.mode is None:
+ # Use the system's default mode
+ os.mkdir(targetpath)
+ else:
+ # Use a safe mode for the directory, the real mode is set
+ # later in _extract_member().
+ os.mkdir(targetpath, 0o700)
+ except FileExistsError:
+ if not os.path.isdir(targetpath):
+ raise
+
+ def makefile(self, tarinfo, targetpath):
+ """Make a file called targetpath.
+ """
+ source = self.fileobj
+ source.seek(tarinfo.offset_data)
+ bufsize = self.copybufsize
+ with bltn_open(targetpath, "wb") as target:
+ if tarinfo.sparse is not None:
+ for offset, size in tarinfo.sparse:
+ target.seek(offset)
+ copyfileobj(source, target, size, ReadError, bufsize)
+ target.seek(tarinfo.size)
+ target.truncate()
+ else:
+ copyfileobj(source, target, tarinfo.size, ReadError, bufsize)
+
+ def makeunknown(self, tarinfo, targetpath):
+ """Make a file from a TarInfo object with an unknown type
+ at targetpath.
+ """
+ self.makefile(tarinfo, targetpath)
+ self._dbg(1, "tarfile: Unknown file type %r, " \
+ "extracted as regular file." % tarinfo.type)
+
+ def makefifo(self, tarinfo, targetpath):
+ """Make a fifo called targetpath.
+ """
+ if hasattr(os, "mkfifo"):
+ os.mkfifo(targetpath)
+ else:
+ raise ExtractError("fifo not supported by system")
+
+ def makedev(self, tarinfo, targetpath):
+ """Make a character or block device called targetpath.
+ """
+ if not hasattr(os, "mknod") or not hasattr(os, "makedev"):
+ raise ExtractError("special devices not supported by system")
+
+ mode = tarinfo.mode
+ if mode is None:
+ # Use mknod's default
+ mode = 0o600
+ if tarinfo.isblk():
+ mode |= stat.S_IFBLK
+ else:
+ mode |= stat.S_IFCHR
+
+ os.mknod(targetpath, mode,
+ os.makedev(tarinfo.devmajor, tarinfo.devminor))
+
+ def makelink(self, tarinfo, targetpath):
+ """Make a (symbolic) link called targetpath. If it cannot be created
+ (platform limitation), we try to make a copy of the referenced file
+ instead of a link.
+ """
+ try:
+ # For systems that support symbolic and hard links.
+ if tarinfo.issym():
+ if os.path.lexists(targetpath):
+ # Avoid FileExistsError on following os.symlink.
+ os.unlink(targetpath)
+ os.symlink(tarinfo.linkname, targetpath)
+ else:
+ if os.path.exists(tarinfo._link_target):
+ os.link(tarinfo._link_target, targetpath)
+ else:
+ self._extract_member(self._find_link_target(tarinfo),
+ targetpath)
+ except symlink_exception:
+ try:
+ self._extract_member(self._find_link_target(tarinfo),
+ targetpath)
+ except KeyError:
+ raise ExtractError("unable to resolve link inside archive") from None
+
+ def chown(self, tarinfo, targetpath, numeric_owner):
+ """Set owner of targetpath according to tarinfo. If numeric_owner
+ is True, use .gid/.uid instead of .gname/.uname. If numeric_owner
+ is False, fall back to .gid/.uid when the search based on name
+ fails.
+ """
+ if hasattr(os, "geteuid") and os.geteuid() == 0:
+ # We have to be root to do so.
+ g = tarinfo.gid
+ u = tarinfo.uid
+ if not numeric_owner:
+ try:
+ if grp and tarinfo.gname:
+ g = grp.getgrnam(tarinfo.gname)[2]
+ except KeyError:
+ pass
+ try:
+ if pwd and tarinfo.uname:
+ u = pwd.getpwnam(tarinfo.uname)[2]
+ except KeyError:
+ pass
+ if g is None:
+ g = -1
+ if u is None:
+ u = -1
+ try:
+ if tarinfo.issym() and hasattr(os, "lchown"):
+ os.lchown(targetpath, u, g)
+ else:
+ os.chown(targetpath, u, g)
+ except (OSError, OverflowError) as e:
+ # OverflowError can be raised if an ID doesn't fit in 'id_t'
+ raise ExtractError("could not change owner") from e
+
+ def chmod(self, tarinfo, targetpath):
+ """Set file permissions of targetpath according to tarinfo.
+ """
+ if tarinfo.mode is None:
+ return
+ try:
+ os.chmod(targetpath, tarinfo.mode)
+ except OSError as e:
+ raise ExtractError("could not change mode") from e
+
+ def utime(self, tarinfo, targetpath):
+ """Set modification time of targetpath according to tarinfo.
+ """
+ mtime = tarinfo.mtime
+ if mtime is None:
+ return
+ if not hasattr(os, 'utime'):
+ return
+ try:
+ os.utime(targetpath, (mtime, mtime))
+ except OSError as e:
+ raise ExtractError("could not change modification time") from e
+
+ #--------------------------------------------------------------------------
+ def next(self):
+ """Return the next member of the archive as a TarInfo object, when
+ TarFile is opened for reading. Return None if there is no more
+ available.
+ """
+ self._check("ra")
+ if self.firstmember is not None:
+ m = self.firstmember
+ self.firstmember = None
+ return m
+
+ # Advance the file pointer.
+ if self.offset != self.fileobj.tell():
+ if self.offset == 0:
+ return None
+ self.fileobj.seek(self.offset - 1)
+ if not self.fileobj.read(1):
+ raise ReadError("unexpected end of data")
+
+ # Read the next block.
+ tarinfo = None
+ while True:
+ try:
+ tarinfo = self.tarinfo.fromtarfile(self)
+ except EOFHeaderError as e:
+ if self.ignore_zeros:
+ self._dbg(2, "0x%X: %s" % (self.offset, e))
+ self.offset += BLOCKSIZE
+ continue
+ except InvalidHeaderError as e:
+ if self.ignore_zeros:
+ self._dbg(2, "0x%X: %s" % (self.offset, e))
+ self.offset += BLOCKSIZE
+ continue
+ elif self.offset == 0:
+ raise ReadError(str(e)) from None
+ except EmptyHeaderError:
+ if self.offset == 0:
+ raise ReadError("empty file") from None
+ except TruncatedHeaderError as e:
+ if self.offset == 0:
+ raise ReadError(str(e)) from None
+ except SubsequentHeaderError as e:
+ raise ReadError(str(e)) from None
+ except Exception as e:
+ try:
+ import zlib
+ if isinstance(e, zlib.error):
+ raise ReadError(f'zlib error: {e}') from None
+ else:
+ raise e
+ except ImportError:
+ raise e
+ break
+
+ if tarinfo is not None:
+ # if streaming the file we do not want to cache the tarinfo
+ if not self.stream:
+ self.members.append(tarinfo)
+ else:
+ self._loaded = True
+
+ return tarinfo
+
+ #--------------------------------------------------------------------------
+ # Little helper methods:
+
+ def _getmember(self, name, tarinfo=None, normalize=False):
+ """Find an archive member by name from bottom to top.
+ If tarinfo is given, it is used as the starting point.
+ """
+ # Ensure that all members have been loaded.
+ members = self.getmembers()
+
+ # Limit the member search list up to tarinfo.
+ skipping = False
+ if tarinfo is not None:
+ try:
+ index = members.index(tarinfo)
+ except ValueError:
+ # The given starting point might be a (modified) copy.
+ # We'll later skip members until we find an equivalent.
+ skipping = True
+ else:
+ # Happy fast path
+ members = members[:index]
+
+ if normalize:
+ name = os.path.normpath(name)
+
+ for member in reversed(members):
+ if skipping:
+ if tarinfo.offset == member.offset:
+ skipping = False
+ continue
+ if normalize:
+ member_name = os.path.normpath(member.name)
+ else:
+ member_name = member.name
+
+ if name == member_name:
+ return member
+
+ if skipping:
+ # Starting point was not found
+ raise ValueError(tarinfo)
+
+ def _load(self):
+ """Read through the entire archive file and look for readable
+ members. This should not run if the file is set to stream.
+ """
+ if not self.stream:
+ while self.next() is not None:
+ pass
+ self._loaded = True
+
+ def _check(self, mode=None):
+ """Check if TarFile is still open, and if the operation's mode
+ corresponds to TarFile's mode.
+ """
+ if self.closed:
+ raise OSError("%s is closed" % self.__class__.__name__)
+ if mode is not None and self.mode not in mode:
+ raise OSError("bad operation for mode %r" % self.mode)
+
+ def _find_link_target(self, tarinfo):
+ """Find the target member of a symlink or hardlink member in the
+ archive.
+ """
+ if tarinfo.issym():
+ # Always search the entire archive.
+ linkname = "/".join(filter(None, (os.path.dirname(tarinfo.name), tarinfo.linkname)))
+ limit = None
+ else:
+ # Search the archive before the link, because a hard link is
+ # just a reference to an already archived file.
+ linkname = tarinfo.linkname
+ limit = tarinfo
+
+ member = self._getmember(linkname, tarinfo=limit, normalize=True)
+ if member is None:
+ raise KeyError("linkname %r not found" % linkname)
+ return member
+
+ def __iter__(self):
+ """Provide an iterator object.
+ """
+ if self._loaded:
+ yield from self.members
+ return
+
+ # Yield items using TarFile's next() method.
+ # When all members have been read, set TarFile as _loaded.
+ index = 0
+ # Fix for SF #1100429: Under rare circumstances it can
+ # happen that getmembers() is called during iteration,
+ # which will have already exhausted the next() method.
+ if self.firstmember is not None:
+ tarinfo = self.next()
+ index += 1
+ yield tarinfo
+
+ while True:
+ if index < len(self.members):
+ tarinfo = self.members[index]
+ elif not self._loaded:
+ tarinfo = self.next()
+ if not tarinfo:
+ self._loaded = True
+ return
+ else:
+ return
+ index += 1
+ yield tarinfo
+
+ def _dbg(self, level, msg):
+ """Write debugging output to sys.stderr.
+ """
+ if level <= self.debug:
+ print(msg, file=sys.stderr)
+
+ def __enter__(self):
+ self._check()
+ return self
+
+ def __exit__(self, type, value, traceback):
+ if type is None:
+ self.close()
+ else:
+ # An exception occurred. We must not call close() because
+ # it would try to write end-of-archive blocks and padding.
+ if not self._extfileobj:
+ self.fileobj.close()
+ self.closed = True
+
+#--------------------
+# exported functions
+#--------------------
+
+def is_tarfile(name):
+ """Return True if name points to a tar archive that we
+ are able to handle, else return False.
+
+ 'name' should be a string, file, or file-like object.
+ """
+ try:
+ if hasattr(name, "read"):
+ pos = name.tell()
+ t = open(fileobj=name)
+ name.seek(pos)
+ else:
+ t = open(name)
+ t.close()
+ return True
+ except TarError:
+ return False
+
+open = TarFile.open
+
+
+def main():
+ import argparse
+
+ description = 'A simple command-line interface for tarfile module.'
+ parser = argparse.ArgumentParser(description=description)
+ parser.add_argument('-v', '--verbose', action='store_true', default=False,
+ help='Verbose output')
+ parser.add_argument('--filter', metavar='',
+ choices=_NAMED_FILTERS,
+ help='Filter for extraction')
+
+ group = parser.add_mutually_exclusive_group(required=True)
+ group.add_argument('-l', '--list', metavar='',
+ help='Show listing of a tarfile')
+ group.add_argument('-e', '--extract', nargs='+',
+ metavar=('', ''),
+ help='Extract tarfile into target dir')
+ group.add_argument('-c', '--create', nargs='+',
+ metavar=('', ''),
+ help='Create tarfile from sources')
+ group.add_argument('-t', '--test', metavar='',
+ help='Test if a tarfile is valid')
+
+ args = parser.parse_args()
+
+ if args.filter and args.extract is None:
+ parser.exit(1, '--filter is only valid for extraction\n')
+
+ if args.test is not None:
+ src = args.test
+ if is_tarfile(src):
+ with open(src, 'r') as tar:
+ tar.getmembers()
+ print(tar.getmembers(), file=sys.stderr)
+ if args.verbose:
+ print('{!r} is a tar archive.'.format(src))
+ else:
+ parser.exit(1, '{!r} is not a tar archive.\n'.format(src))
+
+ elif args.list is not None:
+ src = args.list
+ if is_tarfile(src):
+ with TarFile.open(src, 'r:*') as tf:
+ tf.list(verbose=args.verbose)
+ else:
+ parser.exit(1, '{!r} is not a tar archive.\n'.format(src))
+
+ elif args.extract is not None:
+ if len(args.extract) == 1:
+ src = args.extract[0]
+ curdir = os.curdir
+ elif len(args.extract) == 2:
+ src, curdir = args.extract
+ else:
+ parser.exit(1, parser.format_help())
+
+ if is_tarfile(src):
+ with TarFile.open(src, 'r:*') as tf:
+ tf.extractall(path=curdir, filter=args.filter)
+ if args.verbose:
+ if curdir == '.':
+ msg = '{!r} file is extracted.'.format(src)
+ else:
+ msg = ('{!r} file is extracted '
+ 'into {!r} directory.').format(src, curdir)
+ print(msg)
+ else:
+ parser.exit(1, '{!r} is not a tar archive.\n'.format(src))
+
+ elif args.create is not None:
+ tar_name = args.create.pop(0)
+ _, ext = os.path.splitext(tar_name)
+ compressions = {
+ # gz
+ '.gz': 'gz',
+ '.tgz': 'gz',
+ # xz
+ '.xz': 'xz',
+ '.txz': 'xz',
+ # bz2
+ '.bz2': 'bz2',
+ '.tbz': 'bz2',
+ '.tbz2': 'bz2',
+ '.tb2': 'bz2',
+ }
+ tar_mode = 'w:' + compressions[ext] if ext in compressions else 'w'
+ tar_files = args.create
+
+ with TarFile.open(tar_name, tar_mode) as tf:
+ for file_name in tar_files:
+ tf.add(file_name)
+
+ if args.verbose:
+ print('{!r} file created.'.format(tar_name))
+
+if __name__ == '__main__':
+ main()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__main__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__main__.py
new file mode 100644
index 0000000..daf5509
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__main__.py
@@ -0,0 +1,5 @@
+from . import main
+
+
+if __name__ == '__main__':
+ main()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..00bbae6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__pycache__/__main__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__pycache__/__main__.cpython-312.pyc
new file mode 100644
index 0000000..343f90b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/__pycache__/__main__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/compat/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/compat/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/compat/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/compat/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..26092d0
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/compat/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/compat/__pycache__/py38.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/compat/__pycache__/py38.cpython-312.pyc
new file mode 100644
index 0000000..6be6c29
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/compat/__pycache__/py38.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/compat/py38.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/compat/py38.py
new file mode 100644
index 0000000..20fbbfc
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/backports/tarfile/compat/py38.py
@@ -0,0 +1,24 @@
+import sys
+
+
+if sys.version_info < (3, 9):
+
+ def removesuffix(self, suffix):
+ # suffix='' should not call self[:-0].
+ if suffix and self.endswith(suffix):
+ return self[: -len(suffix)]
+ else:
+ return self[:]
+
+ def removeprefix(self, prefix):
+ if self.startswith(prefix):
+ return self[len(prefix) :]
+ else:
+ return self[:]
+else:
+
+ def removesuffix(self, suffix):
+ return self.removesuffix(suffix)
+
+ def removeprefix(self, prefix):
+ return self.removeprefix(prefix)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/METADATA b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/METADATA
new file mode 100644
index 0000000..85513e8
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/METADATA
@@ -0,0 +1,129 @@
+Metadata-Version: 2.1
+Name: importlib_metadata
+Version: 8.0.0
+Summary: Read metadata from Python packages
+Author-email: "Jason R. Coombs"
+Project-URL: Source, https://github.com/python/importlib_metadata
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+Requires-Python: >=3.8
+Description-Content-Type: text/x-rst
+License-File: LICENSE
+Requires-Dist: zipp >=0.5
+Requires-Dist: typing-extensions >=3.6.4 ; python_version < "3.8"
+Provides-Extra: doc
+Requires-Dist: sphinx >=3.5 ; extra == 'doc'
+Requires-Dist: jaraco.packaging >=9.3 ; extra == 'doc'
+Requires-Dist: rst.linker >=1.9 ; extra == 'doc'
+Requires-Dist: furo ; extra == 'doc'
+Requires-Dist: sphinx-lint ; extra == 'doc'
+Requires-Dist: jaraco.tidelift >=1.4 ; extra == 'doc'
+Provides-Extra: perf
+Requires-Dist: ipython ; extra == 'perf'
+Provides-Extra: test
+Requires-Dist: pytest !=8.1.*,>=6 ; extra == 'test'
+Requires-Dist: pytest-checkdocs >=2.4 ; extra == 'test'
+Requires-Dist: pytest-cov ; extra == 'test'
+Requires-Dist: pytest-mypy ; extra == 'test'
+Requires-Dist: pytest-enabler >=2.2 ; extra == 'test'
+Requires-Dist: pytest-ruff >=0.2.1 ; extra == 'test'
+Requires-Dist: packaging ; extra == 'test'
+Requires-Dist: pyfakefs ; extra == 'test'
+Requires-Dist: flufl.flake8 ; extra == 'test'
+Requires-Dist: pytest-perf >=0.9.2 ; extra == 'test'
+Requires-Dist: jaraco.test >=5.4 ; extra == 'test'
+Requires-Dist: importlib-resources >=1.3 ; (python_version < "3.9") and extra == 'test'
+
+.. image:: https://img.shields.io/pypi/v/importlib_metadata.svg
+ :target: https://pypi.org/project/importlib_metadata
+
+.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg
+
+.. image:: https://github.com/python/importlib_metadata/actions/workflows/main.yml/badge.svg
+ :target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22tests%22
+ :alt: tests
+
+.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+ :target: https://github.com/astral-sh/ruff
+ :alt: Ruff
+
+.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest
+ :target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest
+
+.. image:: https://img.shields.io/badge/skeleton-2024-informational
+ :target: https://blog.jaraco.com/skeleton
+
+.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata
+ :target: https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=readme
+
+Library to access the metadata for a Python package.
+
+This package supplies third-party access to the functionality of
+`importlib.metadata `_
+including improvements added to subsequent Python versions.
+
+
+Compatibility
+=============
+
+New features are introduced in this third-party library and later merged
+into CPython. The following table indicates which versions of this library
+were contributed to different versions in the standard library:
+
+.. list-table::
+ :header-rows: 1
+
+ * - importlib_metadata
+ - stdlib
+ * - 7.0
+ - 3.13
+ * - 6.5
+ - 3.12
+ * - 4.13
+ - 3.11
+ * - 4.6
+ - 3.10
+ * - 1.4
+ - 3.8
+
+
+Usage
+=====
+
+See the `online documentation `_
+for usage details.
+
+`Finder authors
+`_ can
+also add support for custom package installers. See the above documentation
+for details.
+
+
+Caveats
+=======
+
+This project primarily supports third-party packages installed by PyPA
+tools (or other conforming packages). It does not support:
+
+- Packages in the stdlib.
+- Packages installed without metadata.
+
+Project details
+===============
+
+ * Project home: https://github.com/python/importlib_metadata
+ * Report bugs at: https://github.com/python/importlib_metadata/issues
+ * Code hosting: https://github.com/python/importlib_metadata
+ * Documentation: https://importlib-metadata.readthedocs.io/
+
+For Enterprise
+==============
+
+Available as part of the Tidelift Subscription.
+
+This project 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 `_.
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/RECORD b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/RECORD
new file mode 100644
index 0000000..07b7dc5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/RECORD
@@ -0,0 +1,32 @@
+importlib_metadata-8.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+importlib_metadata-8.0.0.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
+importlib_metadata-8.0.0.dist-info/METADATA,sha256=anuQ7_7h4J1bSEzfcjIBakPi2cyVQ7y7jklLHsBeH1k,4648
+importlib_metadata-8.0.0.dist-info/RECORD,,
+importlib_metadata-8.0.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+importlib_metadata-8.0.0.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
+importlib_metadata-8.0.0.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19
+importlib_metadata/__init__.py,sha256=tZNB-23h8Bixi9uCrQqj9Yf0aeC--Josdy3IZRIQeB0,33798
+importlib_metadata/__pycache__/__init__.cpython-312.pyc,,
+importlib_metadata/__pycache__/_adapters.cpython-312.pyc,,
+importlib_metadata/__pycache__/_collections.cpython-312.pyc,,
+importlib_metadata/__pycache__/_compat.cpython-312.pyc,,
+importlib_metadata/__pycache__/_functools.cpython-312.pyc,,
+importlib_metadata/__pycache__/_itertools.cpython-312.pyc,,
+importlib_metadata/__pycache__/_meta.cpython-312.pyc,,
+importlib_metadata/__pycache__/_text.cpython-312.pyc,,
+importlib_metadata/__pycache__/diagnose.cpython-312.pyc,,
+importlib_metadata/_adapters.py,sha256=rIhWTwBvYA1bV7i-5FfVX38qEXDTXFeS5cb5xJtP3ks,2317
+importlib_metadata/_collections.py,sha256=CJ0OTCHIjWA0ZIVS4voORAsn2R4R2cQBEtPsZEJpASY,743
+importlib_metadata/_compat.py,sha256=73QKrN9KNoaZzhbX5yPCCZa-FaALwXe8TPlDR72JgBU,1314
+importlib_metadata/_functools.py,sha256=PsY2-4rrKX4RVeRC1oGp1lB1pmC9eKN88_f-bD9uOoA,2895
+importlib_metadata/_itertools.py,sha256=cvr_2v8BRbxcIl5x5ldfqdHjhI8Yi8s8yk50G_nm6jQ,2068
+importlib_metadata/_meta.py,sha256=nxZ7C8GVlcBFAKWyVOn_dn7ot_twBcbm1NmvjIetBHI,1801
+importlib_metadata/_text.py,sha256=HCsFksZpJLeTP3NEk_ngrAeXVRRtTrtyh9eOABoRP4A,2166
+importlib_metadata/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+importlib_metadata/compat/__pycache__/__init__.cpython-312.pyc,,
+importlib_metadata/compat/__pycache__/py311.cpython-312.pyc,,
+importlib_metadata/compat/__pycache__/py39.cpython-312.pyc,,
+importlib_metadata/compat/py311.py,sha256=uqm-K-uohyj1042TH4a9Er_I5o7667DvulcD-gC_fSA,608
+importlib_metadata/compat/py39.py,sha256=cPkMv6-0ilK-0Jw_Tkn0xYbOKJZc4WJKQHow0c2T44w,1102
+importlib_metadata/diagnose.py,sha256=nkSRMiowlmkhLYhKhvCg9glmt_11Cox-EmLzEbqYTa8,379
+importlib_metadata/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/REQUESTED b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/REQUESTED
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/WHEEL
new file mode 100644
index 0000000..edf4ec7
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: setuptools (70.1.1)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/top_level.txt
new file mode 100644
index 0000000..bbb0754
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata-8.0.0.dist-info/top_level.txt
@@ -0,0 +1 @@
+importlib_metadata
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__init__.py
new file mode 100644
index 0000000..ed48135
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__init__.py
@@ -0,0 +1,1083 @@
+from __future__ import annotations
+
+import os
+import re
+import abc
+import sys
+import json
+import zipp
+import email
+import types
+import inspect
+import pathlib
+import operator
+import textwrap
+import functools
+import itertools
+import posixpath
+import collections
+
+from . import _meta
+from .compat import py39, py311
+from ._collections import FreezableDefaultDict, Pair
+from ._compat import (
+ NullFinder,
+ install,
+)
+from ._functools import method_cache, pass_none
+from ._itertools import always_iterable, unique_everseen
+from ._meta import PackageMetadata, SimplePath
+
+from contextlib import suppress
+from importlib import import_module
+from importlib.abc import MetaPathFinder
+from itertools import starmap
+from typing import Any, Iterable, List, Mapping, Match, Optional, Set, cast
+
+__all__ = [
+ 'Distribution',
+ 'DistributionFinder',
+ 'PackageMetadata',
+ 'PackageNotFoundError',
+ 'distribution',
+ 'distributions',
+ 'entry_points',
+ 'files',
+ 'metadata',
+ 'packages_distributions',
+ 'requires',
+ 'version',
+]
+
+
+class PackageNotFoundError(ModuleNotFoundError):
+ """The package was not found."""
+
+ def __str__(self) -> str:
+ return f"No package metadata was found for {self.name}"
+
+ @property
+ def name(self) -> str: # type: ignore[override]
+ (name,) = self.args
+ return name
+
+
+class Sectioned:
+ """
+ A simple entry point config parser for performance
+
+ >>> for item in Sectioned.read(Sectioned._sample):
+ ... print(item)
+ Pair(name='sec1', value='# comments ignored')
+ Pair(name='sec1', value='a = 1')
+ Pair(name='sec1', value='b = 2')
+ Pair(name='sec2', value='a = 2')
+
+ >>> res = Sectioned.section_pairs(Sectioned._sample)
+ >>> item = next(res)
+ >>> item.name
+ 'sec1'
+ >>> item.value
+ Pair(name='a', value='1')
+ >>> item = next(res)
+ >>> item.value
+ Pair(name='b', value='2')
+ >>> item = next(res)
+ >>> item.name
+ 'sec2'
+ >>> item.value
+ Pair(name='a', value='2')
+ >>> list(res)
+ []
+ """
+
+ _sample = textwrap.dedent(
+ """
+ [sec1]
+ # comments ignored
+ a = 1
+ b = 2
+
+ [sec2]
+ a = 2
+ """
+ ).lstrip()
+
+ @classmethod
+ def section_pairs(cls, text):
+ return (
+ section._replace(value=Pair.parse(section.value))
+ for section in cls.read(text, filter_=cls.valid)
+ if section.name is not None
+ )
+
+ @staticmethod
+ def read(text, filter_=None):
+ lines = filter(filter_, map(str.strip, text.splitlines()))
+ name = None
+ for value in lines:
+ section_match = value.startswith('[') and value.endswith(']')
+ if section_match:
+ name = value.strip('[]')
+ continue
+ yield Pair(name, value)
+
+ @staticmethod
+ def valid(line: str):
+ return line and not line.startswith('#')
+
+
+class EntryPoint:
+ """An entry point as defined by Python packaging conventions.
+
+ See `the packaging docs on entry points
+ `_
+ for more information.
+
+ >>> ep = EntryPoint(
+ ... name=None, group=None, value='package.module:attr [extra1, extra2]')
+ >>> ep.module
+ 'package.module'
+ >>> ep.attr
+ 'attr'
+ >>> ep.extras
+ ['extra1', 'extra2']
+ """
+
+ pattern = re.compile(
+ r'(?P[\w.]+)\s*'
+ r'(:\s*(?P[\w.]+)\s*)?'
+ r'((?P\[.*\])\s*)?$'
+ )
+ """
+ A regular expression describing the syntax for an entry point,
+ which might look like:
+
+ - module
+ - package.module
+ - package.module:attribute
+ - package.module:object.attribute
+ - package.module:attr [extra1, extra2]
+
+ Other combinations are possible as well.
+
+ The expression is lenient about whitespace around the ':',
+ following the attr, and following any extras.
+ """
+
+ name: str
+ value: str
+ group: str
+
+ dist: Optional[Distribution] = None
+
+ def __init__(self, name: str, value: str, group: str) -> None:
+ vars(self).update(name=name, value=value, group=group)
+
+ def load(self) -> Any:
+ """Load the entry point from its definition. If only a module
+ is indicated by the value, return that module. Otherwise,
+ return the named object.
+ """
+ match = cast(Match, self.pattern.match(self.value))
+ module = import_module(match.group('module'))
+ attrs = filter(None, (match.group('attr') or '').split('.'))
+ return functools.reduce(getattr, attrs, module)
+
+ @property
+ def module(self) -> str:
+ match = self.pattern.match(self.value)
+ assert match is not None
+ return match.group('module')
+
+ @property
+ def attr(self) -> str:
+ match = self.pattern.match(self.value)
+ assert match is not None
+ return match.group('attr')
+
+ @property
+ def extras(self) -> List[str]:
+ match = self.pattern.match(self.value)
+ assert match is not None
+ return re.findall(r'\w+', match.group('extras') or '')
+
+ def _for(self, dist):
+ vars(self).update(dist=dist)
+ return self
+
+ def matches(self, **params):
+ """
+ EntryPoint matches the given parameters.
+
+ >>> ep = EntryPoint(group='foo', name='bar', value='bing:bong [extra1, extra2]')
+ >>> ep.matches(group='foo')
+ True
+ >>> ep.matches(name='bar', value='bing:bong [extra1, extra2]')
+ True
+ >>> ep.matches(group='foo', name='other')
+ False
+ >>> ep.matches()
+ True
+ >>> ep.matches(extras=['extra1', 'extra2'])
+ True
+ >>> ep.matches(module='bing')
+ True
+ >>> ep.matches(attr='bong')
+ True
+ """
+ attrs = (getattr(self, param) for param in params)
+ return all(map(operator.eq, params.values(), attrs))
+
+ def _key(self):
+ return self.name, self.value, self.group
+
+ def __lt__(self, other):
+ return self._key() < other._key()
+
+ def __eq__(self, other):
+ return self._key() == other._key()
+
+ def __setattr__(self, name, value):
+ raise AttributeError("EntryPoint objects are immutable.")
+
+ def __repr__(self):
+ return (
+ f'EntryPoint(name={self.name!r}, value={self.value!r}, '
+ f'group={self.group!r})'
+ )
+
+ def __hash__(self) -> int:
+ return hash(self._key())
+
+
+class EntryPoints(tuple):
+ """
+ An immutable collection of selectable EntryPoint objects.
+ """
+
+ __slots__ = ()
+
+ def __getitem__(self, name: str) -> EntryPoint: # type: ignore[override]
+ """
+ Get the EntryPoint in self matching name.
+ """
+ try:
+ return next(iter(self.select(name=name)))
+ except StopIteration:
+ raise KeyError(name)
+
+ def __repr__(self):
+ """
+ Repr with classname and tuple constructor to
+ signal that we deviate from regular tuple behavior.
+ """
+ return '%s(%r)' % (self.__class__.__name__, tuple(self))
+
+ def select(self, **params) -> EntryPoints:
+ """
+ Select entry points from self that match the
+ given parameters (typically group and/or name).
+ """
+ return EntryPoints(ep for ep in self if py39.ep_matches(ep, **params))
+
+ @property
+ def names(self) -> Set[str]:
+ """
+ Return the set of all names of all entry points.
+ """
+ return {ep.name for ep in self}
+
+ @property
+ def groups(self) -> Set[str]:
+ """
+ Return the set of all groups of all entry points.
+ """
+ return {ep.group for ep in self}
+
+ @classmethod
+ def _from_text_for(cls, text, dist):
+ return cls(ep._for(dist) for ep in cls._from_text(text))
+
+ @staticmethod
+ def _from_text(text):
+ return (
+ EntryPoint(name=item.value.name, value=item.value.value, group=item.name)
+ for item in Sectioned.section_pairs(text or '')
+ )
+
+
+class PackagePath(pathlib.PurePosixPath):
+ """A reference to a path in a package"""
+
+ hash: Optional[FileHash]
+ size: int
+ dist: Distribution
+
+ def read_text(self, encoding: str = 'utf-8') -> str: # type: ignore[override]
+ return self.locate().read_text(encoding=encoding)
+
+ def read_binary(self) -> bytes:
+ return self.locate().read_bytes()
+
+ def locate(self) -> SimplePath:
+ """Return a path-like object for this path"""
+ return self.dist.locate_file(self)
+
+
+class FileHash:
+ def __init__(self, spec: str) -> None:
+ self.mode, _, self.value = spec.partition('=')
+
+ def __repr__(self) -> str:
+ return f''
+
+
+class Distribution(metaclass=abc.ABCMeta):
+ """
+ An abstract Python distribution package.
+
+ Custom providers may derive from this class and define
+ the abstract methods to provide a concrete implementation
+ for their environment. Some providers may opt to override
+ the default implementation of some properties to bypass
+ the file-reading mechanism.
+ """
+
+ @abc.abstractmethod
+ def read_text(self, filename) -> Optional[str]:
+ """Attempt to load metadata file given by the name.
+
+ Python distribution metadata is organized by blobs of text
+ typically represented as "files" in the metadata directory
+ (e.g. package-1.0.dist-info). These files include things
+ like:
+
+ - METADATA: The distribution metadata including fields
+ like Name and Version and Description.
+ - entry_points.txt: A series of entry points as defined in
+ `the entry points spec `_.
+ - RECORD: A record of files according to
+ `this recording spec `_.
+
+ A package may provide any set of files, including those
+ not listed here or none at all.
+
+ :param filename: The name of the file in the distribution info.
+ :return: The text if found, otherwise None.
+ """
+
+ @abc.abstractmethod
+ def locate_file(self, path: str | os.PathLike[str]) -> SimplePath:
+ """
+ Given a path to a file in this distribution, return a SimplePath
+ to it.
+ """
+
+ @classmethod
+ def from_name(cls, name: str) -> Distribution:
+ """Return the Distribution for the given package name.
+
+ :param name: The name of the distribution package to search for.
+ :return: The Distribution instance (or subclass thereof) for the named
+ package, if found.
+ :raises PackageNotFoundError: When the named package's distribution
+ metadata cannot be found.
+ :raises ValueError: When an invalid value is supplied for name.
+ """
+ if not name:
+ raise ValueError("A distribution name is required.")
+ try:
+ return next(iter(cls.discover(name=name)))
+ except StopIteration:
+ raise PackageNotFoundError(name)
+
+ @classmethod
+ def discover(
+ cls, *, context: Optional[DistributionFinder.Context] = None, **kwargs
+ ) -> Iterable[Distribution]:
+ """Return an iterable of Distribution objects for all packages.
+
+ Pass a ``context`` or pass keyword arguments for constructing
+ a context.
+
+ :context: A ``DistributionFinder.Context`` object.
+ :return: Iterable of Distribution objects for packages matching
+ the context.
+ """
+ if context and kwargs:
+ raise ValueError("cannot accept context and kwargs")
+ context = context or DistributionFinder.Context(**kwargs)
+ return itertools.chain.from_iterable(
+ resolver(context) for resolver in cls._discover_resolvers()
+ )
+
+ @staticmethod
+ def at(path: str | os.PathLike[str]) -> Distribution:
+ """Return a Distribution for the indicated metadata path.
+
+ :param path: a string or path-like object
+ :return: a concrete Distribution instance for the path
+ """
+ return PathDistribution(pathlib.Path(path))
+
+ @staticmethod
+ def _discover_resolvers():
+ """Search the meta_path for resolvers (MetadataPathFinders)."""
+ declared = (
+ getattr(finder, 'find_distributions', None) for finder in sys.meta_path
+ )
+ return filter(None, declared)
+
+ @property
+ def metadata(self) -> _meta.PackageMetadata:
+ """Return the parsed metadata for this Distribution.
+
+ The returned object will have keys that name the various bits of
+ metadata per the
+ `Core metadata specifications `_.
+
+ Custom providers may provide the METADATA file or override this
+ property.
+ """
+ # deferred for performance (python/cpython#109829)
+ from . import _adapters
+
+ opt_text = (
+ self.read_text('METADATA')
+ or self.read_text('PKG-INFO')
+ # This last clause is here to support old egg-info files. Its
+ # effect is to just end up using the PathDistribution's self._path
+ # (which points to the egg-info file) attribute unchanged.
+ or self.read_text('')
+ )
+ text = cast(str, opt_text)
+ return _adapters.Message(email.message_from_string(text))
+
+ @property
+ def name(self) -> str:
+ """Return the 'Name' metadata for the distribution package."""
+ return self.metadata['Name']
+
+ @property
+ def _normalized_name(self):
+ """Return a normalized version of the name."""
+ return Prepared.normalize(self.name)
+
+ @property
+ def version(self) -> str:
+ """Return the 'Version' metadata for the distribution package."""
+ return self.metadata['Version']
+
+ @property
+ def entry_points(self) -> EntryPoints:
+ """
+ Return EntryPoints for this distribution.
+
+ Custom providers may provide the ``entry_points.txt`` file
+ or override this property.
+ """
+ return EntryPoints._from_text_for(self.read_text('entry_points.txt'), self)
+
+ @property
+ def files(self) -> Optional[List[PackagePath]]:
+ """Files in this distribution.
+
+ :return: List of PackagePath for this distribution or None
+
+ Result is `None` if the metadata file that enumerates files
+ (i.e. RECORD for dist-info, or installed-files.txt or
+ SOURCES.txt for egg-info) is missing.
+ Result may be empty if the metadata exists but is empty.
+
+ Custom providers are recommended to provide a "RECORD" file (in
+ ``read_text``) or override this property to allow for callers to be
+ able to resolve filenames provided by the package.
+ """
+
+ def make_file(name, hash=None, size_str=None):
+ result = PackagePath(name)
+ result.hash = FileHash(hash) if hash else None
+ result.size = int(size_str) if size_str else None
+ result.dist = self
+ return result
+
+ @pass_none
+ def make_files(lines):
+ # Delay csv import, since Distribution.files is not as widely used
+ # as other parts of importlib.metadata
+ import csv
+
+ return starmap(make_file, csv.reader(lines))
+
+ @pass_none
+ def skip_missing_files(package_paths):
+ return list(filter(lambda path: path.locate().exists(), package_paths))
+
+ return skip_missing_files(
+ make_files(
+ self._read_files_distinfo()
+ or self._read_files_egginfo_installed()
+ or self._read_files_egginfo_sources()
+ )
+ )
+
+ def _read_files_distinfo(self):
+ """
+ Read the lines of RECORD.
+ """
+ text = self.read_text('RECORD')
+ return text and text.splitlines()
+
+ def _read_files_egginfo_installed(self):
+ """
+ Read installed-files.txt and return lines in a similar
+ CSV-parsable format as RECORD: each file must be placed
+ relative to the site-packages directory and must also be
+ quoted (since file names can contain literal commas).
+
+ This file is written when the package is installed by pip,
+ but it might not be written for other installation methods.
+ Assume the file is accurate if it exists.
+ """
+ text = self.read_text('installed-files.txt')
+ # Prepend the .egg-info/ subdir to the lines in this file.
+ # But this subdir is only available from PathDistribution's
+ # self._path.
+ subdir = getattr(self, '_path', None)
+ if not text or not subdir:
+ return
+
+ paths = (
+ py311.relative_fix((subdir / name).resolve())
+ .relative_to(self.locate_file('').resolve(), walk_up=True)
+ .as_posix()
+ for name in text.splitlines()
+ )
+ return map('"{}"'.format, paths)
+
+ def _read_files_egginfo_sources(self):
+ """
+ Read SOURCES.txt and return lines in a similar CSV-parsable
+ format as RECORD: each file name must be quoted (since it
+ might contain literal commas).
+
+ Note that SOURCES.txt is not a reliable source for what
+ files are installed by a package. This file is generated
+ for a source archive, and the files that are present
+ there (e.g. setup.py) may not correctly reflect the files
+ that are present after the package has been installed.
+ """
+ text = self.read_text('SOURCES.txt')
+ return text and map('"{}"'.format, text.splitlines())
+
+ @property
+ def requires(self) -> Optional[List[str]]:
+ """Generated requirements specified for this Distribution"""
+ reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs()
+ return reqs and list(reqs)
+
+ def _read_dist_info_reqs(self):
+ return self.metadata.get_all('Requires-Dist')
+
+ def _read_egg_info_reqs(self):
+ source = self.read_text('requires.txt')
+ return pass_none(self._deps_from_requires_text)(source)
+
+ @classmethod
+ def _deps_from_requires_text(cls, source):
+ return cls._convert_egg_info_reqs_to_simple_reqs(Sectioned.read(source))
+
+ @staticmethod
+ def _convert_egg_info_reqs_to_simple_reqs(sections):
+ """
+ Historically, setuptools would solicit and store 'extra'
+ requirements, including those with environment markers,
+ in separate sections. More modern tools expect each
+ dependency to be defined separately, with any relevant
+ extras and environment markers attached directly to that
+ requirement. This method converts the former to the
+ latter. See _test_deps_from_requires_text for an example.
+ """
+
+ def make_condition(name):
+ return name and f'extra == "{name}"'
+
+ def quoted_marker(section):
+ section = section or ''
+ extra, sep, markers = section.partition(':')
+ if extra and markers:
+ markers = f'({markers})'
+ conditions = list(filter(None, [markers, make_condition(extra)]))
+ return '; ' + ' and '.join(conditions) if conditions else ''
+
+ def url_req_space(req):
+ """
+ PEP 508 requires a space between the url_spec and the quoted_marker.
+ Ref python/importlib_metadata#357.
+ """
+ # '@' is uniquely indicative of a url_req.
+ return ' ' * ('@' in req)
+
+ for section in sections:
+ space = url_req_space(section.value)
+ yield section.value + space + quoted_marker(section.name)
+
+ @property
+ def origin(self):
+ return self._load_json('direct_url.json')
+
+ def _load_json(self, filename):
+ return pass_none(json.loads)(
+ self.read_text(filename),
+ object_hook=lambda data: types.SimpleNamespace(**data),
+ )
+
+
+class DistributionFinder(MetaPathFinder):
+ """
+ A MetaPathFinder capable of discovering installed distributions.
+
+ Custom providers should implement this interface in order to
+ supply metadata.
+ """
+
+ class Context:
+ """
+ Keyword arguments presented by the caller to
+ ``distributions()`` or ``Distribution.discover()``
+ to narrow the scope of a search for distributions
+ in all DistributionFinders.
+
+ Each DistributionFinder may expect any parameters
+ and should attempt to honor the canonical
+ parameters defined below when appropriate.
+
+ This mechanism gives a custom provider a means to
+ solicit additional details from the caller beyond
+ "name" and "path" when searching distributions.
+ For example, imagine a provider that exposes suites
+ of packages in either a "public" or "private" ``realm``.
+ A caller may wish to query only for distributions in
+ a particular realm and could call
+ ``distributions(realm="private")`` to signal to the
+ custom provider to only include distributions from that
+ realm.
+ """
+
+ name = None
+ """
+ Specific name for which a distribution finder should match.
+ A name of ``None`` matches all distributions.
+ """
+
+ def __init__(self, **kwargs):
+ vars(self).update(kwargs)
+
+ @property
+ def path(self) -> List[str]:
+ """
+ The sequence of directory path that a distribution finder
+ should search.
+
+ Typically refers to Python installed package paths such as
+ "site-packages" directories and defaults to ``sys.path``.
+ """
+ return vars(self).get('path', sys.path)
+
+ @abc.abstractmethod
+ def find_distributions(self, context=Context()) -> Iterable[Distribution]:
+ """
+ Find distributions.
+
+ Return an iterable of all Distribution instances capable of
+ loading the metadata for packages matching the ``context``,
+ a DistributionFinder.Context instance.
+ """
+
+
+class FastPath:
+ """
+ Micro-optimized class for searching a root for children.
+
+ Root is a path on the file system that may contain metadata
+ directories either as natural directories or within a zip file.
+
+ >>> FastPath('').children()
+ ['...']
+
+ FastPath objects are cached and recycled for any given root.
+
+ >>> FastPath('foobar') is FastPath('foobar')
+ True
+ """
+
+ @functools.lru_cache() # type: ignore
+ def __new__(cls, root):
+ return super().__new__(cls)
+
+ def __init__(self, root):
+ self.root = root
+
+ def joinpath(self, child):
+ return pathlib.Path(self.root, child)
+
+ def children(self):
+ with suppress(Exception):
+ return os.listdir(self.root or '.')
+ with suppress(Exception):
+ return self.zip_children()
+ return []
+
+ def zip_children(self):
+ zip_path = zipp.Path(self.root)
+ names = zip_path.root.namelist()
+ self.joinpath = zip_path.joinpath
+
+ return dict.fromkeys(child.split(posixpath.sep, 1)[0] for child in names)
+
+ def search(self, name):
+ return self.lookup(self.mtime).search(name)
+
+ @property
+ def mtime(self):
+ with suppress(OSError):
+ return os.stat(self.root).st_mtime
+ self.lookup.cache_clear()
+
+ @method_cache
+ def lookup(self, mtime):
+ return Lookup(self)
+
+
+class Lookup:
+ """
+ A micro-optimized class for searching a (fast) path for metadata.
+ """
+
+ def __init__(self, path: FastPath):
+ """
+ Calculate all of the children representing metadata.
+
+ From the children in the path, calculate early all of the
+ children that appear to represent metadata (infos) or legacy
+ metadata (eggs).
+ """
+
+ base = os.path.basename(path.root).lower()
+ base_is_egg = base.endswith(".egg")
+ self.infos = FreezableDefaultDict(list)
+ self.eggs = FreezableDefaultDict(list)
+
+ for child in path.children():
+ low = child.lower()
+ if low.endswith((".dist-info", ".egg-info")):
+ # rpartition is faster than splitext and suitable for this purpose.
+ name = low.rpartition(".")[0].partition("-")[0]
+ normalized = Prepared.normalize(name)
+ self.infos[normalized].append(path.joinpath(child))
+ elif base_is_egg and low == "egg-info":
+ name = base.rpartition(".")[0].partition("-")[0]
+ legacy_normalized = Prepared.legacy_normalize(name)
+ self.eggs[legacy_normalized].append(path.joinpath(child))
+
+ self.infos.freeze()
+ self.eggs.freeze()
+
+ def search(self, prepared: Prepared):
+ """
+ Yield all infos and eggs matching the Prepared query.
+ """
+ infos = (
+ self.infos[prepared.normalized]
+ if prepared
+ else itertools.chain.from_iterable(self.infos.values())
+ )
+ eggs = (
+ self.eggs[prepared.legacy_normalized]
+ if prepared
+ else itertools.chain.from_iterable(self.eggs.values())
+ )
+ return itertools.chain(infos, eggs)
+
+
+class Prepared:
+ """
+ A prepared search query for metadata on a possibly-named package.
+
+ Pre-calculates the normalization to prevent repeated operations.
+
+ >>> none = Prepared(None)
+ >>> none.normalized
+ >>> none.legacy_normalized
+ >>> bool(none)
+ False
+ >>> sample = Prepared('Sample__Pkg-name.foo')
+ >>> sample.normalized
+ 'sample_pkg_name_foo'
+ >>> sample.legacy_normalized
+ 'sample__pkg_name.foo'
+ >>> bool(sample)
+ True
+ """
+
+ normalized = None
+ legacy_normalized = None
+
+ def __init__(self, name: Optional[str]):
+ self.name = name
+ if name is None:
+ return
+ self.normalized = self.normalize(name)
+ self.legacy_normalized = self.legacy_normalize(name)
+
+ @staticmethod
+ def normalize(name):
+ """
+ PEP 503 normalization plus dashes as underscores.
+ """
+ return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_')
+
+ @staticmethod
+ def legacy_normalize(name):
+ """
+ Normalize the package name as found in the convention in
+ older packaging tools versions and specs.
+ """
+ return name.lower().replace('-', '_')
+
+ def __bool__(self):
+ return bool(self.name)
+
+
+@install
+class MetadataPathFinder(NullFinder, DistributionFinder):
+ """A degenerate finder for distribution packages on the file system.
+
+ This finder supplies only a find_distributions() method for versions
+ of Python that do not have a PathFinder find_distributions().
+ """
+
+ @classmethod
+ def find_distributions(
+ cls, context=DistributionFinder.Context()
+ ) -> Iterable[PathDistribution]:
+ """
+ Find distributions.
+
+ Return an iterable of all Distribution instances capable of
+ loading the metadata for packages matching ``context.name``
+ (or all names if ``None`` indicated) along the paths in the list
+ of directories ``context.path``.
+ """
+ found = cls._search_paths(context.name, context.path)
+ return map(PathDistribution, found)
+
+ @classmethod
+ def _search_paths(cls, name, paths):
+ """Find metadata directories in paths heuristically."""
+ prepared = Prepared(name)
+ return itertools.chain.from_iterable(
+ path.search(prepared) for path in map(FastPath, paths)
+ )
+
+ @classmethod
+ def invalidate_caches(cls) -> None:
+ FastPath.__new__.cache_clear()
+
+
+class PathDistribution(Distribution):
+ def __init__(self, path: SimplePath) -> None:
+ """Construct a distribution.
+
+ :param path: SimplePath indicating the metadata directory.
+ """
+ self._path = path
+
+ def read_text(self, filename: str | os.PathLike[str]) -> Optional[str]:
+ with suppress(
+ FileNotFoundError,
+ IsADirectoryError,
+ KeyError,
+ NotADirectoryError,
+ PermissionError,
+ ):
+ return self._path.joinpath(filename).read_text(encoding='utf-8')
+
+ return None
+
+ read_text.__doc__ = Distribution.read_text.__doc__
+
+ def locate_file(self, path: str | os.PathLike[str]) -> SimplePath:
+ return self._path.parent / path
+
+ @property
+ def _normalized_name(self):
+ """
+ Performance optimization: where possible, resolve the
+ normalized name from the file system path.
+ """
+ stem = os.path.basename(str(self._path))
+ return (
+ pass_none(Prepared.normalize)(self._name_from_stem(stem))
+ or super()._normalized_name
+ )
+
+ @staticmethod
+ def _name_from_stem(stem):
+ """
+ >>> PathDistribution._name_from_stem('foo-3.0.egg-info')
+ 'foo'
+ >>> PathDistribution._name_from_stem('CherryPy-3.0.dist-info')
+ 'CherryPy'
+ >>> PathDistribution._name_from_stem('face.egg-info')
+ 'face'
+ >>> PathDistribution._name_from_stem('foo.bar')
+ """
+ filename, ext = os.path.splitext(stem)
+ if ext not in ('.dist-info', '.egg-info'):
+ return
+ name, sep, rest = filename.partition('-')
+ return name
+
+
+def distribution(distribution_name: str) -> Distribution:
+ """Get the ``Distribution`` instance for the named package.
+
+ :param distribution_name: The name of the distribution package as a string.
+ :return: A ``Distribution`` instance (or subclass thereof).
+ """
+ return Distribution.from_name(distribution_name)
+
+
+def distributions(**kwargs) -> Iterable[Distribution]:
+ """Get all ``Distribution`` instances in the current environment.
+
+ :return: An iterable of ``Distribution`` instances.
+ """
+ return Distribution.discover(**kwargs)
+
+
+def metadata(distribution_name: str) -> _meta.PackageMetadata:
+ """Get the metadata for the named package.
+
+ :param distribution_name: The name of the distribution package to query.
+ :return: A PackageMetadata containing the parsed metadata.
+ """
+ return Distribution.from_name(distribution_name).metadata
+
+
+def version(distribution_name: str) -> str:
+ """Get the version string for the named package.
+
+ :param distribution_name: The name of the distribution package to query.
+ :return: The version string for the package as defined in the package's
+ "Version" metadata key.
+ """
+ return distribution(distribution_name).version
+
+
+_unique = functools.partial(
+ unique_everseen,
+ key=py39.normalized_name,
+)
+"""
+Wrapper for ``distributions`` to return unique distributions by name.
+"""
+
+
+def entry_points(**params) -> EntryPoints:
+ """Return EntryPoint objects for all installed packages.
+
+ Pass selection parameters (group or name) to filter the
+ result to entry points matching those properties (see
+ EntryPoints.select()).
+
+ :return: EntryPoints for all installed packages.
+ """
+ eps = itertools.chain.from_iterable(
+ dist.entry_points for dist in _unique(distributions())
+ )
+ return EntryPoints(eps).select(**params)
+
+
+def files(distribution_name: str) -> Optional[List[PackagePath]]:
+ """Return a list of files for the named package.
+
+ :param distribution_name: The name of the distribution package to query.
+ :return: List of files composing the distribution.
+ """
+ return distribution(distribution_name).files
+
+
+def requires(distribution_name: str) -> Optional[List[str]]:
+ """
+ Return a list of requirements for the named package.
+
+ :return: An iterable of requirements, suitable for
+ packaging.requirement.Requirement.
+ """
+ return distribution(distribution_name).requires
+
+
+def packages_distributions() -> Mapping[str, List[str]]:
+ """
+ Return a mapping of top-level packages to their
+ distributions.
+
+ >>> import collections.abc
+ >>> pkgs = packages_distributions()
+ >>> all(isinstance(dist, collections.abc.Sequence) for dist in pkgs.values())
+ True
+ """
+ pkg_to_dist = collections.defaultdict(list)
+ for dist in distributions():
+ for pkg in _top_level_declared(dist) or _top_level_inferred(dist):
+ pkg_to_dist[pkg].append(dist.metadata['Name'])
+ return dict(pkg_to_dist)
+
+
+def _top_level_declared(dist):
+ return (dist.read_text('top_level.txt') or '').split()
+
+
+def _topmost(name: PackagePath) -> Optional[str]:
+ """
+ Return the top-most parent as long as there is a parent.
+ """
+ top, *rest = name.parts
+ return top if rest else None
+
+
+def _get_toplevel_name(name: PackagePath) -> str:
+ """
+ Infer a possibly importable module name from a name presumed on
+ sys.path.
+
+ >>> _get_toplevel_name(PackagePath('foo.py'))
+ 'foo'
+ >>> _get_toplevel_name(PackagePath('foo'))
+ 'foo'
+ >>> _get_toplevel_name(PackagePath('foo.pyc'))
+ 'foo'
+ >>> _get_toplevel_name(PackagePath('foo/__init__.py'))
+ 'foo'
+ >>> _get_toplevel_name(PackagePath('foo.pth'))
+ 'foo.pth'
+ >>> _get_toplevel_name(PackagePath('foo.dist-info'))
+ 'foo.dist-info'
+ """
+ return _topmost(name) or (
+ # python/typeshed#10328
+ inspect.getmodulename(name) # type: ignore
+ or str(name)
+ )
+
+
+def _top_level_inferred(dist):
+ opt_names = set(map(_get_toplevel_name, always_iterable(dist.files)))
+
+ def importable_name(name):
+ return '.' not in name
+
+ return filter(importable_name, opt_names)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..b42fbea
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_adapters.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_adapters.cpython-312.pyc
new file mode 100644
index 0000000..8adeef4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_adapters.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_collections.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_collections.cpython-312.pyc
new file mode 100644
index 0000000..d07030b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_collections.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_compat.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_compat.cpython-312.pyc
new file mode 100644
index 0000000..b0f0020
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_compat.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_functools.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_functools.cpython-312.pyc
new file mode 100644
index 0000000..5711479
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_functools.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_itertools.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_itertools.cpython-312.pyc
new file mode 100644
index 0000000..96e0467
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_itertools.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_meta.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_meta.cpython-312.pyc
new file mode 100644
index 0000000..a1fc694
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_meta.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_text.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_text.cpython-312.pyc
new file mode 100644
index 0000000..7eeaf6a
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_text.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/diagnose.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/diagnose.cpython-312.pyc
new file mode 100644
index 0000000..f338896
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/diagnose.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_adapters.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_adapters.py
new file mode 100644
index 0000000..6223263
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_adapters.py
@@ -0,0 +1,83 @@
+import re
+import textwrap
+import email.message
+
+from ._text import FoldedCase
+
+
+class Message(email.message.Message):
+ multiple_use_keys = set(
+ map(
+ FoldedCase,
+ [
+ 'Classifier',
+ 'Obsoletes-Dist',
+ 'Platform',
+ 'Project-URL',
+ 'Provides-Dist',
+ 'Provides-Extra',
+ 'Requires-Dist',
+ 'Requires-External',
+ 'Supported-Platform',
+ 'Dynamic',
+ ],
+ )
+ )
+ """
+ Keys that may be indicated multiple times per PEP 566.
+ """
+
+ def __new__(cls, orig: email.message.Message):
+ res = super().__new__(cls)
+ vars(res).update(vars(orig))
+ return res
+
+ def __init__(self, *args, **kwargs):
+ self._headers = self._repair_headers()
+
+ # suppress spurious error from mypy
+ def __iter__(self):
+ return super().__iter__()
+
+ def __getitem__(self, item):
+ """
+ Override parent behavior to typical dict behavior.
+
+ ``email.message.Message`` will emit None values for missing
+ keys. Typical mappings, including this ``Message``, will raise
+ a key error for missing keys.
+
+ Ref python/importlib_metadata#371.
+ """
+ res = super().__getitem__(item)
+ if res is None:
+ raise KeyError(item)
+ return res
+
+ def _repair_headers(self):
+ def redent(value):
+ "Correct for RFC822 indentation"
+ if not value or '\n' not in value:
+ return value
+ return textwrap.dedent(' ' * 8 + value)
+
+ headers = [(key, redent(value)) for key, value in vars(self)['_headers']]
+ if self._payload:
+ headers.append(('Description', self.get_payload()))
+ return headers
+
+ @property
+ def json(self):
+ """
+ Convert PackageMetadata to a JSON-compatible format
+ per PEP 0566.
+ """
+
+ def transform(key):
+ value = self.get_all(key) if key in self.multiple_use_keys else self[key]
+ if key == 'Keywords':
+ value = re.split(r'\s+', value)
+ tk = key.lower().replace('-', '_')
+ return tk, value
+
+ return dict(map(transform, map(FoldedCase, self)))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_collections.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_collections.py
new file mode 100644
index 0000000..cf0954e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_collections.py
@@ -0,0 +1,30 @@
+import collections
+
+
+# from jaraco.collections 3.3
+class FreezableDefaultDict(collections.defaultdict):
+ """
+ Often it is desirable to prevent the mutation of
+ a default dict after its initial construction, such
+ as to prevent mutation during iteration.
+
+ >>> dd = FreezableDefaultDict(list)
+ >>> dd[0].append('1')
+ >>> dd.freeze()
+ >>> dd[1]
+ []
+ >>> len(dd)
+ 1
+ """
+
+ def __missing__(self, key):
+ return getattr(self, '_frozen', super().__missing__)(key)
+
+ def freeze(self):
+ self._frozen = lambda key: self.default_factory()
+
+
+class Pair(collections.namedtuple('Pair', 'name value')):
+ @classmethod
+ def parse(cls, text):
+ return cls(*map(str.strip, text.split("=", 1)))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_compat.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_compat.py
new file mode 100644
index 0000000..df312b1
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_compat.py
@@ -0,0 +1,57 @@
+import sys
+import platform
+
+
+__all__ = ['install', 'NullFinder']
+
+
+def install(cls):
+ """
+ Class decorator for installation on sys.meta_path.
+
+ Adds the backport DistributionFinder to sys.meta_path and
+ attempts to disable the finder functionality of the stdlib
+ DistributionFinder.
+ """
+ sys.meta_path.append(cls())
+ disable_stdlib_finder()
+ return cls
+
+
+def disable_stdlib_finder():
+ """
+ Give the backport primacy for discovering path-based distributions
+ by monkey-patching the stdlib O_O.
+
+ See #91 for more background for rationale on this sketchy
+ behavior.
+ """
+
+ def matches(finder):
+ return getattr(
+ finder, '__module__', None
+ ) == '_frozen_importlib_external' and hasattr(finder, 'find_distributions')
+
+ for finder in filter(matches, sys.meta_path): # pragma: nocover
+ del finder.find_distributions
+
+
+class NullFinder:
+ """
+ A "Finder" (aka "MetaPathFinder") that never finds any modules,
+ but may find distributions.
+ """
+
+ @staticmethod
+ def find_spec(*args, **kwargs):
+ return None
+
+
+def pypy_partial(val):
+ """
+ Adjust for variable stacklevel on partial under PyPy.
+
+ Workaround for #327.
+ """
+ is_pypy = platform.python_implementation() == 'PyPy'
+ return val + is_pypy
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_functools.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_functools.py
new file mode 100644
index 0000000..71f66bd
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_functools.py
@@ -0,0 +1,104 @@
+import types
+import functools
+
+
+# from jaraco.functools 3.3
+def method_cache(method, cache_wrapper=None):
+ """
+ Wrap lru_cache to support storing the cache data in the object instances.
+
+ Abstracts the common paradigm where the method explicitly saves an
+ underscore-prefixed protected property on first call and returns that
+ subsequently.
+
+ >>> class MyClass:
+ ... calls = 0
+ ...
+ ... @method_cache
+ ... def method(self, value):
+ ... self.calls += 1
+ ... return value
+
+ >>> a = MyClass()
+ >>> a.method(3)
+ 3
+ >>> for x in range(75):
+ ... res = a.method(x)
+ >>> a.calls
+ 75
+
+ Note that the apparent behavior will be exactly like that of lru_cache
+ except that the cache is stored on each instance, so values in one
+ instance will not flush values from another, and when an instance is
+ deleted, so are the cached values for that instance.
+
+ >>> b = MyClass()
+ >>> for x in range(35):
+ ... res = b.method(x)
+ >>> b.calls
+ 35
+ >>> a.method(0)
+ 0
+ >>> a.calls
+ 75
+
+ Note that if method had been decorated with ``functools.lru_cache()``,
+ a.calls would have been 76 (due to the cached value of 0 having been
+ flushed by the 'b' instance).
+
+ Clear the cache with ``.cache_clear()``
+
+ >>> a.method.cache_clear()
+
+ Same for a method that hasn't yet been called.
+
+ >>> c = MyClass()
+ >>> c.method.cache_clear()
+
+ Another cache wrapper may be supplied:
+
+ >>> cache = functools.lru_cache(maxsize=2)
+ >>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache)
+ >>> a = MyClass()
+ >>> a.method2()
+ 3
+
+ Caution - do not subsequently wrap the method with another decorator, such
+ as ``@property``, which changes the semantics of the function.
+
+ See also
+ http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/
+ for another implementation and additional justification.
+ """
+ cache_wrapper = cache_wrapper or functools.lru_cache()
+
+ def wrapper(self, *args, **kwargs):
+ # it's the first call, replace the method with a cached, bound method
+ bound_method = types.MethodType(method, self)
+ cached_method = cache_wrapper(bound_method)
+ setattr(self, method.__name__, cached_method)
+ return cached_method(*args, **kwargs)
+
+ # Support cache clear even before cache has been created.
+ wrapper.cache_clear = lambda: None
+
+ return wrapper
+
+
+# From jaraco.functools 3.3
+def pass_none(func):
+ """
+ Wrap func so it's not called if its first param is None
+
+ >>> print_text = pass_none(print)
+ >>> print_text('text')
+ text
+ >>> print_text(None)
+ """
+
+ @functools.wraps(func)
+ def wrapper(param, *args, **kwargs):
+ if param is not None:
+ return func(param, *args, **kwargs)
+
+ return wrapper
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_itertools.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_itertools.py
new file mode 100644
index 0000000..d4ca9b9
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_itertools.py
@@ -0,0 +1,73 @@
+from itertools import filterfalse
+
+
+def unique_everseen(iterable, key=None):
+ "List unique elements, preserving order. Remember all elements ever seen."
+ # unique_everseen('AAAABBBCCDAABBB') --> A B C D
+ # unique_everseen('ABBCcAD', str.lower) --> A B C D
+ seen = set()
+ seen_add = seen.add
+ if key is None:
+ for element in filterfalse(seen.__contains__, iterable):
+ seen_add(element)
+ yield element
+ else:
+ for element in iterable:
+ k = key(element)
+ if k not in seen:
+ seen_add(k)
+ yield element
+
+
+# copied from more_itertools 8.8
+def always_iterable(obj, base_type=(str, bytes)):
+ """If *obj* is iterable, return an iterator over its items::
+
+ >>> obj = (1, 2, 3)
+ >>> list(always_iterable(obj))
+ [1, 2, 3]
+
+ If *obj* is not iterable, return a one-item iterable containing *obj*::
+
+ >>> obj = 1
+ >>> list(always_iterable(obj))
+ [1]
+
+ If *obj* is ``None``, return an empty iterable:
+
+ >>> obj = None
+ >>> list(always_iterable(None))
+ []
+
+ By default, binary and text strings are not considered iterable::
+
+ >>> obj = 'foo'
+ >>> list(always_iterable(obj))
+ ['foo']
+
+ If *base_type* is set, objects for which ``isinstance(obj, base_type)``
+ returns ``True`` won't be considered iterable.
+
+ >>> obj = {'a': 1}
+ >>> list(always_iterable(obj)) # Iterate over the dict's keys
+ ['a']
+ >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit
+ [{'a': 1}]
+
+ Set *base_type* to ``None`` to avoid any special handling and treat objects
+ Python considers iterable as iterable:
+
+ >>> obj = 'foo'
+ >>> list(always_iterable(obj, base_type=None))
+ ['f', 'o', 'o']
+ """
+ if obj is None:
+ return iter(())
+
+ if (base_type is not None) and isinstance(obj, base_type):
+ return iter((obj,))
+
+ try:
+ return iter(obj)
+ except TypeError:
+ return iter((obj,))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_meta.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_meta.py
new file mode 100644
index 0000000..1927d0f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_meta.py
@@ -0,0 +1,67 @@
+from __future__ import annotations
+
+import os
+from typing import Protocol
+from typing import Any, Dict, Iterator, List, Optional, TypeVar, Union, overload
+
+
+_T = TypeVar("_T")
+
+
+class PackageMetadata(Protocol):
+ def __len__(self) -> int: ... # pragma: no cover
+
+ def __contains__(self, item: str) -> bool: ... # pragma: no cover
+
+ def __getitem__(self, key: str) -> str: ... # pragma: no cover
+
+ def __iter__(self) -> Iterator[str]: ... # pragma: no cover
+
+ @overload
+ def get(
+ self, name: str, failobj: None = None
+ ) -> Optional[str]: ... # pragma: no cover
+
+ @overload
+ def get(self, name: str, failobj: _T) -> Union[str, _T]: ... # pragma: no cover
+
+ # overload per python/importlib_metadata#435
+ @overload
+ def get_all(
+ self, name: str, failobj: None = None
+ ) -> Optional[List[Any]]: ... # pragma: no cover
+
+ @overload
+ def get_all(self, name: str, failobj: _T) -> Union[List[Any], _T]:
+ """
+ Return all values associated with a possibly multi-valued key.
+ """
+
+ @property
+ def json(self) -> Dict[str, Union[str, List[str]]]:
+ """
+ A JSON-compatible form of the metadata.
+ """
+
+
+class SimplePath(Protocol):
+ """
+ A minimal subset of pathlib.Path required by Distribution.
+ """
+
+ def joinpath(
+ self, other: Union[str, os.PathLike[str]]
+ ) -> SimplePath: ... # pragma: no cover
+
+ def __truediv__(
+ self, other: Union[str, os.PathLike[str]]
+ ) -> SimplePath: ... # pragma: no cover
+
+ @property
+ def parent(self) -> SimplePath: ... # pragma: no cover
+
+ def read_text(self, encoding=None) -> str: ... # pragma: no cover
+
+ def read_bytes(self) -> bytes: ... # pragma: no cover
+
+ def exists(self) -> bool: ... # pragma: no cover
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_text.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_text.py
new file mode 100644
index 0000000..c88cfbb
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/_text.py
@@ -0,0 +1,99 @@
+import re
+
+from ._functools import method_cache
+
+
+# from jaraco.text 3.5
+class FoldedCase(str):
+ """
+ A case insensitive string class; behaves just like str
+ except compares equal when the only variation is case.
+
+ >>> s = FoldedCase('hello world')
+
+ >>> s == 'Hello World'
+ True
+
+ >>> 'Hello World' == s
+ True
+
+ >>> s != 'Hello World'
+ False
+
+ >>> s.index('O')
+ 4
+
+ >>> s.split('O')
+ ['hell', ' w', 'rld']
+
+ >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta']))
+ ['alpha', 'Beta', 'GAMMA']
+
+ Sequence membership is straightforward.
+
+ >>> "Hello World" in [s]
+ True
+ >>> s in ["Hello World"]
+ True
+
+ You may test for set inclusion, but candidate and elements
+ must both be folded.
+
+ >>> FoldedCase("Hello World") in {s}
+ True
+ >>> s in {FoldedCase("Hello World")}
+ True
+
+ String inclusion works as long as the FoldedCase object
+ is on the right.
+
+ >>> "hello" in FoldedCase("Hello World")
+ True
+
+ But not if the FoldedCase object is on the left:
+
+ >>> FoldedCase('hello') in 'Hello World'
+ False
+
+ In that case, use in_:
+
+ >>> FoldedCase('hello').in_('Hello World')
+ True
+
+ >>> FoldedCase('hello') > FoldedCase('Hello')
+ False
+ """
+
+ def __lt__(self, other):
+ return self.lower() < other.lower()
+
+ def __gt__(self, other):
+ return self.lower() > other.lower()
+
+ def __eq__(self, other):
+ return self.lower() == other.lower()
+
+ def __ne__(self, other):
+ return self.lower() != other.lower()
+
+ def __hash__(self):
+ return hash(self.lower())
+
+ def __contains__(self, other):
+ return super().lower().__contains__(other.lower())
+
+ def in_(self, other):
+ "Does self appear in other?"
+ return self in FoldedCase(other)
+
+ # cache lower since it's likely to be called frequently.
+ @method_cache
+ def lower(self):
+ return super().lower()
+
+ def index(self, sub):
+ return self.lower().index(sub.lower())
+
+ def split(self, splitter=' ', maxsplit=0):
+ pattern = re.compile(re.escape(splitter), re.I)
+ return pattern.split(self, maxsplit)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..0e1630c
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/__pycache__/py311.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/__pycache__/py311.cpython-312.pyc
new file mode 100644
index 0000000..1ecd362
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/__pycache__/py311.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/__pycache__/py39.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/__pycache__/py39.cpython-312.pyc
new file mode 100644
index 0000000..921e05f
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/__pycache__/py39.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/py311.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/py311.py
new file mode 100644
index 0000000..3a53274
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/py311.py
@@ -0,0 +1,22 @@
+import os
+import pathlib
+import sys
+import types
+
+
+def wrap(path): # pragma: no cover
+ """
+ Workaround for https://github.com/python/cpython/issues/84538
+ to add backward compatibility for walk_up=True.
+ An example affected package is dask-labextension, which uses
+ jupyter-packaging to install JupyterLab javascript files outside
+ of site-packages.
+ """
+
+ def relative_to(root, *, walk_up=False):
+ return pathlib.Path(os.path.relpath(path, root))
+
+ return types.SimpleNamespace(relative_to=relative_to)
+
+
+relative_fix = wrap if sys.version_info < (3, 12) else lambda x: x
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/py39.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/py39.py
new file mode 100644
index 0000000..1f15bd9
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/compat/py39.py
@@ -0,0 +1,36 @@
+"""
+Compatibility layer with Python 3.8/3.9
+"""
+
+from typing import TYPE_CHECKING, Any, Optional
+
+if TYPE_CHECKING: # pragma: no cover
+ # Prevent circular imports on runtime.
+ from .. import Distribution, EntryPoint
+else:
+ Distribution = EntryPoint = Any
+
+
+def normalized_name(dist: Distribution) -> Optional[str]:
+ """
+ Honor name normalization for distributions that don't provide ``_normalized_name``.
+ """
+ try:
+ return dist._normalized_name
+ except AttributeError:
+ from .. import Prepared # -> delay to prevent circular imports.
+
+ return Prepared.normalize(getattr(dist, "name", None) or dist.metadata['Name'])
+
+
+def ep_matches(ep: EntryPoint, **params) -> bool:
+ """
+ Workaround for ``EntryPoint`` objects without the ``matches`` method.
+ """
+ try:
+ return ep.matches(**params)
+ except AttributeError:
+ from .. import EntryPoint # -> delay to prevent circular imports.
+
+ # Reconstruct the EntryPoint object to make sure it is compatible.
+ return EntryPoint(ep.name, ep.value, ep.group).matches(**params)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/diagnose.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/diagnose.py
new file mode 100644
index 0000000..e405471
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/diagnose.py
@@ -0,0 +1,21 @@
+import sys
+
+from . import Distribution
+
+
+def inspect(path):
+ print("Inspecting", path)
+ dists = list(Distribution.discover(path=[path]))
+ if not dists:
+ return
+ print("Found", len(dists), "packages:", end=' ')
+ print(', '.join(dist.name for dist in dists))
+
+
+def run():
+ for path in sys.path:
+ inspect(path)
+
+
+if __name__ == '__main__':
+ run()
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/py.typed b/testcline/lib/python3.12/site-packages/setuptools/_vendor/importlib_metadata/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/LICENSE
new file mode 100644
index 0000000..1bb5a44
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/LICENSE
@@ -0,0 +1,17 @@
+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/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/METADATA b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/METADATA
new file mode 100644
index 0000000..9a2097a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/METADATA
@@ -0,0 +1,591 @@
+Metadata-Version: 2.1
+Name: inflect
+Version: 7.3.1
+Summary: Correctly generate plurals, singular nouns, ordinals, indefinite articles
+Author-email: Paul Dyson
+Maintainer-email: "Jason R. Coombs"
+Project-URL: Source, https://github.com/jaraco/inflect
+Keywords: plural,inflect,participle
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Text Processing :: Linguistic
+Requires-Python: >=3.8
+Description-Content-Type: text/x-rst
+License-File: LICENSE
+Requires-Dist: more-itertools >=8.5.0
+Requires-Dist: typeguard >=4.0.1
+Requires-Dist: typing-extensions ; python_version < "3.9"
+Provides-Extra: doc
+Requires-Dist: sphinx >=3.5 ; extra == 'doc'
+Requires-Dist: jaraco.packaging >=9.3 ; extra == 'doc'
+Requires-Dist: rst.linker >=1.9 ; extra == 'doc'
+Requires-Dist: furo ; extra == 'doc'
+Requires-Dist: sphinx-lint ; extra == 'doc'
+Requires-Dist: jaraco.tidelift >=1.4 ; extra == 'doc'
+Provides-Extra: test
+Requires-Dist: pytest !=8.1.*,>=6 ; extra == 'test'
+Requires-Dist: pytest-checkdocs >=2.4 ; extra == 'test'
+Requires-Dist: pytest-cov ; extra == 'test'
+Requires-Dist: pytest-mypy ; extra == 'test'
+Requires-Dist: pytest-enabler >=2.2 ; extra == 'test'
+Requires-Dist: pytest-ruff >=0.2.1 ; extra == 'test'
+Requires-Dist: pygments ; extra == 'test'
+
+.. image:: https://img.shields.io/pypi/v/inflect.svg
+ :target: https://pypi.org/project/inflect
+
+.. image:: https://img.shields.io/pypi/pyversions/inflect.svg
+
+.. image:: https://github.com/jaraco/inflect/actions/workflows/main.yml/badge.svg
+ :target: https://github.com/jaraco/inflect/actions?query=workflow%3A%22tests%22
+ :alt: tests
+
+.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+ :target: https://github.com/astral-sh/ruff
+ :alt: Ruff
+
+.. image:: https://readthedocs.org/projects/inflect/badge/?version=latest
+ :target: https://inflect.readthedocs.io/en/latest/?badge=latest
+
+.. image:: https://img.shields.io/badge/skeleton-2024-informational
+ :target: https://blog.jaraco.com/skeleton
+
+.. image:: https://tidelift.com/badges/package/pypi/inflect
+ :target: https://tidelift.com/subscription/pkg/pypi-inflect?utm_source=pypi-inflect&utm_medium=readme
+
+NAME
+====
+
+inflect.py - Correctly generate plurals, singular nouns, ordinals, indefinite articles; convert numbers to words.
+
+SYNOPSIS
+========
+
+.. code-block:: python
+
+ import inflect
+
+ p = inflect.engine()
+
+ # METHODS:
+
+ # plural plural_noun plural_verb plural_adj singular_noun no num
+ # compare compare_nouns compare_nouns compare_adjs
+ # a an
+ # present_participle
+ # ordinal number_to_words
+ # join
+ # inflect classical gender
+ # defnoun defverb defadj defa defan
+
+
+ # UNCONDITIONALLY FORM THE PLURAL
+
+ print("The plural of ", word, " is ", p.plural(word))
+
+
+ # CONDITIONALLY FORM THE PLURAL
+
+ print("I saw", cat_count, p.plural("cat", cat_count))
+
+
+ # FORM PLURALS FOR SPECIFIC PARTS OF SPEECH
+
+ print(
+ p.plural_noun("I", N1),
+ p.plural_verb("saw", N1),
+ p.plural_adj("my", N2),
+ p.plural_noun("saw", N2),
+ )
+
+
+ # FORM THE SINGULAR OF PLURAL NOUNS
+
+ print("The singular of ", word, " is ", p.singular_noun(word))
+
+ # SELECT THE GENDER OF SINGULAR PRONOUNS
+
+ print(p.singular_noun("they")) # 'it'
+ p.gender("feminine")
+ print(p.singular_noun("they")) # 'she'
+
+
+ # DEAL WITH "0/1/N" -> "no/1/N" TRANSLATION:
+
+ print("There ", p.plural_verb("was", errors), p.no(" error", errors))
+
+
+ # USE DEFAULT COUNTS:
+
+ print(
+ p.num(N1, ""),
+ p.plural("I"),
+ p.plural_verb(" saw"),
+ p.num(N2),
+ p.plural_noun(" saw"),
+ )
+ print("There ", p.num(errors, ""), p.plural_verb("was"), p.no(" error"))
+
+
+ # COMPARE TWO WORDS "NUMBER-INSENSITIVELY":
+
+ if p.compare(word1, word2):
+ print("same")
+ if p.compare_nouns(word1, word2):
+ print("same noun")
+ if p.compare_verbs(word1, word2):
+ print("same verb")
+ if p.compare_adjs(word1, word2):
+ print("same adj.")
+
+
+ # ADD CORRECT "a" OR "an" FOR A GIVEN WORD:
+
+ print("Did you want ", p.a(thing), " or ", p.an(idea))
+
+
+ # CONVERT NUMERALS INTO ORDINALS (i.e. 1->1st, 2->2nd, 3->3rd, etc.)
+
+ print("It was", p.ordinal(position), " from the left\n")
+
+ # CONVERT NUMERALS TO WORDS (i.e. 1->"one", 101->"one hundred and one", etc.)
+ # RETURNS A SINGLE STRING...
+
+ words = p.number_to_words(1234)
+ # "one thousand, two hundred and thirty-four"
+ words = p.number_to_words(p.ordinal(1234))
+ # "one thousand, two hundred and thirty-fourth"
+
+
+ # GET BACK A LIST OF STRINGS, ONE FOR EACH "CHUNK"...
+
+ words = p.number_to_words(1234, wantlist=True)
+ # ("one thousand","two hundred and thirty-four")
+
+
+ # OPTIONAL PARAMETERS CHANGE TRANSLATION:
+
+ words = p.number_to_words(12345, group=1)
+ # "one, two, three, four, five"
+
+ words = p.number_to_words(12345, group=2)
+ # "twelve, thirty-four, five"
+
+ words = p.number_to_words(12345, group=3)
+ # "one twenty-three, forty-five"
+
+ words = p.number_to_words(1234, andword="")
+ # "one thousand, two hundred thirty-four"
+
+ words = p.number_to_words(1234, andword=", plus")
+ # "one thousand, two hundred, plus thirty-four"
+ # TODO: I get no comma before plus: check perl
+
+ words = p.number_to_words(555_1202, group=1, zero="oh")
+ # "five, five, five, one, two, oh, two"
+
+ words = p.number_to_words(555_1202, group=1, one="unity")
+ # "five, five, five, unity, two, oh, two"
+
+ words = p.number_to_words(123.456, group=1, decimal="mark")
+ # "one two three mark four five six"
+ # TODO: DOCBUG: perl gives commas here as do I
+
+ # LITERAL STYLE ONLY NAMES NUMBERS LESS THAN A CERTAIN THRESHOLD...
+
+ words = p.number_to_words(9, threshold=10) # "nine"
+ words = p.number_to_words(10, threshold=10) # "ten"
+ words = p.number_to_words(11, threshold=10) # "11"
+ words = p.number_to_words(1000, threshold=10) # "1,000"
+
+ # JOIN WORDS INTO A LIST:
+
+ mylist = p.join(("apple", "banana", "carrot"))
+ # "apple, banana, and carrot"
+
+ mylist = p.join(("apple", "banana"))
+ # "apple and banana"
+
+ mylist = p.join(("apple", "banana", "carrot"), final_sep="")
+ # "apple, banana and carrot"
+
+
+ # REQUIRE "CLASSICAL" PLURALS (EG: "focus"->"foci", "cherub"->"cherubim")
+
+ p.classical() # USE ALL CLASSICAL PLURALS
+
+ p.classical(all=True) # USE ALL CLASSICAL PLURALS
+ p.classical(all=False) # SWITCH OFF CLASSICAL MODE
+
+ p.classical(zero=True) # "no error" INSTEAD OF "no errors"
+ p.classical(zero=False) # "no errors" INSTEAD OF "no error"
+
+ p.classical(herd=True) # "2 buffalo" INSTEAD OF "2 buffalos"
+ p.classical(herd=False) # "2 buffalos" INSTEAD OF "2 buffalo"
+
+ p.classical(persons=True) # "2 chairpersons" INSTEAD OF "2 chairpeople"
+ p.classical(persons=False) # "2 chairpeople" INSTEAD OF "2 chairpersons"
+
+ p.classical(ancient=True) # "2 formulae" INSTEAD OF "2 formulas"
+ p.classical(ancient=False) # "2 formulas" INSTEAD OF "2 formulae"
+
+
+ # INTERPOLATE "plural()", "plural_noun()", "plural_verb()", "plural_adj()", "singular_noun()",
+ # a()", "an()", "num()" AND "ordinal()" WITHIN STRINGS:
+
+ print(p.inflect("The plural of {0} is plural('{0}')".format(word)))
+ print(p.inflect("The singular of {0} is singular_noun('{0}')".format(word)))
+ print(p.inflect("I saw {0} plural('cat',{0})".format(cat_count)))
+ print(
+ p.inflect(
+ "plural('I',{0}) "
+ "plural_verb('saw',{0}) "
+ "plural('a',{1}) "
+ "plural_noun('saw',{1})".format(N1, N2)
+ )
+ )
+ print(
+ p.inflect(
+ "num({0}, False)plural('I') "
+ "plural_verb('saw') "
+ "num({1}, False)plural('a') "
+ "plural_noun('saw')".format(N1, N2)
+ )
+ )
+ print(p.inflect("I saw num({0}) plural('cat')\nnum()".format(cat_count)))
+ print(p.inflect("There plural_verb('was',{0}) no('error',{0})".format(errors)))
+ print(p.inflect("There num({0}, False)plural_verb('was') no('error')".format(errors)))
+ print(p.inflect("Did you want a('{0}') or an('{1}')".format(thing, idea)))
+ print(p.inflect("It was ordinal('{0}') from the left".format(position)))
+
+
+ # ADD USER-DEFINED INFLECTIONS (OVERRIDING INBUILT RULES):
+
+ p.defnoun("VAX", "VAXen") # SINGULAR => PLURAL
+
+ p.defverb(
+ "will", # 1ST PERSON SINGULAR
+ "shall", # 1ST PERSON PLURAL
+ "will", # 2ND PERSON SINGULAR
+ "will", # 2ND PERSON PLURAL
+ "will", # 3RD PERSON SINGULAR
+ "will", # 3RD PERSON PLURAL
+ )
+
+ p.defadj("hir", "their") # SINGULAR => PLURAL
+
+ p.defa("h") # "AY HALWAYS SEZ 'HAITCH'!"
+
+ p.defan("horrendous.*") # "AN HORRENDOUS AFFECTATION"
+
+
+DESCRIPTION
+===========
+
+The methods of the class ``engine`` in module ``inflect.py`` provide plural
+inflections, singular noun inflections, "a"/"an" selection for English words,
+and manipulation of numbers as words.
+
+Plural forms of all nouns, most verbs, and some adjectives are
+provided. Where appropriate, "classical" variants (for example: "brother" ->
+"brethren", "dogma" -> "dogmata", etc.) are also provided.
+
+Single forms of nouns are also provided. The gender of singular pronouns
+can be chosen (for example "they" -> "it" or "she" or "he" or "they").
+
+Pronunciation-based "a"/"an" selection is provided for all English
+words, and most initialisms.
+
+It is also possible to inflect numerals (1,2,3) to ordinals (1st, 2nd, 3rd)
+and to English words ("one", "two", "three").
+
+In generating these inflections, ``inflect.py`` follows the Oxford
+English Dictionary and the guidelines in Fowler's Modern English
+Usage, preferring the former where the two disagree.
+
+The module is built around standard British spelling, but is designed
+to cope with common American variants as well. Slang, jargon, and
+other English dialects are *not* explicitly catered for.
+
+Where two or more inflected forms exist for a single word (typically a
+"classical" form and a "modern" form), ``inflect.py`` prefers the
+more common form (typically the "modern" one), unless "classical"
+processing has been specified
+(see `MODERN VS CLASSICAL INFLECTIONS`).
+
+FORMING PLURALS AND SINGULARS
+=============================
+
+Inflecting Plurals and Singulars
+--------------------------------
+
+All of the ``plural...`` plural inflection methods take the word to be
+inflected as their first argument and return the corresponding inflection.
+Note that all such methods expect the *singular* form of the word. The
+results of passing a plural form are undefined (and unlikely to be correct).
+Similarly, the ``si...`` singular inflection method expects the *plural*
+form of the word.
+
+The ``plural...`` methods also take an optional second argument,
+which indicates the grammatical "number" of the word (or of another word
+with which the word being inflected must agree). If the "number" argument is
+supplied and is not ``1`` (or ``"one"`` or ``"a"``, or some other adjective that
+implies the singular), the plural form of the word is returned. If the
+"number" argument *does* indicate singularity, the (uninflected) word
+itself is returned. If the number argument is omitted, the plural form
+is returned unconditionally.
+
+The ``si...`` method takes a second argument in a similar fashion. If it is
+some form of the number ``1``, or is omitted, the singular form is returned.
+Otherwise the plural is returned unaltered.
+
+
+The various methods of ``inflect.engine`` are:
+
+
+
+``plural_noun(word, count=None)``
+
+ The method ``plural_noun()`` takes a *singular* English noun or
+ pronoun and returns its plural. Pronouns in the nominative ("I" ->
+ "we") and accusative ("me" -> "us") cases are handled, as are
+ possessive pronouns ("mine" -> "ours").
+
+
+``plural_verb(word, count=None)``
+
+ The method ``plural_verb()`` takes the *singular* form of a
+ conjugated verb (that is, one which is already in the correct "person"
+ and "mood") and returns the corresponding plural conjugation.
+
+
+``plural_adj(word, count=None)``
+
+ The method ``plural_adj()`` takes the *singular* form of
+ certain types of adjectives and returns the corresponding plural form.
+ Adjectives that are correctly handled include: "numerical" adjectives
+ ("a" -> "some"), demonstrative adjectives ("this" -> "these", "that" ->
+ "those"), and possessives ("my" -> "our", "cat's" -> "cats'", "child's"
+ -> "childrens'", etc.)
+
+
+``plural(word, count=None)``
+
+ The method ``plural()`` takes a *singular* English noun,
+ pronoun, verb, or adjective and returns its plural form. Where a word
+ has more than one inflection depending on its part of speech (for
+ example, the noun "thought" inflects to "thoughts", the verb "thought"
+ to "thought"), the (singular) noun sense is preferred to the (singular)
+ verb sense.
+
+ Hence ``plural("knife")`` will return "knives" ("knife" having been treated
+ as a singular noun), whereas ``plural("knifes")`` will return "knife"
+ ("knifes" having been treated as a 3rd person singular verb).
+
+ The inherent ambiguity of such cases suggests that,
+ where the part of speech is known, ``plural_noun``, ``plural_verb``, and
+ ``plural_adj`` should be used in preference to ``plural``.
+
+
+``singular_noun(word, count=None)``
+
+ The method ``singular_noun()`` takes a *plural* English noun or
+ pronoun and returns its singular. Pronouns in the nominative ("we" ->
+ "I") and accusative ("us" -> "me") cases are handled, as are
+ possessive pronouns ("ours" -> "mine"). When third person
+ singular pronouns are returned they take the neuter gender by default
+ ("they" -> "it"), not ("they"-> "she") nor ("they" -> "he"). This can be
+ changed with ``gender()``.
+
+Note that all these methods ignore any whitespace surrounding the
+word being inflected, but preserve that whitespace when the result is
+returned. For example, ``plural(" cat ")`` returns " cats ".
+
+
+``gender(genderletter)``
+
+ The third person plural pronoun takes the same form for the female, male and
+ neuter (e.g. "they"). The singular however, depends upon gender (e.g. "she",
+ "he", "it" and "they" -- "they" being the gender neutral form.) By default
+ ``singular_noun`` returns the neuter form, however, the gender can be selected with
+ the ``gender`` method. Pass the first letter of the gender to
+ ``gender`` to return the f(eminine), m(asculine), n(euter) or t(hey)
+ form of the singular. e.g.
+ gender('f') followed by singular_noun('themselves') returns 'herself'.
+
+Numbered plurals
+----------------
+
+The ``plural...`` methods return only the inflected word, not the count that
+was used to inflect it. Thus, in order to produce "I saw 3 ducks", it
+is necessary to use:
+
+.. code-block:: python
+
+ print("I saw", N, p.plural_noun(animal, N))
+
+Since the usual purpose of producing a plural is to make it agree with
+a preceding count, inflect.py provides a method
+(``no(word, count)``) which, given a word and a(n optional) count, returns the
+count followed by the correctly inflected word. Hence the previous
+example can be rewritten:
+
+.. code-block:: python
+
+ print("I saw ", p.no(animal, N))
+
+In addition, if the count is zero (or some other term which implies
+zero, such as ``"zero"``, ``"nil"``, etc.) the count is replaced by the
+word "no". Hence, if ``N`` had the value zero, the previous example
+would print (the somewhat more elegant)::
+
+ I saw no animals
+
+rather than::
+
+ I saw 0 animals
+
+Note that the name of the method is a pun: the method
+returns either a number (a *No.*) or a ``"no"``, in front of the
+inflected word.
+
+
+Reducing the number of counts required
+--------------------------------------
+
+In some contexts, the need to supply an explicit count to the various
+``plural...`` methods makes for tiresome repetition. For example:
+
+.. code-block:: python
+
+ print(
+ plural_adj("This", errors),
+ plural_noun(" error", errors),
+ plural_verb(" was", errors),
+ " fatal.",
+ )
+
+inflect.py therefore provides a method
+(``num(count=None, show=None)``) which may be used to set a persistent "default number"
+value. If such a value is set, it is subsequently used whenever an
+optional second "number" argument is omitted. The default value thus set
+can subsequently be removed by calling ``num()`` with no arguments.
+Hence we could rewrite the previous example:
+
+.. code-block:: python
+
+ p.num(errors)
+ print(p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal.")
+ p.num()
+
+Normally, ``num()`` returns its first argument, so that it may also
+be "inlined" in contexts like:
+
+.. code-block:: python
+
+ print(p.num(errors), p.plural_noun(" error"), p.plural_verb(" was"), " detected.")
+ if severity > 1:
+ print(
+ p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal."
+ )
+
+However, in certain contexts (see `INTERPOLATING INFLECTIONS IN STRINGS`)
+it is preferable that ``num()`` return an empty string. Hence ``num()``
+provides an optional second argument. If that argument is supplied (that is, if
+it is defined) and evaluates to false, ``num`` returns an empty string
+instead of its first argument. For example:
+
+.. code-block:: python
+
+ print(p.num(errors, 0), p.no("error"), p.plural_verb(" was"), " detected.")
+ if severity > 1:
+ print(
+ p.plural_adj("This"), p.plural_noun(" error"), p.plural_verb(" was"), "fatal."
+ )
+
+
+
+Number-insensitive equality
+---------------------------
+
+inflect.py also provides a solution to the problem
+of comparing words of differing plurality through the methods
+``compare(word1, word2)``, ``compare_nouns(word1, word2)``,
+``compare_verbs(word1, word2)``, and ``compare_adjs(word1, word2)``.
+Each of these methods takes two strings, and compares them
+using the corresponding plural-inflection method (``plural()``, ``plural_noun()``,
+``plural_verb()``, and ``plural_adj()`` respectively).
+
+The comparison returns true if:
+
+- the strings are equal, or
+- one string is equal to a plural form of the other, or
+- the strings are two different plural forms of the one word.
+
+
+Hence all of the following return true:
+
+.. code-block:: python
+
+ p.compare("index", "index") # RETURNS "eq"
+ p.compare("index", "indexes") # RETURNS "s:p"
+ p.compare("index", "indices") # RETURNS "s:p"
+ p.compare("indexes", "index") # RETURNS "p:s"
+ p.compare("indices", "index") # RETURNS "p:s"
+ p.compare("indices", "indexes") # RETURNS "p:p"
+ p.compare("indexes", "indices") # RETURNS "p:p"
+ p.compare("indices", "indices") # RETURNS "eq"
+
+As indicated by the comments in the previous example, the actual value
+returned by the various ``compare`` methods encodes which of the
+three equality rules succeeded: "eq" is returned if the strings were
+identical, "s:p" if the strings were singular and plural respectively,
+"p:s" for plural and singular, and "p:p" for two distinct plurals.
+Inequality is indicated by returning an empty string.
+
+It should be noted that two distinct singular words which happen to take
+the same plural form are *not* considered equal, nor are cases where
+one (singular) word's plural is the other (plural) word's singular.
+Hence all of the following return false:
+
+.. code-block:: python
+
+ p.compare("base", "basis") # ALTHOUGH BOTH -> "bases"
+ p.compare("syrinx", "syringe") # ALTHOUGH BOTH -> "syringes"
+ p.compare("she", "he") # ALTHOUGH BOTH -> "they"
+
+ p.compare("opus", "operas") # ALTHOUGH "opus" -> "opera" -> "operas"
+ p.compare("taxi", "taxes") # ALTHOUGH "taxi" -> "taxis" -> "taxes"
+
+Note too that, although the comparison is "number-insensitive" it is *not*
+case-insensitive (that is, ``plural("time","Times")`` returns false. To obtain
+both number and case insensitivity, use the ``lower()`` method on both strings
+(that is, ``plural("time".lower(), "Times".lower())`` returns true).
+
+Related Functionality
+=====================
+
+Shout out to these libraries that provide related functionality:
+
+* `WordSet `_
+ parses identifiers like variable names into sets of words suitable for re-assembling
+ in another form.
+
+* `word2number `_ converts words to
+ a number.
+
+
+For Enterprise
+==============
+
+Available as part of the Tidelift Subscription.
+
+This project 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 `_.
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/RECORD b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/RECORD
new file mode 100644
index 0000000..73ff576
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/RECORD
@@ -0,0 +1,13 @@
+inflect-7.3.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+inflect-7.3.1.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+inflect-7.3.1.dist-info/METADATA,sha256=ZgMNY0WAZRs-U8wZiV2SMfjSKqBrMngXyDMs_CAwMwg,21079
+inflect-7.3.1.dist-info/RECORD,,
+inflect-7.3.1.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
+inflect-7.3.1.dist-info/top_level.txt,sha256=m52ujdp10CqT6jh1XQxZT6kEntcnv-7Tl7UiGNTzWZA,8
+inflect/__init__.py,sha256=Jxy1HJXZiZ85kHeLAhkmvz6EMTdFqBe-duvt34R6IOc,103796
+inflect/__pycache__/__init__.cpython-312.pyc,,
+inflect/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+inflect/compat/__pycache__/__init__.cpython-312.pyc,,
+inflect/compat/__pycache__/py38.cpython-312.pyc,,
+inflect/compat/py38.py,sha256=oObVfVnWX9_OpnOuEJn1mFbJxVhwyR5epbiTNXDDaso,160
+inflect/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/WHEEL
new file mode 100644
index 0000000..564c672
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: setuptools (70.2.0)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/top_level.txt
new file mode 100644
index 0000000..0fd75fa
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect-7.3.1.dist-info/top_level.txt
@@ -0,0 +1 @@
+inflect
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/__init__.py
new file mode 100644
index 0000000..3eec27f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/__init__.py
@@ -0,0 +1,3986 @@
+"""
+inflect: english language inflection
+ - correctly generate plurals, ordinals, indefinite articles
+ - convert numbers to words
+
+Copyright (C) 2010 Paul Dyson
+
+Based upon the Perl module
+`Lingua::EN::Inflect `_.
+
+methods:
+ classical inflect
+ plural plural_noun plural_verb plural_adj singular_noun no num a an
+ compare compare_nouns compare_verbs compare_adjs
+ present_participle
+ ordinal
+ number_to_words
+ join
+ defnoun defverb defadj defa defan
+
+INFLECTIONS:
+ classical inflect
+ plural plural_noun plural_verb plural_adj singular_noun compare
+ no num a an present_participle
+
+PLURALS:
+ classical inflect
+ plural plural_noun plural_verb plural_adj singular_noun no num
+ compare compare_nouns compare_verbs compare_adjs
+
+COMPARISONS:
+ classical
+ compare compare_nouns compare_verbs compare_adjs
+
+ARTICLES:
+ classical inflect num a an
+
+NUMERICAL:
+ ordinal number_to_words
+
+USER_DEFINED:
+ defnoun defverb defadj defa defan
+
+Exceptions:
+ UnknownClassicalModeError
+ BadNumValueError
+ BadChunkingOptionError
+ NumOutOfRangeError
+ BadUserDefinedPatternError
+ BadRcFileError
+ BadGenderError
+
+"""
+
+from __future__ import annotations
+
+import ast
+import collections
+import contextlib
+import functools
+import itertools
+import re
+from numbers import Number
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ Callable,
+ Dict,
+ Iterable,
+ List,
+ Literal,
+ Match,
+ Optional,
+ Sequence,
+ Tuple,
+ Union,
+ cast,
+)
+
+from more_itertools import windowed_complete
+from typeguard import typechecked
+
+from .compat.py38 import Annotated
+
+
+class UnknownClassicalModeError(Exception):
+ pass
+
+
+class BadNumValueError(Exception):
+ pass
+
+
+class BadChunkingOptionError(Exception):
+ pass
+
+
+class NumOutOfRangeError(Exception):
+ pass
+
+
+class BadUserDefinedPatternError(Exception):
+ pass
+
+
+class BadRcFileError(Exception):
+ pass
+
+
+class BadGenderError(Exception):
+ pass
+
+
+def enclose(s: str) -> str:
+ return f"(?:{s})"
+
+
+def joinstem(cutpoint: Optional[int] = 0, words: Optional[Iterable[str]] = None) -> str:
+ """
+ Join stem of each word in words into a string for regex.
+
+ Each word is truncated at cutpoint.
+
+ Cutpoint is usually negative indicating the number of letters to remove
+ from the end of each word.
+
+ >>> joinstem(-2, ["ephemeris", "iris", ".*itis"])
+ '(?:ephemer|ir|.*it)'
+
+ >>> joinstem(None, ["ephemeris"])
+ '(?:ephemeris)'
+
+ >>> joinstem(5, None)
+ '(?:)'
+ """
+ return enclose("|".join(w[:cutpoint] for w in words or []))
+
+
+def bysize(words: Iterable[str]) -> Dict[int, set]:
+ """
+ From a list of words, return a dict of sets sorted by word length.
+
+ >>> words = ['ant', 'cat', 'dog', 'pig', 'frog', 'goat', 'horse', 'elephant']
+ >>> ret = bysize(words)
+ >>> sorted(ret[3])
+ ['ant', 'cat', 'dog', 'pig']
+ >>> ret[5]
+ {'horse'}
+ """
+ res: Dict[int, set] = collections.defaultdict(set)
+ for w in words:
+ res[len(w)].add(w)
+ return res
+
+
+def make_pl_si_lists(
+ lst: Iterable[str],
+ plending: str,
+ siendingsize: Optional[int],
+ dojoinstem: bool = True,
+):
+ """
+ given a list of singular words: lst
+
+ an ending to append to make the plural: plending
+
+ the number of characters to remove from the singular
+ before appending plending: siendingsize
+
+ a flag whether to create a joinstem: dojoinstem
+
+ return:
+ a list of pluralised words: si_list (called si because this is what you need to
+ look for to make the singular)
+
+ the pluralised words as a dict of sets sorted by word length: si_bysize
+ the singular words as a dict of sets sorted by word length: pl_bysize
+ if dojoinstem is True: a regular expression that matches any of the stems: stem
+ """
+ if siendingsize is not None:
+ siendingsize = -siendingsize
+ si_list = [w[:siendingsize] + plending for w in lst]
+ pl_bysize = bysize(lst)
+ si_bysize = bysize(si_list)
+ if dojoinstem:
+ stem = joinstem(siendingsize, lst)
+ return si_list, si_bysize, pl_bysize, stem
+ else:
+ return si_list, si_bysize, pl_bysize
+
+
+# 1. PLURALS
+
+pl_sb_irregular_s = {
+ "corpus": "corpuses|corpora",
+ "opus": "opuses|opera",
+ "genus": "genera",
+ "mythos": "mythoi",
+ "penis": "penises|penes",
+ "testis": "testes",
+ "atlas": "atlases|atlantes",
+ "yes": "yeses",
+}
+
+pl_sb_irregular = {
+ "child": "children",
+ "chili": "chilis|chilies",
+ "brother": "brothers|brethren",
+ "infinity": "infinities|infinity",
+ "loaf": "loaves",
+ "lore": "lores|lore",
+ "hoof": "hoofs|hooves",
+ "beef": "beefs|beeves",
+ "thief": "thiefs|thieves",
+ "money": "monies",
+ "mongoose": "mongooses",
+ "ox": "oxen",
+ "cow": "cows|kine",
+ "graffito": "graffiti",
+ "octopus": "octopuses|octopodes",
+ "genie": "genies|genii",
+ "ganglion": "ganglions|ganglia",
+ "trilby": "trilbys",
+ "turf": "turfs|turves",
+ "numen": "numina",
+ "atman": "atmas",
+ "occiput": "occiputs|occipita",
+ "sabretooth": "sabretooths",
+ "sabertooth": "sabertooths",
+ "lowlife": "lowlifes",
+ "flatfoot": "flatfoots",
+ "tenderfoot": "tenderfoots",
+ "romany": "romanies",
+ "jerry": "jerries",
+ "mary": "maries",
+ "talouse": "talouses",
+ "rom": "roma",
+ "carmen": "carmina",
+}
+
+pl_sb_irregular.update(pl_sb_irregular_s)
+# pl_sb_irregular_keys = enclose('|'.join(pl_sb_irregular.keys()))
+
+pl_sb_irregular_caps = {
+ "Romany": "Romanies",
+ "Jerry": "Jerrys",
+ "Mary": "Marys",
+ "Rom": "Roma",
+}
+
+pl_sb_irregular_compound = {"prima donna": "prima donnas|prime donne"}
+
+si_sb_irregular = {v: k for (k, v) in pl_sb_irregular.items()}
+for k in list(si_sb_irregular):
+ if "|" in k:
+ k1, k2 = k.split("|")
+ si_sb_irregular[k1] = si_sb_irregular[k2] = si_sb_irregular[k]
+ del si_sb_irregular[k]
+si_sb_irregular_caps = {v: k for (k, v) in pl_sb_irregular_caps.items()}
+si_sb_irregular_compound = {v: k for (k, v) in pl_sb_irregular_compound.items()}
+for k in list(si_sb_irregular_compound):
+ if "|" in k:
+ k1, k2 = k.split("|")
+ si_sb_irregular_compound[k1] = si_sb_irregular_compound[k2] = (
+ si_sb_irregular_compound[k]
+ )
+ del si_sb_irregular_compound[k]
+
+# si_sb_irregular_keys = enclose('|'.join(si_sb_irregular.keys()))
+
+# Z's that don't double
+
+pl_sb_z_zes_list = ("quartz", "topaz")
+pl_sb_z_zes_bysize = bysize(pl_sb_z_zes_list)
+
+pl_sb_ze_zes_list = ("snooze",)
+pl_sb_ze_zes_bysize = bysize(pl_sb_ze_zes_list)
+
+
+# CLASSICAL "..is" -> "..ides"
+
+pl_sb_C_is_ides_complete = [
+ # GENERAL WORDS...
+ "ephemeris",
+ "iris",
+ "clitoris",
+ "chrysalis",
+ "epididymis",
+]
+
+pl_sb_C_is_ides_endings = [
+ # INFLAMATIONS...
+ "itis"
+]
+
+pl_sb_C_is_ides = joinstem(
+ -2, pl_sb_C_is_ides_complete + [f".*{w}" for w in pl_sb_C_is_ides_endings]
+)
+
+pl_sb_C_is_ides_list = pl_sb_C_is_ides_complete + pl_sb_C_is_ides_endings
+
+(
+ si_sb_C_is_ides_list,
+ si_sb_C_is_ides_bysize,
+ pl_sb_C_is_ides_bysize,
+) = make_pl_si_lists(pl_sb_C_is_ides_list, "ides", 2, dojoinstem=False)
+
+
+# CLASSICAL "..a" -> "..ata"
+
+pl_sb_C_a_ata_list = (
+ "anathema",
+ "bema",
+ "carcinoma",
+ "charisma",
+ "diploma",
+ "dogma",
+ "drama",
+ "edema",
+ "enema",
+ "enigma",
+ "lemma",
+ "lymphoma",
+ "magma",
+ "melisma",
+ "miasma",
+ "oedema",
+ "sarcoma",
+ "schema",
+ "soma",
+ "stigma",
+ "stoma",
+ "trauma",
+ "gumma",
+ "pragma",
+)
+
+(
+ si_sb_C_a_ata_list,
+ si_sb_C_a_ata_bysize,
+ pl_sb_C_a_ata_bysize,
+ pl_sb_C_a_ata,
+) = make_pl_si_lists(pl_sb_C_a_ata_list, "ata", 1)
+
+# UNCONDITIONAL "..a" -> "..ae"
+
+pl_sb_U_a_ae_list = (
+ "alumna",
+ "alga",
+ "vertebra",
+ "persona",
+ "vita",
+)
+(
+ si_sb_U_a_ae_list,
+ si_sb_U_a_ae_bysize,
+ pl_sb_U_a_ae_bysize,
+ pl_sb_U_a_ae,
+) = make_pl_si_lists(pl_sb_U_a_ae_list, "e", None)
+
+# CLASSICAL "..a" -> "..ae"
+
+pl_sb_C_a_ae_list = (
+ "amoeba",
+ "antenna",
+ "formula",
+ "hyperbola",
+ "medusa",
+ "nebula",
+ "parabola",
+ "abscissa",
+ "hydra",
+ "nova",
+ "lacuna",
+ "aurora",
+ "umbra",
+ "flora",
+ "fauna",
+)
+(
+ si_sb_C_a_ae_list,
+ si_sb_C_a_ae_bysize,
+ pl_sb_C_a_ae_bysize,
+ pl_sb_C_a_ae,
+) = make_pl_si_lists(pl_sb_C_a_ae_list, "e", None)
+
+
+# CLASSICAL "..en" -> "..ina"
+
+pl_sb_C_en_ina_list = ("stamen", "foramen", "lumen")
+
+(
+ si_sb_C_en_ina_list,
+ si_sb_C_en_ina_bysize,
+ pl_sb_C_en_ina_bysize,
+ pl_sb_C_en_ina,
+) = make_pl_si_lists(pl_sb_C_en_ina_list, "ina", 2)
+
+
+# UNCONDITIONAL "..um" -> "..a"
+
+pl_sb_U_um_a_list = (
+ "bacterium",
+ "agendum",
+ "desideratum",
+ "erratum",
+ "stratum",
+ "datum",
+ "ovum",
+ "extremum",
+ "candelabrum",
+)
+(
+ si_sb_U_um_a_list,
+ si_sb_U_um_a_bysize,
+ pl_sb_U_um_a_bysize,
+ pl_sb_U_um_a,
+) = make_pl_si_lists(pl_sb_U_um_a_list, "a", 2)
+
+# CLASSICAL "..um" -> "..a"
+
+pl_sb_C_um_a_list = (
+ "maximum",
+ "minimum",
+ "momentum",
+ "optimum",
+ "quantum",
+ "cranium",
+ "curriculum",
+ "dictum",
+ "phylum",
+ "aquarium",
+ "compendium",
+ "emporium",
+ "encomium",
+ "gymnasium",
+ "honorarium",
+ "interregnum",
+ "lustrum",
+ "memorandum",
+ "millennium",
+ "rostrum",
+ "spectrum",
+ "speculum",
+ "stadium",
+ "trapezium",
+ "ultimatum",
+ "medium",
+ "vacuum",
+ "velum",
+ "consortium",
+ "arboretum",
+)
+
+(
+ si_sb_C_um_a_list,
+ si_sb_C_um_a_bysize,
+ pl_sb_C_um_a_bysize,
+ pl_sb_C_um_a,
+) = make_pl_si_lists(pl_sb_C_um_a_list, "a", 2)
+
+
+# UNCONDITIONAL "..us" -> "i"
+
+pl_sb_U_us_i_list = (
+ "alumnus",
+ "alveolus",
+ "bacillus",
+ "bronchus",
+ "locus",
+ "nucleus",
+ "stimulus",
+ "meniscus",
+ "sarcophagus",
+)
+(
+ si_sb_U_us_i_list,
+ si_sb_U_us_i_bysize,
+ pl_sb_U_us_i_bysize,
+ pl_sb_U_us_i,
+) = make_pl_si_lists(pl_sb_U_us_i_list, "i", 2)
+
+# CLASSICAL "..us" -> "..i"
+
+pl_sb_C_us_i_list = (
+ "focus",
+ "radius",
+ "genius",
+ "incubus",
+ "succubus",
+ "nimbus",
+ "fungus",
+ "nucleolus",
+ "stylus",
+ "torus",
+ "umbilicus",
+ "uterus",
+ "hippopotamus",
+ "cactus",
+)
+
+(
+ si_sb_C_us_i_list,
+ si_sb_C_us_i_bysize,
+ pl_sb_C_us_i_bysize,
+ pl_sb_C_us_i,
+) = make_pl_si_lists(pl_sb_C_us_i_list, "i", 2)
+
+
+# CLASSICAL "..us" -> "..us" (ASSIMILATED 4TH DECLENSION LATIN NOUNS)
+
+pl_sb_C_us_us = (
+ "status",
+ "apparatus",
+ "prospectus",
+ "sinus",
+ "hiatus",
+ "impetus",
+ "plexus",
+)
+pl_sb_C_us_us_bysize = bysize(pl_sb_C_us_us)
+
+# UNCONDITIONAL "..on" -> "a"
+
+pl_sb_U_on_a_list = (
+ "criterion",
+ "perihelion",
+ "aphelion",
+ "phenomenon",
+ "prolegomenon",
+ "noumenon",
+ "organon",
+ "asyndeton",
+ "hyperbaton",
+)
+(
+ si_sb_U_on_a_list,
+ si_sb_U_on_a_bysize,
+ pl_sb_U_on_a_bysize,
+ pl_sb_U_on_a,
+) = make_pl_si_lists(pl_sb_U_on_a_list, "a", 2)
+
+# CLASSICAL "..on" -> "..a"
+
+pl_sb_C_on_a_list = ("oxymoron",)
+
+(
+ si_sb_C_on_a_list,
+ si_sb_C_on_a_bysize,
+ pl_sb_C_on_a_bysize,
+ pl_sb_C_on_a,
+) = make_pl_si_lists(pl_sb_C_on_a_list, "a", 2)
+
+
+# CLASSICAL "..o" -> "..i" (BUT NORMALLY -> "..os")
+
+pl_sb_C_o_i = [
+ "solo",
+ "soprano",
+ "basso",
+ "alto",
+ "contralto",
+ "tempo",
+ "piano",
+ "virtuoso",
+] # list not tuple so can concat for pl_sb_U_o_os
+
+pl_sb_C_o_i_bysize = bysize(pl_sb_C_o_i)
+si_sb_C_o_i_bysize = bysize([f"{w[:-1]}i" for w in pl_sb_C_o_i])
+
+pl_sb_C_o_i_stems = joinstem(-1, pl_sb_C_o_i)
+
+# ALWAYS "..o" -> "..os"
+
+pl_sb_U_o_os_complete = {"ado", "ISO", "NATO", "NCO", "NGO", "oto"}
+si_sb_U_o_os_complete = {f"{w}s" for w in pl_sb_U_o_os_complete}
+
+
+pl_sb_U_o_os_endings = [
+ "aficionado",
+ "aggro",
+ "albino",
+ "allegro",
+ "ammo",
+ "Antananarivo",
+ "archipelago",
+ "armadillo",
+ "auto",
+ "avocado",
+ "Bamako",
+ "Barquisimeto",
+ "bimbo",
+ "bingo",
+ "Biro",
+ "bolero",
+ "Bolzano",
+ "bongo",
+ "Boto",
+ "burro",
+ "Cairo",
+ "canto",
+ "cappuccino",
+ "casino",
+ "cello",
+ "Chicago",
+ "Chimango",
+ "cilantro",
+ "cochito",
+ "coco",
+ "Colombo",
+ "Colorado",
+ "commando",
+ "concertino",
+ "contango",
+ "credo",
+ "crescendo",
+ "cyano",
+ "demo",
+ "ditto",
+ "Draco",
+ "dynamo",
+ "embryo",
+ "Esperanto",
+ "espresso",
+ "euro",
+ "falsetto",
+ "Faro",
+ "fiasco",
+ "Filipino",
+ "flamenco",
+ "furioso",
+ "generalissimo",
+ "Gestapo",
+ "ghetto",
+ "gigolo",
+ "gizmo",
+ "Greensboro",
+ "gringo",
+ "Guaiabero",
+ "guano",
+ "gumbo",
+ "gyro",
+ "hairdo",
+ "hippo",
+ "Idaho",
+ "impetigo",
+ "inferno",
+ "info",
+ "intermezzo",
+ "intertrigo",
+ "Iquico",
+ "jumbo",
+ "junto",
+ "Kakapo",
+ "kilo",
+ "Kinkimavo",
+ "Kokako",
+ "Kosovo",
+ "Lesotho",
+ "libero",
+ "libido",
+ "libretto",
+ "lido",
+ "Lilo",
+ "limbo",
+ "limo",
+ "lineno",
+ "lingo",
+ "lino",
+ "livedo",
+ "loco",
+ "logo",
+ "lumbago",
+ "macho",
+ "macro",
+ "mafioso",
+ "magneto",
+ "magnifico",
+ "Majuro",
+ "Malabo",
+ "manifesto",
+ "Maputo",
+ "Maracaibo",
+ "medico",
+ "memo",
+ "metro",
+ "Mexico",
+ "micro",
+ "Milano",
+ "Monaco",
+ "mono",
+ "Montenegro",
+ "Morocco",
+ "Muqdisho",
+ "myo",
+ "neutrino",
+ "Ningbo",
+ "octavo",
+ "oregano",
+ "Orinoco",
+ "Orlando",
+ "Oslo",
+ "panto",
+ "Paramaribo",
+ "Pardusco",
+ "pedalo",
+ "photo",
+ "pimento",
+ "pinto",
+ "pleco",
+ "Pluto",
+ "pogo",
+ "polo",
+ "poncho",
+ "Porto-Novo",
+ "Porto",
+ "pro",
+ "psycho",
+ "pueblo",
+ "quarto",
+ "Quito",
+ "repo",
+ "rhino",
+ "risotto",
+ "rococo",
+ "rondo",
+ "Sacramento",
+ "saddo",
+ "sago",
+ "salvo",
+ "Santiago",
+ "Sapporo",
+ "Sarajevo",
+ "scherzando",
+ "scherzo",
+ "silo",
+ "sirocco",
+ "sombrero",
+ "staccato",
+ "sterno",
+ "stucco",
+ "stylo",
+ "sumo",
+ "Taiko",
+ "techno",
+ "terrazzo",
+ "testudo",
+ "timpano",
+ "tiro",
+ "tobacco",
+ "Togo",
+ "Tokyo",
+ "torero",
+ "Torino",
+ "Toronto",
+ "torso",
+ "tremolo",
+ "typo",
+ "tyro",
+ "ufo",
+ "UNESCO",
+ "vaquero",
+ "vermicello",
+ "verso",
+ "vibrato",
+ "violoncello",
+ "Virgo",
+ "weirdo",
+ "WHO",
+ "WTO",
+ "Yamoussoukro",
+ "yo-yo",
+ "zero",
+ "Zibo",
+] + pl_sb_C_o_i
+
+pl_sb_U_o_os_bysize = bysize(pl_sb_U_o_os_endings)
+si_sb_U_o_os_bysize = bysize([f"{w}s" for w in pl_sb_U_o_os_endings])
+
+
+# UNCONDITIONAL "..ch" -> "..chs"
+
+pl_sb_U_ch_chs_list = ("czech", "eunuch", "stomach")
+
+(
+ si_sb_U_ch_chs_list,
+ si_sb_U_ch_chs_bysize,
+ pl_sb_U_ch_chs_bysize,
+ pl_sb_U_ch_chs,
+) = make_pl_si_lists(pl_sb_U_ch_chs_list, "s", None)
+
+
+# UNCONDITIONAL "..[ei]x" -> "..ices"
+
+pl_sb_U_ex_ices_list = ("codex", "murex", "silex")
+(
+ si_sb_U_ex_ices_list,
+ si_sb_U_ex_ices_bysize,
+ pl_sb_U_ex_ices_bysize,
+ pl_sb_U_ex_ices,
+) = make_pl_si_lists(pl_sb_U_ex_ices_list, "ices", 2)
+
+pl_sb_U_ix_ices_list = ("radix", "helix")
+(
+ si_sb_U_ix_ices_list,
+ si_sb_U_ix_ices_bysize,
+ pl_sb_U_ix_ices_bysize,
+ pl_sb_U_ix_ices,
+) = make_pl_si_lists(pl_sb_U_ix_ices_list, "ices", 2)
+
+# CLASSICAL "..[ei]x" -> "..ices"
+
+pl_sb_C_ex_ices_list = (
+ "vortex",
+ "vertex",
+ "cortex",
+ "latex",
+ "pontifex",
+ "apex",
+ "index",
+ "simplex",
+)
+
+(
+ si_sb_C_ex_ices_list,
+ si_sb_C_ex_ices_bysize,
+ pl_sb_C_ex_ices_bysize,
+ pl_sb_C_ex_ices,
+) = make_pl_si_lists(pl_sb_C_ex_ices_list, "ices", 2)
+
+
+pl_sb_C_ix_ices_list = ("appendix",)
+
+(
+ si_sb_C_ix_ices_list,
+ si_sb_C_ix_ices_bysize,
+ pl_sb_C_ix_ices_bysize,
+ pl_sb_C_ix_ices,
+) = make_pl_si_lists(pl_sb_C_ix_ices_list, "ices", 2)
+
+
+# ARABIC: ".." -> "..i"
+
+pl_sb_C_i_list = ("afrit", "afreet", "efreet")
+
+(si_sb_C_i_list, si_sb_C_i_bysize, pl_sb_C_i_bysize, pl_sb_C_i) = make_pl_si_lists(
+ pl_sb_C_i_list, "i", None
+)
+
+
+# HEBREW: ".." -> "..im"
+
+pl_sb_C_im_list = ("goy", "seraph", "cherub")
+
+(si_sb_C_im_list, si_sb_C_im_bysize, pl_sb_C_im_bysize, pl_sb_C_im) = make_pl_si_lists(
+ pl_sb_C_im_list, "im", None
+)
+
+
+# UNCONDITIONAL "..man" -> "..mans"
+
+pl_sb_U_man_mans_list = """
+ ataman caiman cayman ceriman
+ desman dolman farman harman hetman
+ human leman ottoman shaman talisman
+""".split()
+pl_sb_U_man_mans_caps_list = """
+ Alabaman Bahaman Burman German
+ Hiroshiman Liman Nakayaman Norman Oklahoman
+ Panaman Roman Selman Sonaman Tacoman Yakiman
+ Yokohaman Yuman
+""".split()
+
+(
+ si_sb_U_man_mans_list,
+ si_sb_U_man_mans_bysize,
+ pl_sb_U_man_mans_bysize,
+) = make_pl_si_lists(pl_sb_U_man_mans_list, "s", None, dojoinstem=False)
+(
+ si_sb_U_man_mans_caps_list,
+ si_sb_U_man_mans_caps_bysize,
+ pl_sb_U_man_mans_caps_bysize,
+) = make_pl_si_lists(pl_sb_U_man_mans_caps_list, "s", None, dojoinstem=False)
+
+# UNCONDITIONAL "..louse" -> "..lice"
+pl_sb_U_louse_lice_list = ("booklouse", "grapelouse", "louse", "woodlouse")
+
+(
+ si_sb_U_louse_lice_list,
+ si_sb_U_louse_lice_bysize,
+ pl_sb_U_louse_lice_bysize,
+) = make_pl_si_lists(pl_sb_U_louse_lice_list, "lice", 5, dojoinstem=False)
+
+pl_sb_uninflected_s_complete = [
+ # PAIRS OR GROUPS SUBSUMED TO A SINGULAR...
+ "breeches",
+ "britches",
+ "pajamas",
+ "pyjamas",
+ "clippers",
+ "gallows",
+ "hijinks",
+ "headquarters",
+ "pliers",
+ "scissors",
+ "testes",
+ "herpes",
+ "pincers",
+ "shears",
+ "proceedings",
+ "trousers",
+ # UNASSIMILATED LATIN 4th DECLENSION
+ "cantus",
+ "coitus",
+ "nexus",
+ # RECENT IMPORTS...
+ "contretemps",
+ "corps",
+ "debris",
+ "siemens",
+ # DISEASES
+ "mumps",
+ # MISCELLANEOUS OTHERS...
+ "diabetes",
+ "jackanapes",
+ "series",
+ "species",
+ "subspecies",
+ "rabies",
+ "chassis",
+ "innings",
+ "news",
+ "mews",
+ "haggis",
+]
+
+pl_sb_uninflected_s_endings = [
+ # RECENT IMPORTS...
+ "ois",
+ # DISEASES
+ "measles",
+]
+
+pl_sb_uninflected_s = pl_sb_uninflected_s_complete + [
+ f".*{w}" for w in pl_sb_uninflected_s_endings
+]
+
+pl_sb_uninflected_herd = (
+ # DON'T INFLECT IN CLASSICAL MODE, OTHERWISE NORMAL INFLECTION
+ "wildebeest",
+ "swine",
+ "eland",
+ "bison",
+ "buffalo",
+ "cattle",
+ "elk",
+ "rhinoceros",
+ "zucchini",
+ "caribou",
+ "dace",
+ "grouse",
+ "guinea fowl",
+ "guinea-fowl",
+ "haddock",
+ "hake",
+ "halibut",
+ "herring",
+ "mackerel",
+ "pickerel",
+ "pike",
+ "roe",
+ "seed",
+ "shad",
+ "snipe",
+ "teal",
+ "turbot",
+ "water fowl",
+ "water-fowl",
+)
+
+pl_sb_uninflected_complete = [
+ # SOME FISH AND HERD ANIMALS
+ "tuna",
+ "salmon",
+ "mackerel",
+ "trout",
+ "bream",
+ "sea-bass",
+ "sea bass",
+ "carp",
+ "cod",
+ "flounder",
+ "whiting",
+ "moose",
+ # OTHER ODDITIES
+ "graffiti",
+ "djinn",
+ "samuri",
+ "offspring",
+ "pence",
+ "quid",
+ "hertz",
+] + pl_sb_uninflected_s_complete
+# SOME WORDS ENDING IN ...s (OFTEN PAIRS TAKEN AS A WHOLE)
+
+pl_sb_uninflected_caps = [
+ # ALL NATIONALS ENDING IN -ese
+ "Portuguese",
+ "Amoyese",
+ "Borghese",
+ "Congoese",
+ "Faroese",
+ "Foochowese",
+ "Genevese",
+ "Genoese",
+ "Gilbertese",
+ "Hottentotese",
+ "Kiplingese",
+ "Kongoese",
+ "Lucchese",
+ "Maltese",
+ "Nankingese",
+ "Niasese",
+ "Pekingese",
+ "Piedmontese",
+ "Pistoiese",
+ "Sarawakese",
+ "Shavese",
+ "Vermontese",
+ "Wenchowese",
+ "Yengeese",
+]
+
+
+pl_sb_uninflected_endings = [
+ # UNCOUNTABLE NOUNS
+ "butter",
+ "cash",
+ "furniture",
+ "information",
+ # SOME FISH AND HERD ANIMALS
+ "fish",
+ "deer",
+ "sheep",
+ # ALL NATIONALS ENDING IN -ese
+ "nese",
+ "rese",
+ "lese",
+ "mese",
+ # DISEASES
+ "pox",
+ # OTHER ODDITIES
+ "craft",
+] + pl_sb_uninflected_s_endings
+# SOME WORDS ENDING IN ...s (OFTEN PAIRS TAKEN AS A WHOLE)
+
+
+pl_sb_uninflected_bysize = bysize(pl_sb_uninflected_endings)
+
+
+# SINGULAR WORDS ENDING IN ...s (ALL INFLECT WITH ...es)
+
+pl_sb_singular_s_complete = [
+ "acropolis",
+ "aegis",
+ "alias",
+ "asbestos",
+ "bathos",
+ "bias",
+ "bronchitis",
+ "bursitis",
+ "caddis",
+ "cannabis",
+ "canvas",
+ "chaos",
+ "cosmos",
+ "dais",
+ "digitalis",
+ "epidermis",
+ "ethos",
+ "eyas",
+ "gas",
+ "glottis",
+ "hubris",
+ "ibis",
+ "lens",
+ "mantis",
+ "marquis",
+ "metropolis",
+ "pathos",
+ "pelvis",
+ "polis",
+ "rhinoceros",
+ "sassafras",
+ "trellis",
+] + pl_sb_C_is_ides_complete
+
+
+pl_sb_singular_s_endings = ["ss", "us"] + pl_sb_C_is_ides_endings
+
+pl_sb_singular_s_bysize = bysize(pl_sb_singular_s_endings)
+
+si_sb_singular_s_complete = [f"{w}es" for w in pl_sb_singular_s_complete]
+si_sb_singular_s_endings = [f"{w}es" for w in pl_sb_singular_s_endings]
+si_sb_singular_s_bysize = bysize(si_sb_singular_s_endings)
+
+pl_sb_singular_s_es = ["[A-Z].*es"]
+
+pl_sb_singular_s = enclose(
+ "|".join(
+ pl_sb_singular_s_complete
+ + [f".*{w}" for w in pl_sb_singular_s_endings]
+ + pl_sb_singular_s_es
+ )
+)
+
+
+# PLURALS ENDING IN uses -> use
+
+
+si_sb_ois_oi_case = ("Bolshois", "Hanois")
+
+si_sb_uses_use_case = ("Betelgeuses", "Duses", "Meuses", "Syracuses", "Toulouses")
+
+si_sb_uses_use = (
+ "abuses",
+ "applauses",
+ "blouses",
+ "carouses",
+ "causes",
+ "chartreuses",
+ "clauses",
+ "contuses",
+ "douses",
+ "excuses",
+ "fuses",
+ "grouses",
+ "hypotenuses",
+ "masseuses",
+ "menopauses",
+ "misuses",
+ "muses",
+ "overuses",
+ "pauses",
+ "peruses",
+ "profuses",
+ "recluses",
+ "reuses",
+ "ruses",
+ "souses",
+ "spouses",
+ "suffuses",
+ "transfuses",
+ "uses",
+)
+
+si_sb_ies_ie_case = (
+ "Addies",
+ "Aggies",
+ "Allies",
+ "Amies",
+ "Angies",
+ "Annies",
+ "Annmaries",
+ "Archies",
+ "Arties",
+ "Aussies",
+ "Barbies",
+ "Barries",
+ "Basies",
+ "Bennies",
+ "Bernies",
+ "Berties",
+ "Bessies",
+ "Betties",
+ "Billies",
+ "Blondies",
+ "Bobbies",
+ "Bonnies",
+ "Bowies",
+ "Brandies",
+ "Bries",
+ "Brownies",
+ "Callies",
+ "Carnegies",
+ "Carries",
+ "Cassies",
+ "Charlies",
+ "Cheries",
+ "Christies",
+ "Connies",
+ "Curies",
+ "Dannies",
+ "Debbies",
+ "Dixies",
+ "Dollies",
+ "Donnies",
+ "Drambuies",
+ "Eddies",
+ "Effies",
+ "Ellies",
+ "Elsies",
+ "Eries",
+ "Ernies",
+ "Essies",
+ "Eugenies",
+ "Fannies",
+ "Flossies",
+ "Frankies",
+ "Freddies",
+ "Gillespies",
+ "Goldies",
+ "Gracies",
+ "Guthries",
+ "Hallies",
+ "Hatties",
+ "Hetties",
+ "Hollies",
+ "Jackies",
+ "Jamies",
+ "Janies",
+ "Jannies",
+ "Jeanies",
+ "Jeannies",
+ "Jennies",
+ "Jessies",
+ "Jimmies",
+ "Jodies",
+ "Johnies",
+ "Johnnies",
+ "Josies",
+ "Julies",
+ "Kalgoorlies",
+ "Kathies",
+ "Katies",
+ "Kellies",
+ "Kewpies",
+ "Kristies",
+ "Laramies",
+ "Lassies",
+ "Lauries",
+ "Leslies",
+ "Lessies",
+ "Lillies",
+ "Lizzies",
+ "Lonnies",
+ "Lories",
+ "Lorries",
+ "Lotties",
+ "Louies",
+ "Mackenzies",
+ "Maggies",
+ "Maisies",
+ "Mamies",
+ "Marcies",
+ "Margies",
+ "Maries",
+ "Marjories",
+ "Matties",
+ "McKenzies",
+ "Melanies",
+ "Mickies",
+ "Millies",
+ "Minnies",
+ "Mollies",
+ "Mounties",
+ "Nannies",
+ "Natalies",
+ "Nellies",
+ "Netties",
+ "Ollies",
+ "Ozzies",
+ "Pearlies",
+ "Pottawatomies",
+ "Reggies",
+ "Richies",
+ "Rickies",
+ "Robbies",
+ "Ronnies",
+ "Rosalies",
+ "Rosemaries",
+ "Rosies",
+ "Roxies",
+ "Rushdies",
+ "Ruthies",
+ "Sadies",
+ "Sallies",
+ "Sammies",
+ "Scotties",
+ "Selassies",
+ "Sherries",
+ "Sophies",
+ "Stacies",
+ "Stefanies",
+ "Stephanies",
+ "Stevies",
+ "Susies",
+ "Sylvies",
+ "Tammies",
+ "Terries",
+ "Tessies",
+ "Tommies",
+ "Tracies",
+ "Trekkies",
+ "Valaries",
+ "Valeries",
+ "Valkyries",
+ "Vickies",
+ "Virgies",
+ "Willies",
+ "Winnies",
+ "Wylies",
+ "Yorkies",
+)
+
+si_sb_ies_ie = (
+ "aeries",
+ "baggies",
+ "belies",
+ "biggies",
+ "birdies",
+ "bogies",
+ "bonnies",
+ "boogies",
+ "bookies",
+ "bourgeoisies",
+ "brownies",
+ "budgies",
+ "caddies",
+ "calories",
+ "camaraderies",
+ "cockamamies",
+ "collies",
+ "cookies",
+ "coolies",
+ "cooties",
+ "coteries",
+ "crappies",
+ "curies",
+ "cutesies",
+ "dogies",
+ "eyries",
+ "floozies",
+ "footsies",
+ "freebies",
+ "genies",
+ "goalies",
+ "groupies",
+ "hies",
+ "jalousies",
+ "junkies",
+ "kiddies",
+ "laddies",
+ "lassies",
+ "lies",
+ "lingeries",
+ "magpies",
+ "menageries",
+ "mommies",
+ "movies",
+ "neckties",
+ "newbies",
+ "nighties",
+ "oldies",
+ "organdies",
+ "overlies",
+ "pies",
+ "pinkies",
+ "pixies",
+ "potpies",
+ "prairies",
+ "quickies",
+ "reveries",
+ "rookies",
+ "rotisseries",
+ "softies",
+ "sorties",
+ "species",
+ "stymies",
+ "sweeties",
+ "ties",
+ "underlies",
+ "unties",
+ "veggies",
+ "vies",
+ "yuppies",
+ "zombies",
+)
+
+
+si_sb_oes_oe_case = (
+ "Chloes",
+ "Crusoes",
+ "Defoes",
+ "Faeroes",
+ "Ivanhoes",
+ "Joes",
+ "McEnroes",
+ "Moes",
+ "Monroes",
+ "Noes",
+ "Poes",
+ "Roscoes",
+ "Tahoes",
+ "Tippecanoes",
+ "Zoes",
+)
+
+si_sb_oes_oe = (
+ "aloes",
+ "backhoes",
+ "canoes",
+ "does",
+ "floes",
+ "foes",
+ "hoes",
+ "mistletoes",
+ "oboes",
+ "pekoes",
+ "roes",
+ "sloes",
+ "throes",
+ "tiptoes",
+ "toes",
+ "woes",
+)
+
+si_sb_z_zes = ("quartzes", "topazes")
+
+si_sb_zzes_zz = ("buzzes", "fizzes", "frizzes", "razzes")
+
+si_sb_ches_che_case = (
+ "Andromaches",
+ "Apaches",
+ "Blanches",
+ "Comanches",
+ "Nietzsches",
+ "Porsches",
+ "Roches",
+)
+
+si_sb_ches_che = (
+ "aches",
+ "avalanches",
+ "backaches",
+ "bellyaches",
+ "caches",
+ "cloches",
+ "creches",
+ "douches",
+ "earaches",
+ "fiches",
+ "headaches",
+ "heartaches",
+ "microfiches",
+ "niches",
+ "pastiches",
+ "psyches",
+ "quiches",
+ "stomachaches",
+ "toothaches",
+ "tranches",
+)
+
+si_sb_xes_xe = ("annexes", "axes", "deluxes", "pickaxes")
+
+si_sb_sses_sse_case = ("Hesses", "Jesses", "Larousses", "Matisses")
+si_sb_sses_sse = (
+ "bouillabaisses",
+ "crevasses",
+ "demitasses",
+ "impasses",
+ "mousses",
+ "posses",
+)
+
+si_sb_ves_ve_case = (
+ # *[nwl]ives -> [nwl]live
+ "Clives",
+ "Palmolives",
+)
+si_sb_ves_ve = (
+ # *[^d]eaves -> eave
+ "interweaves",
+ "weaves",
+ # *[nwl]ives -> [nwl]live
+ "olives",
+ # *[eoa]lves -> [eoa]lve
+ "bivalves",
+ "dissolves",
+ "resolves",
+ "salves",
+ "twelves",
+ "valves",
+)
+
+
+plverb_special_s = enclose(
+ "|".join(
+ [pl_sb_singular_s]
+ + pl_sb_uninflected_s
+ + list(pl_sb_irregular_s)
+ + ["(.*[csx])is", "(.*)ceps", "[A-Z].*s"]
+ )
+)
+
+_pl_sb_postfix_adj_defn = (
+ ("general", enclose(r"(?!major|lieutenant|brigadier|adjutant|.*star)\S+")),
+ ("martial", enclose("court")),
+ ("force", enclose("pound")),
+)
+
+pl_sb_postfix_adj: Iterable[str] = (
+ enclose(val + f"(?=(?:-|\\s+){key})") for key, val in _pl_sb_postfix_adj_defn
+)
+
+pl_sb_postfix_adj_stems = f"({'|'.join(pl_sb_postfix_adj)})(.*)"
+
+
+# PLURAL WORDS ENDING IS es GO TO SINGULAR is
+
+si_sb_es_is = (
+ "amanuenses",
+ "amniocenteses",
+ "analyses",
+ "antitheses",
+ "apotheoses",
+ "arterioscleroses",
+ "atheroscleroses",
+ "axes",
+ # 'bases', # bases -> basis
+ "catalyses",
+ "catharses",
+ "chasses",
+ "cirrhoses",
+ "cocces",
+ "crises",
+ "diagnoses",
+ "dialyses",
+ "diereses",
+ "electrolyses",
+ "emphases",
+ "exegeses",
+ "geneses",
+ "halitoses",
+ "hydrolyses",
+ "hypnoses",
+ "hypotheses",
+ "hystereses",
+ "metamorphoses",
+ "metastases",
+ "misdiagnoses",
+ "mitoses",
+ "mononucleoses",
+ "narcoses",
+ "necroses",
+ "nemeses",
+ "neuroses",
+ "oases",
+ "osmoses",
+ "osteoporoses",
+ "paralyses",
+ "parentheses",
+ "parthenogeneses",
+ "periphrases",
+ "photosyntheses",
+ "probosces",
+ "prognoses",
+ "prophylaxes",
+ "prostheses",
+ "preces",
+ "psoriases",
+ "psychoanalyses",
+ "psychokineses",
+ "psychoses",
+ "scleroses",
+ "scolioses",
+ "sepses",
+ "silicoses",
+ "symbioses",
+ "synopses",
+ "syntheses",
+ "taxes",
+ "telekineses",
+ "theses",
+ "thromboses",
+ "tuberculoses",
+ "urinalyses",
+)
+
+pl_prep_list = """
+ about above across after among around at athwart before behind
+ below beneath beside besides between betwixt beyond but by
+ during except for from in into near of off on onto out over
+ since till to under until unto upon with""".split()
+
+pl_prep_list_da = pl_prep_list + ["de", "du", "da"]
+
+pl_prep_bysize = bysize(pl_prep_list_da)
+
+pl_prep = enclose("|".join(pl_prep_list_da))
+
+pl_sb_prep_dual_compound = rf"(.*?)((?:-|\s+)(?:{pl_prep})(?:-|\s+))a(?:-|\s+)(.*)"
+
+
+singular_pronoun_genders = {
+ "neuter",
+ "feminine",
+ "masculine",
+ "gender-neutral",
+ "feminine or masculine",
+ "masculine or feminine",
+}
+
+pl_pron_nom = {
+ # NOMINATIVE REFLEXIVE
+ "i": "we",
+ "myself": "ourselves",
+ "you": "you",
+ "yourself": "yourselves",
+ "she": "they",
+ "herself": "themselves",
+ "he": "they",
+ "himself": "themselves",
+ "it": "they",
+ "itself": "themselves",
+ "they": "they",
+ "themself": "themselves",
+ # POSSESSIVE
+ "mine": "ours",
+ "yours": "yours",
+ "hers": "theirs",
+ "his": "theirs",
+ "its": "theirs",
+ "theirs": "theirs",
+}
+
+si_pron: Dict[str, Dict[str, Union[str, Dict[str, str]]]] = {
+ "nom": {v: k for (k, v) in pl_pron_nom.items()}
+}
+si_pron["nom"]["we"] = "I"
+
+
+pl_pron_acc = {
+ # ACCUSATIVE REFLEXIVE
+ "me": "us",
+ "myself": "ourselves",
+ "you": "you",
+ "yourself": "yourselves",
+ "her": "them",
+ "herself": "themselves",
+ "him": "them",
+ "himself": "themselves",
+ "it": "them",
+ "itself": "themselves",
+ "them": "them",
+ "themself": "themselves",
+}
+
+pl_pron_acc_keys = enclose("|".join(pl_pron_acc))
+pl_pron_acc_keys_bysize = bysize(pl_pron_acc)
+
+si_pron["acc"] = {v: k for (k, v) in pl_pron_acc.items()}
+
+for _thecase, _plur, _gend, _sing in (
+ ("nom", "they", "neuter", "it"),
+ ("nom", "they", "feminine", "she"),
+ ("nom", "they", "masculine", "he"),
+ ("nom", "they", "gender-neutral", "they"),
+ ("nom", "they", "feminine or masculine", "she or he"),
+ ("nom", "they", "masculine or feminine", "he or she"),
+ ("nom", "themselves", "neuter", "itself"),
+ ("nom", "themselves", "feminine", "herself"),
+ ("nom", "themselves", "masculine", "himself"),
+ ("nom", "themselves", "gender-neutral", "themself"),
+ ("nom", "themselves", "feminine or masculine", "herself or himself"),
+ ("nom", "themselves", "masculine or feminine", "himself or herself"),
+ ("nom", "theirs", "neuter", "its"),
+ ("nom", "theirs", "feminine", "hers"),
+ ("nom", "theirs", "masculine", "his"),
+ ("nom", "theirs", "gender-neutral", "theirs"),
+ ("nom", "theirs", "feminine or masculine", "hers or his"),
+ ("nom", "theirs", "masculine or feminine", "his or hers"),
+ ("acc", "them", "neuter", "it"),
+ ("acc", "them", "feminine", "her"),
+ ("acc", "them", "masculine", "him"),
+ ("acc", "them", "gender-neutral", "them"),
+ ("acc", "them", "feminine or masculine", "her or him"),
+ ("acc", "them", "masculine or feminine", "him or her"),
+ ("acc", "themselves", "neuter", "itself"),
+ ("acc", "themselves", "feminine", "herself"),
+ ("acc", "themselves", "masculine", "himself"),
+ ("acc", "themselves", "gender-neutral", "themself"),
+ ("acc", "themselves", "feminine or masculine", "herself or himself"),
+ ("acc", "themselves", "masculine or feminine", "himself or herself"),
+):
+ try:
+ si_pron[_thecase][_plur][_gend] = _sing # type: ignore
+ except TypeError:
+ si_pron[_thecase][_plur] = {}
+ si_pron[_thecase][_plur][_gend] = _sing # type: ignore
+
+
+si_pron_acc_keys = enclose("|".join(si_pron["acc"]))
+si_pron_acc_keys_bysize = bysize(si_pron["acc"])
+
+
+def get_si_pron(thecase, word, gender) -> str:
+ try:
+ sing = si_pron[thecase][word]
+ except KeyError:
+ raise # not a pronoun
+ try:
+ return sing[gender] # has several types due to gender
+ except TypeError:
+ return cast(str, sing) # answer independent of gender
+
+
+# These dictionaries group verbs by first, second and third person
+# conjugations.
+
+plverb_irregular_pres = {
+ "am": "are",
+ "are": "are",
+ "is": "are",
+ "was": "were",
+ "were": "were",
+ "have": "have",
+ "has": "have",
+ "do": "do",
+ "does": "do",
+}
+
+plverb_ambiguous_pres = {
+ "act": "act",
+ "acts": "act",
+ "blame": "blame",
+ "blames": "blame",
+ "can": "can",
+ "must": "must",
+ "fly": "fly",
+ "flies": "fly",
+ "copy": "copy",
+ "copies": "copy",
+ "drink": "drink",
+ "drinks": "drink",
+ "fight": "fight",
+ "fights": "fight",
+ "fire": "fire",
+ "fires": "fire",
+ "like": "like",
+ "likes": "like",
+ "look": "look",
+ "looks": "look",
+ "make": "make",
+ "makes": "make",
+ "reach": "reach",
+ "reaches": "reach",
+ "run": "run",
+ "runs": "run",
+ "sink": "sink",
+ "sinks": "sink",
+ "sleep": "sleep",
+ "sleeps": "sleep",
+ "view": "view",
+ "views": "view",
+}
+
+plverb_ambiguous_pres_keys = re.compile(
+ rf"^({enclose('|'.join(plverb_ambiguous_pres))})((\s.*)?)$", re.IGNORECASE
+)
+
+
+plverb_irregular_non_pres = (
+ "did",
+ "had",
+ "ate",
+ "made",
+ "put",
+ "spent",
+ "fought",
+ "sank",
+ "gave",
+ "sought",
+ "shall",
+ "could",
+ "ought",
+ "should",
+)
+
+plverb_ambiguous_non_pres = re.compile(
+ r"^((?:thought|saw|bent|will|might|cut))((\s.*)?)$", re.IGNORECASE
+)
+
+# "..oes" -> "..oe" (the rest are "..oes" -> "o")
+
+pl_v_oes_oe = ("canoes", "floes", "oboes", "roes", "throes", "woes")
+pl_v_oes_oe_endings_size4 = ("hoes", "toes")
+pl_v_oes_oe_endings_size5 = ("shoes",)
+
+
+pl_count_zero = ("0", "no", "zero", "nil")
+
+
+pl_count_one = ("1", "a", "an", "one", "each", "every", "this", "that")
+
+pl_adj_special = {"a": "some", "an": "some", "this": "these", "that": "those"}
+
+pl_adj_special_keys = re.compile(
+ rf"^({enclose('|'.join(pl_adj_special))})$", re.IGNORECASE
+)
+
+pl_adj_poss = {
+ "my": "our",
+ "your": "your",
+ "its": "their",
+ "her": "their",
+ "his": "their",
+ "their": "their",
+}
+
+pl_adj_poss_keys = re.compile(rf"^({enclose('|'.join(pl_adj_poss))})$", re.IGNORECASE)
+
+
+# 2. INDEFINITE ARTICLES
+
+# THIS PATTERN MATCHES STRINGS OF CAPITALS STARTING WITH A "VOWEL-SOUND"
+# CONSONANT FOLLOWED BY ANOTHER CONSONANT, AND WHICH ARE NOT LIKELY
+# TO BE REAL WORDS (OH, ALL RIGHT THEN, IT'S JUST MAGIC!)
+
+A_abbrev = re.compile(
+ r"""
+^(?! FJO | [HLMNS]Y. | RY[EO] | SQU
+ | ( F[LR]? | [HL] | MN? | N | RH? | S[CHKLMNPTVW]? | X(YL)?) [AEIOU])
+[FHLMNRSX][A-Z]
+""",
+ re.VERBOSE,
+)
+
+# THIS PATTERN CODES THE BEGINNINGS OF ALL ENGLISH WORDS BEGINING WITH A
+# 'y' FOLLOWED BY A CONSONANT. ANY OTHER Y-CONSONANT PREFIX THEREFORE
+# IMPLIES AN ABBREVIATION.
+
+A_y_cons = re.compile(r"^(y(b[lor]|cl[ea]|fere|gg|p[ios]|rou|tt))", re.IGNORECASE)
+
+# EXCEPTIONS TO EXCEPTIONS
+
+A_explicit_a = re.compile(r"^((?:unabomber|unanimous|US))", re.IGNORECASE)
+
+A_explicit_an = re.compile(
+ r"^((?:euler|hour(?!i)|heir|honest|hono[ur]|mpeg))", re.IGNORECASE
+)
+
+A_ordinal_an = re.compile(r"^([aefhilmnorsx]-?th)", re.IGNORECASE)
+
+A_ordinal_a = re.compile(r"^([bcdgjkpqtuvwyz]-?th)", re.IGNORECASE)
+
+
+# NUMERICAL INFLECTIONS
+
+nth = {
+ 0: "th",
+ 1: "st",
+ 2: "nd",
+ 3: "rd",
+ 4: "th",
+ 5: "th",
+ 6: "th",
+ 7: "th",
+ 8: "th",
+ 9: "th",
+ 11: "th",
+ 12: "th",
+ 13: "th",
+}
+nth_suff = set(nth.values())
+
+ordinal = dict(
+ ty="tieth",
+ one="first",
+ two="second",
+ three="third",
+ five="fifth",
+ eight="eighth",
+ nine="ninth",
+ twelve="twelfth",
+)
+
+ordinal_suff = re.compile(rf"({'|'.join(ordinal)})\Z")
+
+
+# NUMBERS
+
+unit = ["", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
+teen = [
+ "ten",
+ "eleven",
+ "twelve",
+ "thirteen",
+ "fourteen",
+ "fifteen",
+ "sixteen",
+ "seventeen",
+ "eighteen",
+ "nineteen",
+]
+ten = [
+ "",
+ "",
+ "twenty",
+ "thirty",
+ "forty",
+ "fifty",
+ "sixty",
+ "seventy",
+ "eighty",
+ "ninety",
+]
+mill = [
+ " ",
+ " thousand",
+ " million",
+ " billion",
+ " trillion",
+ " quadrillion",
+ " quintillion",
+ " sextillion",
+ " septillion",
+ " octillion",
+ " nonillion",
+ " decillion",
+]
+
+
+# SUPPORT CLASSICAL PLURALIZATIONS
+
+def_classical = dict(
+ all=False, zero=False, herd=False, names=True, persons=False, ancient=False
+)
+
+all_classical = {k: True for k in def_classical}
+no_classical = {k: False for k in def_classical}
+
+
+# Maps strings to built-in constant types
+string_to_constant = {"True": True, "False": False, "None": None}
+
+
+# Pre-compiled regular expression objects
+DOLLAR_DIGITS = re.compile(r"\$(\d+)")
+FUNCTION_CALL = re.compile(r"((\w+)\([^)]*\)*)", re.IGNORECASE)
+PARTITION_WORD = re.compile(r"\A(\s*)(.+?)(\s*)\Z")
+PL_SB_POSTFIX_ADJ_STEMS_RE = re.compile(
+ rf"^(?:{pl_sb_postfix_adj_stems})$", re.IGNORECASE
+)
+PL_SB_PREP_DUAL_COMPOUND_RE = re.compile(
+ rf"^(?:{pl_sb_prep_dual_compound})$", re.IGNORECASE
+)
+DENOMINATOR = re.compile(r"(?P.+)( (per|a) .+)")
+PLVERB_SPECIAL_S_RE = re.compile(rf"^({plverb_special_s})$")
+WHITESPACE = re.compile(r"\s")
+ENDS_WITH_S = re.compile(r"^(.*[^s])s$", re.IGNORECASE)
+ENDS_WITH_APOSTROPHE_S = re.compile(r"^(.*)'s?$")
+INDEFINITE_ARTICLE_TEST = re.compile(r"\A(\s*)(?:an?\s+)?(.+?)(\s*)\Z", re.IGNORECASE)
+SPECIAL_AN = re.compile(r"^[aefhilmnorsx]$", re.IGNORECASE)
+SPECIAL_A = re.compile(r"^[bcdgjkpqtuvwyz]$", re.IGNORECASE)
+SPECIAL_ABBREV_AN = re.compile(r"^[aefhilmnorsx][.-]", re.IGNORECASE)
+SPECIAL_ABBREV_A = re.compile(r"^[a-z][.-]", re.IGNORECASE)
+CONSONANTS = re.compile(r"^[^aeiouy]", re.IGNORECASE)
+ARTICLE_SPECIAL_EU = re.compile(r"^e[uw]", re.IGNORECASE)
+ARTICLE_SPECIAL_ONCE = re.compile(r"^onc?e\b", re.IGNORECASE)
+ARTICLE_SPECIAL_ONETIME = re.compile(r"^onetime\b", re.IGNORECASE)
+ARTICLE_SPECIAL_UNIT = re.compile(r"^uni([^nmd]|mo)", re.IGNORECASE)
+ARTICLE_SPECIAL_UBA = re.compile(r"^u[bcfghjkqrst][aeiou]", re.IGNORECASE)
+ARTICLE_SPECIAL_UKR = re.compile(r"^ukr", re.IGNORECASE)
+SPECIAL_CAPITALS = re.compile(r"^U[NK][AIEO]?")
+VOWELS = re.compile(r"^[aeiou]", re.IGNORECASE)
+
+DIGIT_GROUP = re.compile(r"(\d)")
+TWO_DIGITS = re.compile(r"(\d)(\d)")
+THREE_DIGITS = re.compile(r"(\d)(\d)(\d)")
+THREE_DIGITS_WORD = re.compile(r"(\d)(\d)(\d)(?=\D*\Z)")
+TWO_DIGITS_WORD = re.compile(r"(\d)(\d)(?=\D*\Z)")
+ONE_DIGIT_WORD = re.compile(r"(\d)(?=\D*\Z)")
+
+FOUR_DIGIT_COMMA = re.compile(r"(\d)(\d{3}(?:,|\Z))")
+NON_DIGIT = re.compile(r"\D")
+WHITESPACES_COMMA = re.compile(r"\s+,")
+COMMA_WORD = re.compile(r", (\S+)\s+\Z")
+WHITESPACES = re.compile(r"\s+")
+
+
+PRESENT_PARTICIPLE_REPLACEMENTS = (
+ (re.compile(r"ie$"), r"y"),
+ (
+ re.compile(r"ue$"),
+ r"u",
+ ), # TODO: isn't ue$ -> u encompassed in the following rule?
+ (re.compile(r"([auy])e$"), r"\g<1>"),
+ (re.compile(r"ski$"), r"ski"),
+ (re.compile(r"[^b]i$"), r""),
+ (re.compile(r"^(are|were)$"), r"be"),
+ (re.compile(r"^(had)$"), r"hav"),
+ (re.compile(r"^(hoe)$"), r"\g<1>"),
+ (re.compile(r"([^e])e$"), r"\g<1>"),
+ (re.compile(r"er$"), r"er"),
+ (re.compile(r"([^aeiou][aeiouy]([bdgmnprst]))$"), r"\g<1>\g<2>"),
+)
+
+DIGIT = re.compile(r"\d")
+
+
+class Words(str):
+ lowered: str
+ split_: List[str]
+ first: str
+ last: str
+
+ def __init__(self, orig) -> None:
+ self.lowered = self.lower()
+ self.split_ = self.split()
+ self.first = self.split_[0]
+ self.last = self.split_[-1]
+
+
+Falsish = Any # ideally, falsish would only validate on bool(value) is False
+
+
+_STATIC_TYPE_CHECKING = TYPE_CHECKING
+# ^-- Workaround for typeguard AST manipulation:
+# https://github.com/agronholm/typeguard/issues/353#issuecomment-1556306554
+
+if _STATIC_TYPE_CHECKING: # pragma: no cover
+ Word = Annotated[str, "String with at least 1 character"]
+else:
+
+ class _WordMeta(type): # Too dynamic to be supported by mypy...
+ def __instancecheck__(self, instance: Any) -> bool:
+ return isinstance(instance, str) and len(instance) >= 1
+
+ class Word(metaclass=_WordMeta): # type: ignore[no-redef]
+ """String with at least 1 character"""
+
+
+class engine:
+ def __init__(self) -> None:
+ self.classical_dict = def_classical.copy()
+ self.persistent_count: Optional[int] = None
+ self.mill_count = 0
+ self.pl_sb_user_defined: List[Optional[Word]] = []
+ self.pl_v_user_defined: List[Optional[Word]] = []
+ self.pl_adj_user_defined: List[Optional[Word]] = []
+ self.si_sb_user_defined: List[Optional[Word]] = []
+ self.A_a_user_defined: List[Optional[Word]] = []
+ self.thegender = "neuter"
+ self.__number_args: Optional[Dict[str, str]] = None
+
+ @property
+ def _number_args(self):
+ return cast(Dict[str, str], self.__number_args)
+
+ @_number_args.setter
+ def _number_args(self, val):
+ self.__number_args = val
+
+ @typechecked
+ def defnoun(self, singular: Optional[Word], plural: Optional[Word]) -> int:
+ """
+ Set the noun plural of singular to plural.
+
+ """
+ self.checkpat(singular)
+ self.checkpatplural(plural)
+ self.pl_sb_user_defined.extend((singular, plural))
+ self.si_sb_user_defined.extend((plural, singular))
+ return 1
+
+ @typechecked
+ def defverb(
+ self,
+ s1: Optional[Word],
+ p1: Optional[Word],
+ s2: Optional[Word],
+ p2: Optional[Word],
+ s3: Optional[Word],
+ p3: Optional[Word],
+ ) -> int:
+ """
+ Set the verb plurals for s1, s2 and s3 to p1, p2 and p3 respectively.
+
+ Where 1, 2 and 3 represent the 1st, 2nd and 3rd person forms of the verb.
+
+ """
+ self.checkpat(s1)
+ self.checkpat(s2)
+ self.checkpat(s3)
+ self.checkpatplural(p1)
+ self.checkpatplural(p2)
+ self.checkpatplural(p3)
+ self.pl_v_user_defined.extend((s1, p1, s2, p2, s3, p3))
+ return 1
+
+ @typechecked
+ def defadj(self, singular: Optional[Word], plural: Optional[Word]) -> int:
+ """
+ Set the adjective plural of singular to plural.
+
+ """
+ self.checkpat(singular)
+ self.checkpatplural(plural)
+ self.pl_adj_user_defined.extend((singular, plural))
+ return 1
+
+ @typechecked
+ def defa(self, pattern: Optional[Word]) -> int:
+ """
+ Define the indefinite article as 'a' for words matching pattern.
+
+ """
+ self.checkpat(pattern)
+ self.A_a_user_defined.extend((pattern, "a"))
+ return 1
+
+ @typechecked
+ def defan(self, pattern: Optional[Word]) -> int:
+ """
+ Define the indefinite article as 'an' for words matching pattern.
+
+ """
+ self.checkpat(pattern)
+ self.A_a_user_defined.extend((pattern, "an"))
+ return 1
+
+ def checkpat(self, pattern: Optional[Word]) -> None:
+ """
+ check for errors in a regex pattern
+ """
+ if pattern is None:
+ return
+ try:
+ re.match(pattern, "")
+ except re.error as err:
+ raise BadUserDefinedPatternError(pattern) from err
+
+ def checkpatplural(self, pattern: Optional[Word]) -> None:
+ """
+ check for errors in a regex replace pattern
+ """
+ return
+
+ @typechecked
+ def ud_match(self, word: Word, wordlist: Sequence[Optional[Word]]) -> Optional[str]:
+ for i in range(len(wordlist) - 2, -2, -2): # backwards through even elements
+ mo = re.search(rf"^{wordlist[i]}$", word, re.IGNORECASE)
+ if mo:
+ if wordlist[i + 1] is None:
+ return None
+ pl = DOLLAR_DIGITS.sub(
+ r"\\1", cast(Word, wordlist[i + 1])
+ ) # change $n to \n for expand
+ return mo.expand(pl)
+ return None
+
+ def classical(self, **kwargs) -> None:
+ """
+ turn classical mode on and off for various categories
+
+ turn on all classical modes:
+ classical()
+ classical(all=True)
+
+ turn on or off specific claassical modes:
+ e.g.
+ classical(herd=True)
+ classical(names=False)
+
+ By default all classical modes are off except names.
+
+ unknown value in args or key in kwargs raises
+ exception: UnknownClasicalModeError
+
+ """
+ if not kwargs:
+ self.classical_dict = all_classical.copy()
+ return
+ if "all" in kwargs:
+ if kwargs["all"]:
+ self.classical_dict = all_classical.copy()
+ else:
+ self.classical_dict = no_classical.copy()
+
+ for k, v in kwargs.items():
+ if k in def_classical:
+ self.classical_dict[k] = v
+ else:
+ raise UnknownClassicalModeError
+
+ def num(
+ self, count: Optional[int] = None, show: Optional[int] = None
+ ) -> str: # (;$count,$show)
+ """
+ Set the number to be used in other method calls.
+
+ Returns count.
+
+ Set show to False to return '' instead.
+
+ """
+ if count is not None:
+ try:
+ self.persistent_count = int(count)
+ except ValueError as err:
+ raise BadNumValueError from err
+ if (show is None) or show:
+ return str(count)
+ else:
+ self.persistent_count = None
+ return ""
+
+ def gender(self, gender: str) -> None:
+ """
+ set the gender for the singular of plural pronouns
+
+ can be one of:
+ 'neuter' ('they' -> 'it')
+ 'feminine' ('they' -> 'she')
+ 'masculine' ('they' -> 'he')
+ 'gender-neutral' ('they' -> 'they')
+ 'feminine or masculine' ('they' -> 'she or he')
+ 'masculine or feminine' ('they' -> 'he or she')
+ """
+ if gender in singular_pronoun_genders:
+ self.thegender = gender
+ else:
+ raise BadGenderError
+
+ def _get_value_from_ast(self, obj):
+ """
+ Return the value of the ast object.
+ """
+ if isinstance(obj, ast.Num):
+ return obj.n
+ elif isinstance(obj, ast.Str):
+ return obj.s
+ elif isinstance(obj, ast.List):
+ return [self._get_value_from_ast(e) for e in obj.elts]
+ elif isinstance(obj, ast.Tuple):
+ return tuple([self._get_value_from_ast(e) for e in obj.elts])
+
+ # None, True and False are NameConstants in Py3.4 and above.
+ elif isinstance(obj, ast.NameConstant):
+ return obj.value
+
+ # Probably passed a variable name.
+ # Or passed a single word without wrapping it in quotes as an argument
+ # ex: p.inflect("I plural(see)") instead of p.inflect("I plural('see')")
+ raise NameError(f"name '{obj.id}' is not defined")
+
+ def _string_to_substitute(
+ self, mo: Match, methods_dict: Dict[str, Callable]
+ ) -> str:
+ """
+ Return the string to be substituted for the match.
+ """
+ matched_text, f_name = mo.groups()
+ # matched_text is the complete match string. e.g. plural_noun(cat)
+ # f_name is the function name. e.g. plural_noun
+
+ # Return matched_text if function name is not in methods_dict
+ if f_name not in methods_dict:
+ return matched_text
+
+ # Parse the matched text
+ a_tree = ast.parse(matched_text)
+
+ # get the args and kwargs from ast objects
+ args_list = [
+ self._get_value_from_ast(a)
+ for a in a_tree.body[0].value.args # type: ignore[attr-defined]
+ ]
+ kwargs_list = {
+ kw.arg: self._get_value_from_ast(kw.value)
+ for kw in a_tree.body[0].value.keywords # type: ignore[attr-defined]
+ }
+
+ # Call the corresponding function
+ return methods_dict[f_name](*args_list, **kwargs_list)
+
+ # 0. PERFORM GENERAL INFLECTIONS IN A STRING
+
+ @typechecked
+ def inflect(self, text: Word) -> str:
+ """
+ Perform inflections in a string.
+
+ e.g. inflect('The plural of cat is plural(cat)') returns
+ 'The plural of cat is cats'
+
+ can use plural, plural_noun, plural_verb, plural_adj,
+ singular_noun, a, an, no, ordinal, number_to_words,
+ and prespart
+
+ """
+ save_persistent_count = self.persistent_count
+
+ # Dictionary of allowed methods
+ methods_dict: Dict[str, Callable] = {
+ "plural": self.plural,
+ "plural_adj": self.plural_adj,
+ "plural_noun": self.plural_noun,
+ "plural_verb": self.plural_verb,
+ "singular_noun": self.singular_noun,
+ "a": self.a,
+ "an": self.a,
+ "no": self.no,
+ "ordinal": self.ordinal,
+ "number_to_words": self.number_to_words,
+ "present_participle": self.present_participle,
+ "num": self.num,
+ }
+
+ # Regular expression to find Python's function call syntax
+ output = FUNCTION_CALL.sub(
+ lambda mo: self._string_to_substitute(mo, methods_dict), text
+ )
+ self.persistent_count = save_persistent_count
+ return output
+
+ # ## PLURAL SUBROUTINES
+
+ def postprocess(self, orig: str, inflected) -> str:
+ inflected = str(inflected)
+ if "|" in inflected:
+ word_options = inflected.split("|")
+ # When two parts of a noun need to be pluralized
+ if len(word_options[0].split(" ")) == len(word_options[1].split(" ")):
+ result = inflected.split("|")[self.classical_dict["all"]].split(" ")
+ # When only the last part of the noun needs to be pluralized
+ else:
+ result = inflected.split(" ")
+ for index, word in enumerate(result):
+ if "|" in word:
+ result[index] = word.split("|")[self.classical_dict["all"]]
+ else:
+ result = inflected.split(" ")
+
+ # Try to fix word wise capitalization
+ for index, word in enumerate(orig.split(" ")):
+ if word == "I":
+ # Is this the only word for exceptions like this
+ # Where the original is fully capitalized
+ # without 'meaning' capitalization?
+ # Also this fails to handle a capitalizaion in context
+ continue
+ if word.capitalize() == word:
+ result[index] = result[index].capitalize()
+ if word == word.upper():
+ result[index] = result[index].upper()
+ return " ".join(result)
+
+ def partition_word(self, text: str) -> Tuple[str, str, str]:
+ mo = PARTITION_WORD.search(text)
+ if mo:
+ return mo.group(1), mo.group(2), mo.group(3)
+ else:
+ return "", "", ""
+
+ @typechecked
+ def plural(self, text: Word, count: Optional[Union[str, int, Any]] = None) -> str:
+ """
+ Return the plural of text.
+
+ If count supplied, then return text if count is one of:
+ 1, a, an, one, each, every, this, that
+
+ otherwise return the plural.
+
+ Whitespace at the start and end is preserved.
+
+ """
+ pre, word, post = self.partition_word(text)
+ if not word:
+ return text
+ plural = self.postprocess(
+ word,
+ self._pl_special_adjective(word, count)
+ or self._pl_special_verb(word, count)
+ or self._plnoun(word, count),
+ )
+ return f"{pre}{plural}{post}"
+
+ @typechecked
+ def plural_noun(
+ self, text: Word, count: Optional[Union[str, int, Any]] = None
+ ) -> str:
+ """
+ Return the plural of text, where text is a noun.
+
+ If count supplied, then return text if count is one of:
+ 1, a, an, one, each, every, this, that
+
+ otherwise return the plural.
+
+ Whitespace at the start and end is preserved.
+
+ """
+ pre, word, post = self.partition_word(text)
+ if not word:
+ return text
+ plural = self.postprocess(word, self._plnoun(word, count))
+ return f"{pre}{plural}{post}"
+
+ @typechecked
+ def plural_verb(
+ self, text: Word, count: Optional[Union[str, int, Any]] = None
+ ) -> str:
+ """
+ Return the plural of text, where text is a verb.
+
+ If count supplied, then return text if count is one of:
+ 1, a, an, one, each, every, this, that
+
+ otherwise return the plural.
+
+ Whitespace at the start and end is preserved.
+
+ """
+ pre, word, post = self.partition_word(text)
+ if not word:
+ return text
+ plural = self.postprocess(
+ word,
+ self._pl_special_verb(word, count) or self._pl_general_verb(word, count),
+ )
+ return f"{pre}{plural}{post}"
+
+ @typechecked
+ def plural_adj(
+ self, text: Word, count: Optional[Union[str, int, Any]] = None
+ ) -> str:
+ """
+ Return the plural of text, where text is an adjective.
+
+ If count supplied, then return text if count is one of:
+ 1, a, an, one, each, every, this, that
+
+ otherwise return the plural.
+
+ Whitespace at the start and end is preserved.
+
+ """
+ pre, word, post = self.partition_word(text)
+ if not word:
+ return text
+ plural = self.postprocess(word, self._pl_special_adjective(word, count) or word)
+ return f"{pre}{plural}{post}"
+
+ @typechecked
+ def compare(self, word1: Word, word2: Word) -> Union[str, bool]:
+ """
+ compare word1 and word2 for equality regardless of plurality
+
+ return values:
+ eq - the strings are equal
+ p:s - word1 is the plural of word2
+ s:p - word2 is the plural of word1
+ p:p - word1 and word2 are two different plural forms of the one word
+ False - otherwise
+
+ >>> compare = engine().compare
+ >>> compare("egg", "eggs")
+ 's:p'
+ >>> compare('egg', 'egg')
+ 'eq'
+
+ Words should not be empty.
+
+ >>> compare('egg', '')
+ Traceback (most recent call last):
+ ...
+ typeguard.TypeCheckError:...is not an instance of inflect.Word
+ """
+ norms = self.plural_noun, self.plural_verb, self.plural_adj
+ results = (self._plequal(word1, word2, norm) for norm in norms)
+ return next(filter(None, results), False)
+
+ @typechecked
+ def compare_nouns(self, word1: Word, word2: Word) -> Union[str, bool]:
+ """
+ compare word1 and word2 for equality regardless of plurality
+ word1 and word2 are to be treated as nouns
+
+ return values:
+ eq - the strings are equal
+ p:s - word1 is the plural of word2
+ s:p - word2 is the plural of word1
+ p:p - word1 and word2 are two different plural forms of the one word
+ False - otherwise
+
+ """
+ return self._plequal(word1, word2, self.plural_noun)
+
+ @typechecked
+ def compare_verbs(self, word1: Word, word2: Word) -> Union[str, bool]:
+ """
+ compare word1 and word2 for equality regardless of plurality
+ word1 and word2 are to be treated as verbs
+
+ return values:
+ eq - the strings are equal
+ p:s - word1 is the plural of word2
+ s:p - word2 is the plural of word1
+ p:p - word1 and word2 are two different plural forms of the one word
+ False - otherwise
+
+ """
+ return self._plequal(word1, word2, self.plural_verb)
+
+ @typechecked
+ def compare_adjs(self, word1: Word, word2: Word) -> Union[str, bool]:
+ """
+ compare word1 and word2 for equality regardless of plurality
+ word1 and word2 are to be treated as adjectives
+
+ return values:
+ eq - the strings are equal
+ p:s - word1 is the plural of word2
+ s:p - word2 is the plural of word1
+ p:p - word1 and word2 are two different plural forms of the one word
+ False - otherwise
+
+ """
+ return self._plequal(word1, word2, self.plural_adj)
+
+ @typechecked
+ def singular_noun(
+ self,
+ text: Word,
+ count: Optional[Union[int, str, Any]] = None,
+ gender: Optional[str] = None,
+ ) -> Union[str, Literal[False]]:
+ """
+ Return the singular of text, where text is a plural noun.
+
+ If count supplied, then return the singular if count is one of:
+ 1, a, an, one, each, every, this, that or if count is None
+
+ otherwise return text unchanged.
+
+ Whitespace at the start and end is preserved.
+
+ >>> p = engine()
+ >>> p.singular_noun('horses')
+ 'horse'
+ >>> p.singular_noun('knights')
+ 'knight'
+
+ Returns False when a singular noun is passed.
+
+ >>> p.singular_noun('horse')
+ False
+ >>> p.singular_noun('knight')
+ False
+ >>> p.singular_noun('soldier')
+ False
+
+ """
+ pre, word, post = self.partition_word(text)
+ if not word:
+ return text
+ sing = self._sinoun(word, count=count, gender=gender)
+ if sing is not False:
+ plural = self.postprocess(word, sing)
+ return f"{pre}{plural}{post}"
+ return False
+
+ def _plequal(self, word1: str, word2: str, pl) -> Union[str, bool]: # noqa: C901
+ classval = self.classical_dict.copy()
+ self.classical_dict = all_classical.copy()
+ if word1 == word2:
+ return "eq"
+ if word1 == pl(word2):
+ return "p:s"
+ if pl(word1) == word2:
+ return "s:p"
+ self.classical_dict = no_classical.copy()
+ if word1 == pl(word2):
+ return "p:s"
+ if pl(word1) == word2:
+ return "s:p"
+ self.classical_dict = classval.copy()
+
+ if pl == self.plural or pl == self.plural_noun:
+ if self._pl_check_plurals_N(word1, word2):
+ return "p:p"
+ if self._pl_check_plurals_N(word2, word1):
+ return "p:p"
+ if pl == self.plural or pl == self.plural_adj:
+ if self._pl_check_plurals_adj(word1, word2):
+ return "p:p"
+ return False
+
+ def _pl_reg_plurals(self, pair: str, stems: str, end1: str, end2: str) -> bool:
+ pattern = rf"({stems})({end1}\|\1{end2}|{end2}\|\1{end1})"
+ return bool(re.search(pattern, pair))
+
+ def _pl_check_plurals_N(self, word1: str, word2: str) -> bool:
+ stem_endings = (
+ (pl_sb_C_a_ata, "as", "ata"),
+ (pl_sb_C_is_ides, "is", "ides"),
+ (pl_sb_C_a_ae, "s", "e"),
+ (pl_sb_C_en_ina, "ens", "ina"),
+ (pl_sb_C_um_a, "ums", "a"),
+ (pl_sb_C_us_i, "uses", "i"),
+ (pl_sb_C_on_a, "ons", "a"),
+ (pl_sb_C_o_i_stems, "os", "i"),
+ (pl_sb_C_ex_ices, "exes", "ices"),
+ (pl_sb_C_ix_ices, "ixes", "ices"),
+ (pl_sb_C_i, "s", "i"),
+ (pl_sb_C_im, "s", "im"),
+ (".*eau", "s", "x"),
+ (".*ieu", "s", "x"),
+ (".*tri", "xes", "ces"),
+ (".{2,}[yia]n", "xes", "ges"),
+ )
+
+ words = map(Words, (word1, word2))
+ pair = "|".join(word.last for word in words)
+
+ return (
+ pair in pl_sb_irregular_s.values()
+ or pair in pl_sb_irregular.values()
+ or pair in pl_sb_irregular_caps.values()
+ or any(
+ self._pl_reg_plurals(pair, stems, end1, end2)
+ for stems, end1, end2 in stem_endings
+ )
+ )
+
+ def _pl_check_plurals_adj(self, word1: str, word2: str) -> bool:
+ word1a = word1[: word1.rfind("'")] if word1.endswith(("'s", "'")) else ""
+ word2a = word2[: word2.rfind("'")] if word2.endswith(("'s", "'")) else ""
+
+ return (
+ bool(word1a)
+ and bool(word2a)
+ and (
+ self._pl_check_plurals_N(word1a, word2a)
+ or self._pl_check_plurals_N(word2a, word1a)
+ )
+ )
+
+ def get_count(self, count: Optional[Union[str, int]] = None) -> Union[str, int]:
+ if count is None and self.persistent_count is not None:
+ count = self.persistent_count
+
+ if count is not None:
+ count = (
+ 1
+ if (
+ (str(count) in pl_count_one)
+ or (
+ self.classical_dict["zero"]
+ and str(count).lower() in pl_count_zero
+ )
+ )
+ else 2
+ )
+ else:
+ count = ""
+ return count
+
+ # @profile
+ def _plnoun( # noqa: C901
+ self, word: str, count: Optional[Union[str, int]] = None
+ ) -> str:
+ count = self.get_count(count)
+
+ # DEFAULT TO PLURAL
+
+ if count == 1:
+ return word
+
+ # HANDLE USER-DEFINED NOUNS
+
+ value = self.ud_match(word, self.pl_sb_user_defined)
+ if value is not None:
+ return value
+
+ # HANDLE EMPTY WORD, SINGULAR COUNT AND UNINFLECTED PLURALS
+
+ if word == "":
+ return word
+
+ word = Words(word)
+
+ if word.last.lower() in pl_sb_uninflected_complete:
+ if len(word.split_) >= 3:
+ return self._handle_long_compounds(word, count=2) or word
+ return word
+
+ if word in pl_sb_uninflected_caps:
+ return word
+
+ for k, v in pl_sb_uninflected_bysize.items():
+ if word.lowered[-k:] in v:
+ return word
+
+ if self.classical_dict["herd"] and word.last.lower() in pl_sb_uninflected_herd:
+ return word
+
+ # HANDLE COMPOUNDS ("Governor General", "mother-in-law", "aide-de-camp", ETC.)
+
+ mo = PL_SB_POSTFIX_ADJ_STEMS_RE.search(word)
+ if mo and mo.group(2) != "":
+ return f"{self._plnoun(mo.group(1), 2)}{mo.group(2)}"
+
+ if " a " in word.lowered or "-a-" in word.lowered:
+ mo = PL_SB_PREP_DUAL_COMPOUND_RE.search(word)
+ if mo and mo.group(2) != "" and mo.group(3) != "":
+ return (
+ f"{self._plnoun(mo.group(1), 2)}"
+ f"{mo.group(2)}"
+ f"{self._plnoun(mo.group(3))}"
+ )
+
+ if len(word.split_) >= 3:
+ handled_words = self._handle_long_compounds(word, count=2)
+ if handled_words is not None:
+ return handled_words
+
+ # only pluralize denominators in units
+ mo = DENOMINATOR.search(word.lowered)
+ if mo:
+ index = len(mo.group("denominator"))
+ return f"{self._plnoun(word[:index])}{word[index:]}"
+
+ # handle units given in degrees (only accept if
+ # there is no more than one word following)
+ # degree Celsius => degrees Celsius but degree
+ # fahrenheit hour => degree fahrenheit hours
+ if len(word.split_) >= 2 and word.split_[-2] == "degree":
+ return " ".join([self._plnoun(word.first)] + word.split_[1:])
+
+ with contextlib.suppress(ValueError):
+ return self._handle_prepositional_phrase(
+ word.lowered,
+ functools.partial(self._plnoun, count=2),
+ '-',
+ )
+
+ # HANDLE PRONOUNS
+
+ for k, v in pl_pron_acc_keys_bysize.items():
+ if word.lowered[-k:] in v: # ends with accusative pronoun
+ for pk, pv in pl_prep_bysize.items():
+ if word.lowered[:pk] in pv: # starts with a prep
+ if word.lowered.split() == [
+ word.lowered[:pk],
+ word.lowered[-k:],
+ ]:
+ # only whitespace in between
+ return word.lowered[:-k] + pl_pron_acc[word.lowered[-k:]]
+
+ try:
+ return pl_pron_nom[word.lowered]
+ except KeyError:
+ pass
+
+ try:
+ return pl_pron_acc[word.lowered]
+ except KeyError:
+ pass
+
+ # HANDLE ISOLATED IRREGULAR PLURALS
+
+ if word.last in pl_sb_irregular_caps:
+ llen = len(word.last)
+ return f"{word[:-llen]}{pl_sb_irregular_caps[word.last]}"
+
+ lowered_last = word.last.lower()
+ if lowered_last in pl_sb_irregular:
+ llen = len(lowered_last)
+ return f"{word[:-llen]}{pl_sb_irregular[lowered_last]}"
+
+ dash_split = word.lowered.split('-')
+ if (" ".join(dash_split[-2:])).lower() in pl_sb_irregular_compound:
+ llen = len(
+ " ".join(dash_split[-2:])
+ ) # TODO: what if 2 spaces between these words?
+ return (
+ f"{word[:-llen]}"
+ f"{pl_sb_irregular_compound[(' '.join(dash_split[-2:])).lower()]}"
+ )
+
+ if word.lowered[-3:] == "quy":
+ return f"{word[:-1]}ies"
+
+ if word.lowered[-6:] == "person":
+ if self.classical_dict["persons"]:
+ return f"{word}s"
+ else:
+ return f"{word[:-4]}ople"
+
+ # HANDLE FAMILIES OF IRREGULAR PLURALS
+
+ if word.lowered[-3:] == "man":
+ for k, v in pl_sb_U_man_mans_bysize.items():
+ if word.lowered[-k:] in v:
+ return f"{word}s"
+ for k, v in pl_sb_U_man_mans_caps_bysize.items():
+ if word[-k:] in v:
+ return f"{word}s"
+ return f"{word[:-3]}men"
+ if word.lowered[-5:] == "mouse":
+ return f"{word[:-5]}mice"
+ if word.lowered[-5:] == "louse":
+ v = pl_sb_U_louse_lice_bysize.get(len(word))
+ if v and word.lowered in v:
+ return f"{word[:-5]}lice"
+ return f"{word}s"
+ if word.lowered[-5:] == "goose":
+ return f"{word[:-5]}geese"
+ if word.lowered[-5:] == "tooth":
+ return f"{word[:-5]}teeth"
+ if word.lowered[-4:] == "foot":
+ return f"{word[:-4]}feet"
+ if word.lowered[-4:] == "taco":
+ return f"{word[:-5]}tacos"
+
+ if word.lowered == "die":
+ return "dice"
+
+ # HANDLE UNASSIMILATED IMPORTS
+
+ if word.lowered[-4:] == "ceps":
+ return word
+ if word.lowered[-4:] == "zoon":
+ return f"{word[:-2]}a"
+ if word.lowered[-3:] in ("cis", "sis", "xis"):
+ return f"{word[:-2]}es"
+
+ for lastlet, d, numend, post in (
+ ("h", pl_sb_U_ch_chs_bysize, None, "s"),
+ ("x", pl_sb_U_ex_ices_bysize, -2, "ices"),
+ ("x", pl_sb_U_ix_ices_bysize, -2, "ices"),
+ ("m", pl_sb_U_um_a_bysize, -2, "a"),
+ ("s", pl_sb_U_us_i_bysize, -2, "i"),
+ ("n", pl_sb_U_on_a_bysize, -2, "a"),
+ ("a", pl_sb_U_a_ae_bysize, None, "e"),
+ ):
+ if word.lowered[-1] == lastlet: # this test to add speed
+ for k, v in d.items():
+ if word.lowered[-k:] in v:
+ return word[:numend] + post
+
+ # HANDLE INCOMPLETELY ASSIMILATED IMPORTS
+
+ if self.classical_dict["ancient"]:
+ if word.lowered[-4:] == "trix":
+ return f"{word[:-1]}ces"
+ if word.lowered[-3:] in ("eau", "ieu"):
+ return f"{word}x"
+ if word.lowered[-3:] in ("ynx", "inx", "anx") and len(word) > 4:
+ return f"{word[:-1]}ges"
+
+ for lastlet, d, numend, post in (
+ ("n", pl_sb_C_en_ina_bysize, -2, "ina"),
+ ("x", pl_sb_C_ex_ices_bysize, -2, "ices"),
+ ("x", pl_sb_C_ix_ices_bysize, -2, "ices"),
+ ("m", pl_sb_C_um_a_bysize, -2, "a"),
+ ("s", pl_sb_C_us_i_bysize, -2, "i"),
+ ("s", pl_sb_C_us_us_bysize, None, ""),
+ ("a", pl_sb_C_a_ae_bysize, None, "e"),
+ ("a", pl_sb_C_a_ata_bysize, None, "ta"),
+ ("s", pl_sb_C_is_ides_bysize, -1, "des"),
+ ("o", pl_sb_C_o_i_bysize, -1, "i"),
+ ("n", pl_sb_C_on_a_bysize, -2, "a"),
+ ):
+ if word.lowered[-1] == lastlet: # this test to add speed
+ for k, v in d.items():
+ if word.lowered[-k:] in v:
+ return word[:numend] + post
+
+ for d, numend, post in (
+ (pl_sb_C_i_bysize, None, "i"),
+ (pl_sb_C_im_bysize, None, "im"),
+ ):
+ for k, v in d.items():
+ if word.lowered[-k:] in v:
+ return word[:numend] + post
+
+ # HANDLE SINGULAR NOUNS ENDING IN ...s OR OTHER SILIBANTS
+
+ if lowered_last in pl_sb_singular_s_complete:
+ return f"{word}es"
+
+ for k, v in pl_sb_singular_s_bysize.items():
+ if word.lowered[-k:] in v:
+ return f"{word}es"
+
+ if word.lowered[-2:] == "es" and word[0] == word[0].upper():
+ return f"{word}es"
+
+ if word.lowered[-1] == "z":
+ for k, v in pl_sb_z_zes_bysize.items():
+ if word.lowered[-k:] in v:
+ return f"{word}es"
+
+ if word.lowered[-2:-1] != "z":
+ return f"{word}zes"
+
+ if word.lowered[-2:] == "ze":
+ for k, v in pl_sb_ze_zes_bysize.items():
+ if word.lowered[-k:] in v:
+ return f"{word}s"
+
+ if word.lowered[-2:] in ("ch", "sh", "zz", "ss") or word.lowered[-1] == "x":
+ return f"{word}es"
+
+ # HANDLE ...f -> ...ves
+
+ if word.lowered[-3:] in ("elf", "alf", "olf"):
+ return f"{word[:-1]}ves"
+ if word.lowered[-3:] == "eaf" and word.lowered[-4:-3] != "d":
+ return f"{word[:-1]}ves"
+ if word.lowered[-4:] in ("nife", "life", "wife"):
+ return f"{word[:-2]}ves"
+ if word.lowered[-3:] == "arf":
+ return f"{word[:-1]}ves"
+
+ # HANDLE ...y
+
+ if word.lowered[-1] == "y":
+ if word.lowered[-2:-1] in "aeiou" or len(word) == 1:
+ return f"{word}s"
+
+ if self.classical_dict["names"]:
+ if word.lowered[-1] == "y" and word[0] == word[0].upper():
+ return f"{word}s"
+
+ return f"{word[:-1]}ies"
+
+ # HANDLE ...o
+
+ if lowered_last in pl_sb_U_o_os_complete:
+ return f"{word}s"
+
+ for k, v in pl_sb_U_o_os_bysize.items():
+ if word.lowered[-k:] in v:
+ return f"{word}s"
+
+ if word.lowered[-2:] in ("ao", "eo", "io", "oo", "uo"):
+ return f"{word}s"
+
+ if word.lowered[-1] == "o":
+ return f"{word}es"
+
+ # OTHERWISE JUST ADD ...s
+
+ return f"{word}s"
+
+ @classmethod
+ def _handle_prepositional_phrase(cls, phrase, transform, sep):
+ """
+ Given a word or phrase possibly separated by sep, parse out
+ the prepositional phrase and apply the transform to the word
+ preceding the prepositional phrase.
+
+ Raise ValueError if the pivot is not found or if at least two
+ separators are not found.
+
+ >>> engine._handle_prepositional_phrase("man-of-war", str.upper, '-')
+ 'MAN-of-war'
+ >>> engine._handle_prepositional_phrase("man of war", str.upper, ' ')
+ 'MAN of war'
+ """
+ parts = phrase.split(sep)
+ if len(parts) < 3:
+ raise ValueError("Cannot handle words with fewer than two separators")
+
+ pivot = cls._find_pivot(parts, pl_prep_list_da)
+
+ transformed = transform(parts[pivot - 1]) or parts[pivot - 1]
+ return " ".join(
+ parts[: pivot - 1] + [sep.join([transformed, parts[pivot], ''])]
+ ) + " ".join(parts[(pivot + 1) :])
+
+ def _handle_long_compounds(self, word: Words, count: int) -> Union[str, None]:
+ """
+ Handles the plural and singular for compound `Words` that
+ have three or more words, based on the given count.
+
+ >>> engine()._handle_long_compounds(Words("pair of scissors"), 2)
+ 'pairs of scissors'
+ >>> engine()._handle_long_compounds(Words("men beyond hills"), 1)
+ 'man beyond hills'
+ """
+ inflection = self._sinoun if count == 1 else self._plnoun
+ solutions = ( # type: ignore
+ " ".join(
+ itertools.chain(
+ leader,
+ [inflection(cand, count), prep], # type: ignore
+ trailer,
+ )
+ )
+ for leader, (cand, prep), trailer in windowed_complete(word.split_, 2)
+ if prep in pl_prep_list_da # type: ignore
+ )
+ return next(solutions, None)
+
+ @staticmethod
+ def _find_pivot(words, candidates):
+ pivots = (
+ index for index in range(1, len(words) - 1) if words[index] in candidates
+ )
+ try:
+ return next(pivots)
+ except StopIteration:
+ raise ValueError("No pivot found") from None
+
+ def _pl_special_verb( # noqa: C901
+ self, word: str, count: Optional[Union[str, int]] = None
+ ) -> Union[str, bool]:
+ if self.classical_dict["zero"] and str(count).lower() in pl_count_zero:
+ return False
+ count = self.get_count(count)
+
+ if count == 1:
+ return word
+
+ # HANDLE USER-DEFINED VERBS
+
+ value = self.ud_match(word, self.pl_v_user_defined)
+ if value is not None:
+ return value
+
+ # HANDLE IRREGULAR PRESENT TENSE (SIMPLE AND COMPOUND)
+
+ try:
+ words = Words(word)
+ except IndexError:
+ return False # word is ''
+
+ if words.first in plverb_irregular_pres:
+ return f"{plverb_irregular_pres[words.first]}{words[len(words.first) :]}"
+
+ # HANDLE IRREGULAR FUTURE, PRETERITE AND PERFECT TENSES
+
+ if words.first in plverb_irregular_non_pres:
+ return word
+
+ # HANDLE PRESENT NEGATIONS (SIMPLE AND COMPOUND)
+
+ if words.first.endswith("n't") and words.first[:-3] in plverb_irregular_pres:
+ return (
+ f"{plverb_irregular_pres[words.first[:-3]]}n't"
+ f"{words[len(words.first) :]}"
+ )
+
+ if words.first.endswith("n't"):
+ return word
+
+ # HANDLE SPECIAL CASES
+
+ mo = PLVERB_SPECIAL_S_RE.search(word)
+ if mo:
+ return False
+ if WHITESPACE.search(word):
+ return False
+
+ if words.lowered == "quizzes":
+ return "quiz"
+
+ # HANDLE STANDARD 3RD PERSON (CHOP THE ...(e)s OFF SINGLE WORDS)
+
+ if (
+ words.lowered[-4:] in ("ches", "shes", "zzes", "sses")
+ or words.lowered[-3:] == "xes"
+ ):
+ return words[:-2]
+
+ if words.lowered[-3:] == "ies" and len(words) > 3:
+ return words.lowered[:-3] + "y"
+
+ if (
+ words.last.lower() in pl_v_oes_oe
+ or words.lowered[-4:] in pl_v_oes_oe_endings_size4
+ or words.lowered[-5:] in pl_v_oes_oe_endings_size5
+ ):
+ return words[:-1]
+
+ if words.lowered.endswith("oes") and len(words) > 3:
+ return words.lowered[:-2]
+
+ mo = ENDS_WITH_S.search(words)
+ if mo:
+ return mo.group(1)
+
+ # OTHERWISE, A REGULAR VERB (HANDLE ELSEWHERE)
+
+ return False
+
+ def _pl_general_verb(
+ self, word: str, count: Optional[Union[str, int]] = None
+ ) -> str:
+ count = self.get_count(count)
+
+ if count == 1:
+ return word
+
+ # HANDLE AMBIGUOUS PRESENT TENSES (SIMPLE AND COMPOUND)
+
+ mo = plverb_ambiguous_pres_keys.search(word)
+ if mo:
+ return f"{plverb_ambiguous_pres[mo.group(1).lower()]}{mo.group(2)}"
+
+ # HANDLE AMBIGUOUS PRETERITE AND PERFECT TENSES
+
+ mo = plverb_ambiguous_non_pres.search(word)
+ if mo:
+ return word
+
+ # OTHERWISE, 1st OR 2ND PERSON IS UNINFLECTED
+
+ return word
+
+ def _pl_special_adjective(
+ self, word: str, count: Optional[Union[str, int]] = None
+ ) -> Union[str, bool]:
+ count = self.get_count(count)
+
+ if count == 1:
+ return word
+
+ # HANDLE USER-DEFINED ADJECTIVES
+
+ value = self.ud_match(word, self.pl_adj_user_defined)
+ if value is not None:
+ return value
+
+ # HANDLE KNOWN CASES
+
+ mo = pl_adj_special_keys.search(word)
+ if mo:
+ return pl_adj_special[mo.group(1).lower()]
+
+ # HANDLE POSSESSIVES
+
+ mo = pl_adj_poss_keys.search(word)
+ if mo:
+ return pl_adj_poss[mo.group(1).lower()]
+
+ mo = ENDS_WITH_APOSTROPHE_S.search(word)
+ if mo:
+ pl = self.plural_noun(mo.group(1))
+ trailing_s = "" if pl[-1] == "s" else "s"
+ return f"{pl}'{trailing_s}"
+
+ # OTHERWISE, NO IDEA
+
+ return False
+
+ # @profile
+ def _sinoun( # noqa: C901
+ self,
+ word: str,
+ count: Optional[Union[str, int]] = None,
+ gender: Optional[str] = None,
+ ) -> Union[str, bool]:
+ count = self.get_count(count)
+
+ # DEFAULT TO PLURAL
+
+ if count == 2:
+ return word
+
+ # SET THE GENDER
+
+ try:
+ if gender is None:
+ gender = self.thegender
+ elif gender not in singular_pronoun_genders:
+ raise BadGenderError
+ except (TypeError, IndexError) as err:
+ raise BadGenderError from err
+
+ # HANDLE USER-DEFINED NOUNS
+
+ value = self.ud_match(word, self.si_sb_user_defined)
+ if value is not None:
+ return value
+
+ # HANDLE EMPTY WORD, SINGULAR COUNT AND UNINFLECTED PLURALS
+
+ if word == "":
+ return word
+
+ if word in si_sb_ois_oi_case:
+ return word[:-1]
+
+ words = Words(word)
+
+ if words.last.lower() in pl_sb_uninflected_complete:
+ if len(words.split_) >= 3:
+ return self._handle_long_compounds(words, count=1) or word
+ return word
+
+ if word in pl_sb_uninflected_caps:
+ return word
+
+ for k, v in pl_sb_uninflected_bysize.items():
+ if words.lowered[-k:] in v:
+ return word
+
+ if self.classical_dict["herd"] and words.last.lower() in pl_sb_uninflected_herd:
+ return word
+
+ if words.last.lower() in pl_sb_C_us_us:
+ return word if self.classical_dict["ancient"] else False
+
+ # HANDLE COMPOUNDS ("Governor General", "mother-in-law", "aide-de-camp", ETC.)
+
+ mo = PL_SB_POSTFIX_ADJ_STEMS_RE.search(word)
+ if mo and mo.group(2) != "":
+ return f"{self._sinoun(mo.group(1), 1, gender=gender)}{mo.group(2)}"
+
+ with contextlib.suppress(ValueError):
+ return self._handle_prepositional_phrase(
+ words.lowered,
+ functools.partial(self._sinoun, count=1, gender=gender),
+ ' ',
+ )
+
+ with contextlib.suppress(ValueError):
+ return self._handle_prepositional_phrase(
+ words.lowered,
+ functools.partial(self._sinoun, count=1, gender=gender),
+ '-',
+ )
+
+ # HANDLE PRONOUNS
+
+ for k, v in si_pron_acc_keys_bysize.items():
+ if words.lowered[-k:] in v: # ends with accusative pronoun
+ for pk, pv in pl_prep_bysize.items():
+ if words.lowered[:pk] in pv: # starts with a prep
+ if words.lowered.split() == [
+ words.lowered[:pk],
+ words.lowered[-k:],
+ ]:
+ # only whitespace in between
+ return words.lowered[:-k] + get_si_pron(
+ "acc", words.lowered[-k:], gender
+ )
+
+ try:
+ return get_si_pron("nom", words.lowered, gender)
+ except KeyError:
+ pass
+
+ try:
+ return get_si_pron("acc", words.lowered, gender)
+ except KeyError:
+ pass
+
+ # HANDLE ISOLATED IRREGULAR PLURALS
+
+ if words.last in si_sb_irregular_caps:
+ llen = len(words.last)
+ return f"{word[:-llen]}{si_sb_irregular_caps[words.last]}"
+
+ if words.last.lower() in si_sb_irregular:
+ llen = len(words.last.lower())
+ return f"{word[:-llen]}{si_sb_irregular[words.last.lower()]}"
+
+ dash_split = words.lowered.split("-")
+ if (" ".join(dash_split[-2:])).lower() in si_sb_irregular_compound:
+ llen = len(
+ " ".join(dash_split[-2:])
+ ) # TODO: what if 2 spaces between these words?
+ return "{}{}".format(
+ word[:-llen],
+ si_sb_irregular_compound[(" ".join(dash_split[-2:])).lower()],
+ )
+
+ if words.lowered[-5:] == "quies":
+ return word[:-3] + "y"
+
+ if words.lowered[-7:] == "persons":
+ return word[:-1]
+ if words.lowered[-6:] == "people":
+ return word[:-4] + "rson"
+
+ # HANDLE FAMILIES OF IRREGULAR PLURALS
+
+ if words.lowered[-4:] == "mans":
+ for k, v in si_sb_U_man_mans_bysize.items():
+ if words.lowered[-k:] in v:
+ return word[:-1]
+ for k, v in si_sb_U_man_mans_caps_bysize.items():
+ if word[-k:] in v:
+ return word[:-1]
+ if words.lowered[-3:] == "men":
+ return word[:-3] + "man"
+ if words.lowered[-4:] == "mice":
+ return word[:-4] + "mouse"
+ if words.lowered[-4:] == "lice":
+ v = si_sb_U_louse_lice_bysize.get(len(word))
+ if v and words.lowered in v:
+ return word[:-4] + "louse"
+ if words.lowered[-5:] == "geese":
+ return word[:-5] + "goose"
+ if words.lowered[-5:] == "teeth":
+ return word[:-5] + "tooth"
+ if words.lowered[-4:] == "feet":
+ return word[:-4] + "foot"
+
+ if words.lowered == "dice":
+ return "die"
+
+ # HANDLE UNASSIMILATED IMPORTS
+
+ if words.lowered[-4:] == "ceps":
+ return word
+ if words.lowered[-3:] == "zoa":
+ return word[:-1] + "on"
+
+ for lastlet, d, unass_numend, post in (
+ ("s", si_sb_U_ch_chs_bysize, -1, ""),
+ ("s", si_sb_U_ex_ices_bysize, -4, "ex"),
+ ("s", si_sb_U_ix_ices_bysize, -4, "ix"),
+ ("a", si_sb_U_um_a_bysize, -1, "um"),
+ ("i", si_sb_U_us_i_bysize, -1, "us"),
+ ("a", si_sb_U_on_a_bysize, -1, "on"),
+ ("e", si_sb_U_a_ae_bysize, -1, ""),
+ ):
+ if words.lowered[-1] == lastlet: # this test to add speed
+ for k, v in d.items():
+ if words.lowered[-k:] in v:
+ return word[:unass_numend] + post
+
+ # HANDLE INCOMPLETELY ASSIMILATED IMPORTS
+
+ if self.classical_dict["ancient"]:
+ if words.lowered[-6:] == "trices":
+ return word[:-3] + "x"
+ if words.lowered[-4:] in ("eaux", "ieux"):
+ return word[:-1]
+ if words.lowered[-5:] in ("ynges", "inges", "anges") and len(word) > 6:
+ return word[:-3] + "x"
+
+ for lastlet, d, class_numend, post in (
+ ("a", si_sb_C_en_ina_bysize, -3, "en"),
+ ("s", si_sb_C_ex_ices_bysize, -4, "ex"),
+ ("s", si_sb_C_ix_ices_bysize, -4, "ix"),
+ ("a", si_sb_C_um_a_bysize, -1, "um"),
+ ("i", si_sb_C_us_i_bysize, -1, "us"),
+ ("s", pl_sb_C_us_us_bysize, None, ""),
+ ("e", si_sb_C_a_ae_bysize, -1, ""),
+ ("a", si_sb_C_a_ata_bysize, -2, ""),
+ ("s", si_sb_C_is_ides_bysize, -3, "s"),
+ ("i", si_sb_C_o_i_bysize, -1, "o"),
+ ("a", si_sb_C_on_a_bysize, -1, "on"),
+ ("m", si_sb_C_im_bysize, -2, ""),
+ ("i", si_sb_C_i_bysize, -1, ""),
+ ):
+ if words.lowered[-1] == lastlet: # this test to add speed
+ for k, v in d.items():
+ if words.lowered[-k:] in v:
+ return word[:class_numend] + post
+
+ # HANDLE PLURLS ENDING IN uses -> use
+
+ if (
+ words.lowered[-6:] == "houses"
+ or word in si_sb_uses_use_case
+ or words.last.lower() in si_sb_uses_use
+ ):
+ return word[:-1]
+
+ # HANDLE PLURLS ENDING IN ies -> ie
+
+ if word in si_sb_ies_ie_case or words.last.lower() in si_sb_ies_ie:
+ return word[:-1]
+
+ # HANDLE PLURLS ENDING IN oes -> oe
+
+ if (
+ words.lowered[-5:] == "shoes"
+ or word in si_sb_oes_oe_case
+ or words.last.lower() in si_sb_oes_oe
+ ):
+ return word[:-1]
+
+ # HANDLE SINGULAR NOUNS ENDING IN ...s OR OTHER SILIBANTS
+
+ if word in si_sb_sses_sse_case or words.last.lower() in si_sb_sses_sse:
+ return word[:-1]
+
+ if words.last.lower() in si_sb_singular_s_complete:
+ return word[:-2]
+
+ for k, v in si_sb_singular_s_bysize.items():
+ if words.lowered[-k:] in v:
+ return word[:-2]
+
+ if words.lowered[-4:] == "eses" and word[0] == word[0].upper():
+ return word[:-2]
+
+ if words.last.lower() in si_sb_z_zes:
+ return word[:-2]
+
+ if words.last.lower() in si_sb_zzes_zz:
+ return word[:-2]
+
+ if words.lowered[-4:] == "zzes":
+ return word[:-3]
+
+ if word in si_sb_ches_che_case or words.last.lower() in si_sb_ches_che:
+ return word[:-1]
+
+ if words.lowered[-4:] in ("ches", "shes"):
+ return word[:-2]
+
+ if words.last.lower() in si_sb_xes_xe:
+ return word[:-1]
+
+ if words.lowered[-3:] == "xes":
+ return word[:-2]
+
+ # HANDLE ...f -> ...ves
+
+ if word in si_sb_ves_ve_case or words.last.lower() in si_sb_ves_ve:
+ return word[:-1]
+
+ if words.lowered[-3:] == "ves":
+ if words.lowered[-5:-3] in ("el", "al", "ol"):
+ return word[:-3] + "f"
+ if words.lowered[-5:-3] == "ea" and word[-6:-5] != "d":
+ return word[:-3] + "f"
+ if words.lowered[-5:-3] in ("ni", "li", "wi"):
+ return word[:-3] + "fe"
+ if words.lowered[-5:-3] == "ar":
+ return word[:-3] + "f"
+
+ # HANDLE ...y
+
+ if words.lowered[-2:] == "ys":
+ if len(words.lowered) > 2 and words.lowered[-3] in "aeiou":
+ return word[:-1]
+
+ if self.classical_dict["names"]:
+ if words.lowered[-2:] == "ys" and word[0] == word[0].upper():
+ return word[:-1]
+
+ if words.lowered[-3:] == "ies":
+ return word[:-3] + "y"
+
+ # HANDLE ...o
+
+ if words.lowered[-2:] == "os":
+ if words.last.lower() in si_sb_U_o_os_complete:
+ return word[:-1]
+
+ for k, v in si_sb_U_o_os_bysize.items():
+ if words.lowered[-k:] in v:
+ return word[:-1]
+
+ if words.lowered[-3:] in ("aos", "eos", "ios", "oos", "uos"):
+ return word[:-1]
+
+ if words.lowered[-3:] == "oes":
+ return word[:-2]
+
+ # UNASSIMILATED IMPORTS FINAL RULE
+
+ if word in si_sb_es_is:
+ return word[:-2] + "is"
+
+ # OTHERWISE JUST REMOVE ...s
+
+ if words.lowered[-1] == "s":
+ return word[:-1]
+
+ # COULD NOT FIND SINGULAR
+
+ return False
+
+ # ADJECTIVES
+
+ @typechecked
+ def a(self, text: Word, count: Optional[Union[int, str, Any]] = 1) -> str:
+ """
+ Return the appropriate indefinite article followed by text.
+
+ The indefinite article is either 'a' or 'an'.
+
+ If count is not one, then return count followed by text
+ instead of 'a' or 'an'.
+
+ Whitespace at the start and end is preserved.
+
+ """
+ mo = INDEFINITE_ARTICLE_TEST.search(text)
+ if mo:
+ word = mo.group(2)
+ if not word:
+ return text
+ pre = mo.group(1)
+ post = mo.group(3)
+ result = self._indef_article(word, count)
+ return f"{pre}{result}{post}"
+ return ""
+
+ an = a
+
+ _indef_article_cases = (
+ # HANDLE ORDINAL FORMS
+ (A_ordinal_a, "a"),
+ (A_ordinal_an, "an"),
+ # HANDLE SPECIAL CASES
+ (A_explicit_an, "an"),
+ (SPECIAL_AN, "an"),
+ (SPECIAL_A, "a"),
+ # HANDLE ABBREVIATIONS
+ (A_abbrev, "an"),
+ (SPECIAL_ABBREV_AN, "an"),
+ (SPECIAL_ABBREV_A, "a"),
+ # HANDLE CONSONANTS
+ (CONSONANTS, "a"),
+ # HANDLE SPECIAL VOWEL-FORMS
+ (ARTICLE_SPECIAL_EU, "a"),
+ (ARTICLE_SPECIAL_ONCE, "a"),
+ (ARTICLE_SPECIAL_ONETIME, "a"),
+ (ARTICLE_SPECIAL_UNIT, "a"),
+ (ARTICLE_SPECIAL_UBA, "a"),
+ (ARTICLE_SPECIAL_UKR, "a"),
+ (A_explicit_a, "a"),
+ # HANDLE SPECIAL CAPITALS
+ (SPECIAL_CAPITALS, "a"),
+ # HANDLE VOWELS
+ (VOWELS, "an"),
+ # HANDLE y...
+ # (BEFORE CERTAIN CONSONANTS IMPLIES (UNNATURALIZED) "i.." SOUND)
+ (A_y_cons, "an"),
+ )
+
+ def _indef_article(self, word: str, count: Union[int, str, Any]) -> str:
+ mycount = self.get_count(count)
+
+ if mycount != 1:
+ return f"{count} {word}"
+
+ # HANDLE USER-DEFINED VARIANTS
+
+ value = self.ud_match(word, self.A_a_user_defined)
+ if value is not None:
+ return f"{value} {word}"
+
+ matches = (
+ f'{article} {word}'
+ for regexen, article in self._indef_article_cases
+ if regexen.search(word)
+ )
+
+ # OTHERWISE, GUESS "a"
+ fallback = f'a {word}'
+ return next(matches, fallback)
+
+ # 2. TRANSLATE ZERO-QUANTIFIED $word TO "no plural($word)"
+
+ @typechecked
+ def no(self, text: Word, count: Optional[Union[int, str]] = None) -> str:
+ """
+ If count is 0, no, zero or nil, return 'no' followed by the plural
+ of text.
+
+ If count is one of:
+ 1, a, an, one, each, every, this, that
+ return count followed by text.
+
+ Otherwise return count follow by the plural of text.
+
+ In the return value count is always followed by a space.
+
+ Whitespace at the start and end is preserved.
+
+ """
+ if count is None and self.persistent_count is not None:
+ count = self.persistent_count
+
+ if count is None:
+ count = 0
+ mo = PARTITION_WORD.search(text)
+ if mo:
+ pre = mo.group(1)
+ word = mo.group(2)
+ post = mo.group(3)
+ else:
+ pre = ""
+ word = ""
+ post = ""
+
+ if str(count).lower() in pl_count_zero:
+ count = 'no'
+ return f"{pre}{count} {self.plural(word, count)}{post}"
+
+ # PARTICIPLES
+
+ @typechecked
+ def present_participle(self, word: Word) -> str:
+ """
+ Return the present participle for word.
+
+ word is the 3rd person singular verb.
+
+ """
+ plv = self.plural_verb(word, 2)
+ ans = plv
+
+ for regexen, repl in PRESENT_PARTICIPLE_REPLACEMENTS:
+ ans, num = regexen.subn(repl, plv)
+ if num:
+ return f"{ans}ing"
+ return f"{ans}ing"
+
+ # NUMERICAL INFLECTIONS
+
+ @typechecked
+ def ordinal(self, num: Union[Number, Word]) -> str:
+ """
+ Return the ordinal of num.
+
+ >>> ordinal = engine().ordinal
+ >>> ordinal(1)
+ '1st'
+ >>> ordinal('one')
+ 'first'
+ """
+ if DIGIT.match(str(num)):
+ if isinstance(num, (float, int)) and int(num) == num:
+ n = int(num)
+ else:
+ if "." in str(num):
+ try:
+ # numbers after decimal,
+ # so only need last one for ordinal
+ n = int(str(num)[-1])
+
+ except ValueError: # ends with '.', so need to use whole string
+ n = int(str(num)[:-1])
+ else:
+ n = int(num) # type: ignore
+ try:
+ post = nth[n % 100]
+ except KeyError:
+ post = nth[n % 10]
+ return f"{num}{post}"
+ else:
+ return self._sub_ord(num)
+
+ def millfn(self, ind: int = 0) -> str:
+ if ind > len(mill) - 1:
+ raise NumOutOfRangeError
+ return mill[ind]
+
+ def unitfn(self, units: int, mindex: int = 0) -> str:
+ return f"{unit[units]}{self.millfn(mindex)}"
+
+ def tenfn(self, tens, units, mindex=0) -> str:
+ if tens != 1:
+ tens_part = ten[tens]
+ if tens and units:
+ hyphen = "-"
+ else:
+ hyphen = ""
+ unit_part = unit[units]
+ mill_part = self.millfn(mindex)
+ return f"{tens_part}{hyphen}{unit_part}{mill_part}"
+ return f"{teen[units]}{mill[mindex]}"
+
+ def hundfn(self, hundreds: int, tens: int, units: int, mindex: int) -> str:
+ if hundreds:
+ andword = f" {self._number_args['andword']} " if tens or units else ""
+ # use unit not unitfn as simpler
+ return (
+ f"{unit[hundreds]} hundred{andword}"
+ f"{self.tenfn(tens, units)}{self.millfn(mindex)}, "
+ )
+ if tens or units:
+ return f"{self.tenfn(tens, units)}{self.millfn(mindex)}, "
+ return ""
+
+ def group1sub(self, mo: Match) -> str:
+ units = int(mo.group(1))
+ if units == 1:
+ return f" {self._number_args['one']}, "
+ elif units:
+ return f"{unit[units]}, "
+ else:
+ return f" {self._number_args['zero']}, "
+
+ def group1bsub(self, mo: Match) -> str:
+ units = int(mo.group(1))
+ if units:
+ return f"{unit[units]}, "
+ else:
+ return f" {self._number_args['zero']}, "
+
+ def group2sub(self, mo: Match) -> str:
+ tens = int(mo.group(1))
+ units = int(mo.group(2))
+ if tens:
+ return f"{self.tenfn(tens, units)}, "
+ if units:
+ return f" {self._number_args['zero']} {unit[units]}, "
+ return f" {self._number_args['zero']} {self._number_args['zero']}, "
+
+ def group3sub(self, mo: Match) -> str:
+ hundreds = int(mo.group(1))
+ tens = int(mo.group(2))
+ units = int(mo.group(3))
+ if hundreds == 1:
+ hunword = f" {self._number_args['one']}"
+ elif hundreds:
+ hunword = str(unit[hundreds])
+ else:
+ hunword = f" {self._number_args['zero']}"
+ if tens:
+ tenword = self.tenfn(tens, units)
+ elif units:
+ tenword = f" {self._number_args['zero']} {unit[units]}"
+ else:
+ tenword = f" {self._number_args['zero']} {self._number_args['zero']}"
+ return f"{hunword} {tenword}, "
+
+ def hundsub(self, mo: Match) -> str:
+ ret = self.hundfn(
+ int(mo.group(1)), int(mo.group(2)), int(mo.group(3)), self.mill_count
+ )
+ self.mill_count += 1
+ return ret
+
+ def tensub(self, mo: Match) -> str:
+ return f"{self.tenfn(int(mo.group(1)), int(mo.group(2)), self.mill_count)}, "
+
+ def unitsub(self, mo: Match) -> str:
+ return f"{self.unitfn(int(mo.group(1)), self.mill_count)}, "
+
+ def enword(self, num: str, group: int) -> str:
+ # import pdb
+ # pdb.set_trace()
+
+ if group == 1:
+ num = DIGIT_GROUP.sub(self.group1sub, num)
+ elif group == 2:
+ num = TWO_DIGITS.sub(self.group2sub, num)
+ num = DIGIT_GROUP.sub(self.group1bsub, num, 1)
+ elif group == 3:
+ num = THREE_DIGITS.sub(self.group3sub, num)
+ num = TWO_DIGITS.sub(self.group2sub, num, 1)
+ num = DIGIT_GROUP.sub(self.group1sub, num, 1)
+ elif int(num) == 0:
+ num = self._number_args["zero"]
+ elif int(num) == 1:
+ num = self._number_args["one"]
+ else:
+ num = num.lstrip().lstrip("0")
+ self.mill_count = 0
+ # surely there's a better way to do the next bit
+ mo = THREE_DIGITS_WORD.search(num)
+ while mo:
+ num = THREE_DIGITS_WORD.sub(self.hundsub, num, 1)
+ mo = THREE_DIGITS_WORD.search(num)
+ num = TWO_DIGITS_WORD.sub(self.tensub, num, 1)
+ num = ONE_DIGIT_WORD.sub(self.unitsub, num, 1)
+ return num
+
+ @staticmethod
+ def _sub_ord(val):
+ new = ordinal_suff.sub(lambda match: ordinal[match.group(1)], val)
+ return new + "th" * (new == val)
+
+ @classmethod
+ def _chunk_num(cls, num, decimal, group):
+ if decimal:
+ max_split = -1 if group != 0 else 1
+ chunks = num.split(".", max_split)
+ else:
+ chunks = [num]
+ return cls._remove_last_blank(chunks)
+
+ @staticmethod
+ def _remove_last_blank(chunks):
+ """
+ Remove the last item from chunks if it's a blank string.
+
+ Return the resultant chunks and whether the last item was removed.
+ """
+ removed = chunks[-1] == ""
+ result = chunks[:-1] if removed else chunks
+ return result, removed
+
+ @staticmethod
+ def _get_sign(num):
+ return {'+': 'plus', '-': 'minus'}.get(num.lstrip()[0], '')
+
+ @typechecked
+ def number_to_words( # noqa: C901
+ self,
+ num: Union[Number, Word],
+ wantlist: bool = False,
+ group: int = 0,
+ comma: Union[Falsish, str] = ",",
+ andword: str = "and",
+ zero: str = "zero",
+ one: str = "one",
+ decimal: Union[Falsish, str] = "point",
+ threshold: Optional[int] = None,
+ ) -> Union[str, List[str]]:
+ """
+ Return a number in words.
+
+ group = 1, 2 or 3 to group numbers before turning into words
+ comma: define comma
+
+ andword:
+ word for 'and'. Can be set to ''.
+ e.g. "one hundred and one" vs "one hundred one"
+
+ zero: word for '0'
+ one: word for '1'
+ decimal: word for decimal point
+ threshold: numbers above threshold not turned into words
+
+ parameters not remembered from last call. Departure from Perl version.
+ """
+ self._number_args = {"andword": andword, "zero": zero, "one": one}
+ num = str(num)
+
+ # Handle "stylistic" conversions (up to a given threshold)...
+ if threshold is not None and float(num) > threshold:
+ spnum = num.split(".", 1)
+ while comma:
+ (spnum[0], n) = FOUR_DIGIT_COMMA.subn(r"\1,\2", spnum[0])
+ if n == 0:
+ break
+ try:
+ return f"{spnum[0]}.{spnum[1]}"
+ except IndexError:
+ return str(spnum[0])
+
+ if group < 0 or group > 3:
+ raise BadChunkingOptionError
+
+ sign = self._get_sign(num)
+
+ if num in nth_suff:
+ num = zero
+
+ myord = num[-2:] in nth_suff
+ if myord:
+ num = num[:-2]
+
+ chunks, finalpoint = self._chunk_num(num, decimal, group)
+
+ loopstart = chunks[0] == ""
+ first: bool | None = not loopstart
+
+ def _handle_chunk(chunk):
+ nonlocal first
+
+ # remove all non numeric \D
+ chunk = NON_DIGIT.sub("", chunk)
+ if chunk == "":
+ chunk = "0"
+
+ if group == 0 and not first:
+ chunk = self.enword(chunk, 1)
+ else:
+ chunk = self.enword(chunk, group)
+
+ if chunk[-2:] == ", ":
+ chunk = chunk[:-2]
+ chunk = WHITESPACES_COMMA.sub(",", chunk)
+
+ if group == 0 and first:
+ chunk = COMMA_WORD.sub(f" {andword} \\1", chunk)
+ chunk = WHITESPACES.sub(" ", chunk)
+ # chunk = re.sub(r"(\A\s|\s\Z)", self.blankfn, chunk)
+ chunk = chunk.strip()
+ if first:
+ first = None
+ return chunk
+
+ chunks[loopstart:] = map(_handle_chunk, chunks[loopstart:])
+
+ numchunks = []
+ if first != 0:
+ numchunks = chunks[0].split(f"{comma} ")
+
+ if myord and numchunks:
+ numchunks[-1] = self._sub_ord(numchunks[-1])
+
+ for chunk in chunks[1:]:
+ numchunks.append(decimal)
+ numchunks.extend(chunk.split(f"{comma} "))
+
+ if finalpoint:
+ numchunks.append(decimal)
+
+ if wantlist:
+ return [sign] * bool(sign) + numchunks
+
+ signout = f"{sign} " if sign else ""
+ valout = (
+ ', '.join(numchunks)
+ if group
+ else ''.join(self._render(numchunks, decimal, comma))
+ )
+ return signout + valout
+
+ @staticmethod
+ def _render(chunks, decimal, comma):
+ first_item = chunks.pop(0)
+ yield first_item
+ first = decimal is None or not first_item.endswith(decimal)
+ for nc in chunks:
+ if nc == decimal:
+ first = False
+ elif first:
+ yield comma
+ yield f" {nc}"
+
+ @typechecked
+ def join(
+ self,
+ words: Optional[Sequence[Word]],
+ sep: Optional[str] = None,
+ sep_spaced: bool = True,
+ final_sep: Optional[str] = None,
+ conj: str = "and",
+ conj_spaced: bool = True,
+ ) -> str:
+ """
+ Join words into a list.
+
+ e.g. join(['ant', 'bee', 'fly']) returns 'ant, bee, and fly'
+
+ options:
+ conj: replacement for 'and'
+ sep: separator. default ',', unless ',' is in the list then ';'
+ final_sep: final separator. default ',', unless ',' is in the list then ';'
+ conj_spaced: boolean. Should conj have spaces around it
+
+ """
+ if not words:
+ return ""
+ if len(words) == 1:
+ return words[0]
+
+ if conj_spaced:
+ if conj == "":
+ conj = " "
+ else:
+ conj = f" {conj} "
+
+ if len(words) == 2:
+ return f"{words[0]}{conj}{words[1]}"
+
+ if sep is None:
+ if "," in "".join(words):
+ sep = ";"
+ else:
+ sep = ","
+ if final_sep is None:
+ final_sep = sep
+
+ final_sep = f"{final_sep}{conj}"
+
+ if sep_spaced:
+ sep += " "
+
+ return f"{sep.join(words[0:-1])}{final_sep}{words[-1]}"
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..c7da2f4
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/compat/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/compat/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/compat/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/compat/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..e12ff96
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/compat/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/compat/__pycache__/py38.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/compat/__pycache__/py38.cpython-312.pyc
new file mode 100644
index 0000000..119a6b6
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/compat/__pycache__/py38.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/compat/py38.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/compat/py38.py
new file mode 100644
index 0000000..a2d01bd
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/compat/py38.py
@@ -0,0 +1,7 @@
+import sys
+
+
+if sys.version_info > (3, 9):
+ from typing import Annotated
+else: # pragma: no cover
+ from typing_extensions import Annotated # noqa: F401
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/py.typed b/testcline/lib/python3.12/site-packages/setuptools/_vendor/inflect/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/LICENSE
new file mode 100644
index 0000000..1bb5a44
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/LICENSE
@@ -0,0 +1,17 @@
+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/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/METADATA b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/METADATA
new file mode 100644
index 0000000..fe6ca5a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/METADATA
@@ -0,0 +1,85 @@
+Metadata-Version: 2.1
+Name: jaraco.collections
+Version: 5.1.0
+Summary: Collection objects similar to those in stdlib by jaraco
+Author-email: "Jason R. Coombs"
+Project-URL: Source, https://github.com/jaraco/jaraco.collections
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+Requires-Python: >=3.8
+Description-Content-Type: text/x-rst
+License-File: LICENSE
+Requires-Dist: jaraco.text
+Provides-Extra: check
+Requires-Dist: pytest-checkdocs >=2.4 ; extra == 'check'
+Requires-Dist: pytest-ruff >=0.2.1 ; (sys_platform != "cygwin") and extra == 'check'
+Provides-Extra: cover
+Requires-Dist: pytest-cov ; extra == 'cover'
+Provides-Extra: doc
+Requires-Dist: sphinx >=3.5 ; extra == 'doc'
+Requires-Dist: jaraco.packaging >=9.3 ; extra == 'doc'
+Requires-Dist: rst.linker >=1.9 ; extra == 'doc'
+Requires-Dist: furo ; extra == 'doc'
+Requires-Dist: sphinx-lint ; extra == 'doc'
+Requires-Dist: jaraco.tidelift >=1.4 ; extra == 'doc'
+Provides-Extra: enabler
+Requires-Dist: pytest-enabler >=2.2 ; extra == 'enabler'
+Provides-Extra: test
+Requires-Dist: pytest !=8.1.*,>=6 ; extra == 'test'
+Provides-Extra: type
+Requires-Dist: pytest-mypy ; extra == 'type'
+
+.. image:: https://img.shields.io/pypi/v/jaraco.collections.svg
+ :target: https://pypi.org/project/jaraco.collections
+
+.. image:: https://img.shields.io/pypi/pyversions/jaraco.collections.svg
+
+.. image:: https://github.com/jaraco/jaraco.collections/actions/workflows/main.yml/badge.svg
+ :target: https://github.com/jaraco/jaraco.collections/actions?query=workflow%3A%22tests%22
+ :alt: tests
+
+.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+ :target: https://github.com/astral-sh/ruff
+ :alt: Ruff
+
+.. image:: https://readthedocs.org/projects/jaracocollections/badge/?version=latest
+ :target: https://jaracocollections.readthedocs.io/en/latest/?badge=latest
+
+.. image:: https://img.shields.io/badge/skeleton-2024-informational
+ :target: https://blog.jaraco.com/skeleton
+
+.. image:: https://tidelift.com/badges/package/pypi/jaraco.collections
+ :target: https://tidelift.com/subscription/pkg/pypi-jaraco.collections?utm_source=pypi-jaraco.collections&utm_medium=readme
+
+Models and classes to supplement the stdlib 'collections' module.
+
+See the docs, linked above, for descriptions and usage examples.
+
+Highlights include:
+
+- RangeMap: A mapping that accepts a range of values for keys.
+- Projection: A subset over an existing mapping.
+- KeyTransformingDict: Generalized mapping with keys transformed by a function.
+- FoldedCaseKeyedDict: A dict whose string keys are case-insensitive.
+- BijectiveMap: A map where keys map to values and values back to their keys.
+- ItemsAsAttributes: A mapping mix-in exposing items as attributes.
+- IdentityOverrideMap: A map whose keys map by default to themselves unless overridden.
+- FrozenDict: A hashable, immutable map.
+- Enumeration: An object whose keys are enumerated.
+- Everything: A container that contains all things.
+- Least, Greatest: Objects that are always less than or greater than any other.
+- pop_all: Return all items from the mutable sequence and remove them from that sequence.
+- DictStack: A stack of dicts, great for sharing scopes.
+- WeightedLookup: A specialized RangeMap for selecting an item by weights.
+
+For Enterprise
+==============
+
+Available as part of the Tidelift Subscription.
+
+This project 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 `_.
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/RECORD b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/RECORD
new file mode 100644
index 0000000..48b957e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/RECORD
@@ -0,0 +1,10 @@
+jaraco.collections-5.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+jaraco.collections-5.1.0.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+jaraco.collections-5.1.0.dist-info/METADATA,sha256=IMUaliNsA5X1Ox9MXUWOagch5R4Wwb_3M7erp29dBtg,3933
+jaraco.collections-5.1.0.dist-info/RECORD,,
+jaraco.collections-5.1.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+jaraco.collections-5.1.0.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
+jaraco.collections-5.1.0.dist-info/top_level.txt,sha256=0JnN3LfXH4LIRfXL-QFOGCJzQWZO3ELx4R1d_louoQM,7
+jaraco/collections/__init__.py,sha256=Pc1-SqjWm81ad1P0-GttpkwO_LWlnaY6gUq8gcKh2v0,26640
+jaraco/collections/__pycache__/__init__.cpython-312.pyc,,
+jaraco/collections/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/REQUESTED b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/REQUESTED
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/WHEEL
new file mode 100644
index 0000000..50e1e84
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: setuptools (73.0.1)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/top_level.txt
new file mode 100644
index 0000000..f6205a5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.collections-5.1.0.dist-info/top_level.txt
@@ -0,0 +1 @@
+jaraco
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/LICENSE
new file mode 100644
index 0000000..1bb5a44
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/LICENSE
@@ -0,0 +1,17 @@
+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/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/METADATA b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/METADATA
new file mode 100644
index 0000000..a36f7c5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/METADATA
@@ -0,0 +1,75 @@
+Metadata-Version: 2.1
+Name: jaraco.context
+Version: 5.3.0
+Summary: Useful decorators and context managers
+Home-page: https://github.com/jaraco/jaraco.context
+Author: Jason R. Coombs
+Author-email: jaraco@jaraco.com
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+Requires-Python: >=3.8
+License-File: LICENSE
+Requires-Dist: backports.tarfile ; python_version < "3.12"
+Provides-Extra: docs
+Requires-Dist: sphinx >=3.5 ; extra == 'docs'
+Requires-Dist: jaraco.packaging >=9.3 ; extra == 'docs'
+Requires-Dist: rst.linker >=1.9 ; extra == 'docs'
+Requires-Dist: furo ; extra == 'docs'
+Requires-Dist: sphinx-lint ; extra == 'docs'
+Requires-Dist: jaraco.tidelift >=1.4 ; extra == 'docs'
+Provides-Extra: testing
+Requires-Dist: pytest !=8.1.1,>=6 ; extra == 'testing'
+Requires-Dist: pytest-checkdocs >=2.4 ; extra == 'testing'
+Requires-Dist: pytest-cov ; extra == 'testing'
+Requires-Dist: pytest-mypy ; extra == 'testing'
+Requires-Dist: pytest-enabler >=2.2 ; extra == 'testing'
+Requires-Dist: pytest-ruff >=0.2.1 ; extra == 'testing'
+Requires-Dist: portend ; extra == 'testing'
+
+.. image:: https://img.shields.io/pypi/v/jaraco.context.svg
+ :target: https://pypi.org/project/jaraco.context
+
+.. image:: https://img.shields.io/pypi/pyversions/jaraco.context.svg
+
+.. image:: https://github.com/jaraco/jaraco.context/actions/workflows/main.yml/badge.svg
+ :target: https://github.com/jaraco/jaraco.context/actions?query=workflow%3A%22tests%22
+ :alt: tests
+
+.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+ :target: https://github.com/astral-sh/ruff
+ :alt: Ruff
+
+.. image:: https://readthedocs.org/projects/jaracocontext/badge/?version=latest
+ :target: https://jaracocontext.readthedocs.io/en/latest/?badge=latest
+
+.. image:: https://img.shields.io/badge/skeleton-2024-informational
+ :target: https://blog.jaraco.com/skeleton
+
+.. image:: https://tidelift.com/badges/package/pypi/jaraco.context
+ :target: https://tidelift.com/subscription/pkg/pypi-jaraco.context?utm_source=pypi-jaraco.context&utm_medium=readme
+
+
+Highlights
+==========
+
+See the docs linked from the badge above for the full details, but here are some features that may be of interest.
+
+- ``ExceptionTrap`` provides a general-purpose wrapper for trapping exceptions and then acting on the outcome. Includes ``passes`` and ``raises`` decorators to replace the result of a wrapped function by a boolean indicating the outcome of the exception trap. See `this keyring commit `_ for an example of it in production.
+- ``suppress`` simply enables ``contextlib.suppress`` as a decorator.
+- ``on_interrupt`` is a decorator used by CLI entry points to affect the handling of a ``KeyboardInterrupt``. Inspired by `Lucretiel/autocommand#18 `_.
+- ``pushd`` is similar to pytest's ``monkeypatch.chdir`` or path's `default context `_, changes the current working directory for the duration of the context.
+- ``tarball`` will download a tarball, extract it, change directory, yield, then clean up after. Convenient when working with web assets.
+- ``null`` is there for those times when one code branch needs a context and the other doesn't; this null context provides symmetry across those branches.
+
+
+For Enterprise
+==============
+
+Available as part of the Tidelift Subscription.
+
+This project 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 `_.
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/RECORD b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/RECORD
new file mode 100644
index 0000000..09d191f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/RECORD
@@ -0,0 +1,8 @@
+jaraco.context-5.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+jaraco.context-5.3.0.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+jaraco.context-5.3.0.dist-info/METADATA,sha256=xDtguJej0tN9iEXCUvxEJh2a7xceIRVBEakBLSr__tY,4020
+jaraco.context-5.3.0.dist-info/RECORD,,
+jaraco.context-5.3.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+jaraco.context-5.3.0.dist-info/top_level.txt,sha256=0JnN3LfXH4LIRfXL-QFOGCJzQWZO3ELx4R1d_louoQM,7
+jaraco/__pycache__/context.cpython-312.pyc,,
+jaraco/context.py,sha256=REoLIxDkO5MfEYowt_WoupNCRoxBS5v7YX2PbW8lIcs,9552
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/WHEEL
new file mode 100644
index 0000000..bab98d6
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.43.0)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/top_level.txt
new file mode 100644
index 0000000..f6205a5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.context-5.3.0.dist-info/top_level.txt
@@ -0,0 +1 @@
+jaraco
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/LICENSE
new file mode 100644
index 0000000..1bb5a44
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/LICENSE
@@ -0,0 +1,17 @@
+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/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/METADATA b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/METADATA
new file mode 100644
index 0000000..c865140
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/METADATA
@@ -0,0 +1,64 @@
+Metadata-Version: 2.1
+Name: jaraco.functools
+Version: 4.0.1
+Summary: Functools like those found in stdlib
+Author-email: "Jason R. Coombs"
+Project-URL: Homepage, https://github.com/jaraco/jaraco.functools
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+Requires-Python: >=3.8
+Description-Content-Type: text/x-rst
+License-File: LICENSE
+Requires-Dist: more-itertools
+Provides-Extra: docs
+Requires-Dist: sphinx >=3.5 ; extra == 'docs'
+Requires-Dist: sphinx <7.2.5 ; extra == 'docs'
+Requires-Dist: jaraco.packaging >=9.3 ; extra == 'docs'
+Requires-Dist: rst.linker >=1.9 ; extra == 'docs'
+Requires-Dist: furo ; extra == 'docs'
+Requires-Dist: sphinx-lint ; extra == 'docs'
+Requires-Dist: jaraco.tidelift >=1.4 ; extra == 'docs'
+Provides-Extra: testing
+Requires-Dist: pytest >=6 ; extra == 'testing'
+Requires-Dist: pytest-checkdocs >=2.4 ; extra == 'testing'
+Requires-Dist: pytest-cov ; extra == 'testing'
+Requires-Dist: pytest-enabler >=2.2 ; extra == 'testing'
+Requires-Dist: pytest-ruff >=0.2.1 ; extra == 'testing'
+Requires-Dist: jaraco.classes ; extra == 'testing'
+Requires-Dist: pytest-mypy ; (platform_python_implementation != "PyPy") and extra == 'testing'
+
+.. image:: https://img.shields.io/pypi/v/jaraco.functools.svg
+ :target: https://pypi.org/project/jaraco.functools
+
+.. image:: https://img.shields.io/pypi/pyversions/jaraco.functools.svg
+
+.. image:: https://github.com/jaraco/jaraco.functools/actions/workflows/main.yml/badge.svg
+ :target: https://github.com/jaraco/jaraco.functools/actions?query=workflow%3A%22tests%22
+ :alt: tests
+
+.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+ :target: https://github.com/astral-sh/ruff
+ :alt: Ruff
+
+.. image:: https://readthedocs.org/projects/jaracofunctools/badge/?version=latest
+ :target: https://jaracofunctools.readthedocs.io/en/latest/?badge=latest
+
+.. image:: https://img.shields.io/badge/skeleton-2024-informational
+ :target: https://blog.jaraco.com/skeleton
+
+.. image:: https://tidelift.com/badges/package/pypi/jaraco.functools
+ :target: https://tidelift.com/subscription/pkg/pypi-jaraco.functools?utm_source=pypi-jaraco.functools&utm_medium=readme
+
+Additional functools in the spirit of stdlib's functools.
+
+For Enterprise
+==============
+
+Available as part of the Tidelift Subscription.
+
+This project 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 `_.
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/RECORD b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/RECORD
new file mode 100644
index 0000000..ef3bc21
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/RECORD
@@ -0,0 +1,10 @@
+jaraco.functools-4.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+jaraco.functools-4.0.1.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+jaraco.functools-4.0.1.dist-info/METADATA,sha256=i4aUaQDX-jjdEQK5wevhegyx8JyLfin2HyvaSk3FHso,2891
+jaraco.functools-4.0.1.dist-info/RECORD,,
+jaraco.functools-4.0.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+jaraco.functools-4.0.1.dist-info/top_level.txt,sha256=0JnN3LfXH4LIRfXL-QFOGCJzQWZO3ELx4R1d_louoQM,7
+jaraco/functools/__init__.py,sha256=hEAJaS2uSZRuF_JY4CxCHIYh79ZpxaPp9OiHyr9EJ1w,16642
+jaraco/functools/__init__.pyi,sha256=gk3dsgHzo5F_U74HzAvpNivFAPCkPJ1b2-yCd62dfnw,3878
+jaraco/functools/__pycache__/__init__.cpython-312.pyc,,
+jaraco/functools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/WHEEL
new file mode 100644
index 0000000..bab98d6
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.43.0)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/top_level.txt
new file mode 100644
index 0000000..f6205a5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.functools-4.0.1.dist-info/top_level.txt
@@ -0,0 +1 @@
+jaraco
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/LICENSE
new file mode 100644
index 0000000..1bb5a44
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/LICENSE
@@ -0,0 +1,17 @@
+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/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/METADATA b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/METADATA
new file mode 100644
index 0000000..0258a38
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/METADATA
@@ -0,0 +1,95 @@
+Metadata-Version: 2.1
+Name: jaraco.text
+Version: 3.12.1
+Summary: Module for text manipulation
+Author-email: "Jason R. Coombs"
+Project-URL: Homepage, https://github.com/jaraco/jaraco.text
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+Requires-Python: >=3.8
+Description-Content-Type: text/x-rst
+License-File: LICENSE
+Requires-Dist: jaraco.functools
+Requires-Dist: jaraco.context >=4.1
+Requires-Dist: autocommand
+Requires-Dist: inflect
+Requires-Dist: more-itertools
+Requires-Dist: importlib-resources ; python_version < "3.9"
+Provides-Extra: doc
+Requires-Dist: sphinx >=3.5 ; extra == 'doc'
+Requires-Dist: jaraco.packaging >=9.3 ; extra == 'doc'
+Requires-Dist: rst.linker >=1.9 ; extra == 'doc'
+Requires-Dist: furo ; extra == 'doc'
+Requires-Dist: sphinx-lint ; extra == 'doc'
+Requires-Dist: jaraco.tidelift >=1.4 ; extra == 'doc'
+Provides-Extra: test
+Requires-Dist: pytest !=8.1.*,>=6 ; extra == 'test'
+Requires-Dist: pytest-checkdocs >=2.4 ; extra == 'test'
+Requires-Dist: pytest-cov ; extra == 'test'
+Requires-Dist: pytest-mypy ; extra == 'test'
+Requires-Dist: pytest-enabler >=2.2 ; extra == 'test'
+Requires-Dist: pytest-ruff >=0.2.1 ; extra == 'test'
+Requires-Dist: pathlib2 ; (python_version < "3.10") and extra == 'test'
+
+.. image:: https://img.shields.io/pypi/v/jaraco.text.svg
+ :target: https://pypi.org/project/jaraco.text
+
+.. image:: https://img.shields.io/pypi/pyversions/jaraco.text.svg
+
+.. image:: https://github.com/jaraco/jaraco.text/actions/workflows/main.yml/badge.svg
+ :target: https://github.com/jaraco/jaraco.text/actions?query=workflow%3A%22tests%22
+ :alt: tests
+
+.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+ :target: https://github.com/astral-sh/ruff
+ :alt: Ruff
+
+.. image:: https://readthedocs.org/projects/jaracotext/badge/?version=latest
+ :target: https://jaracotext.readthedocs.io/en/latest/?badge=latest
+
+.. image:: https://img.shields.io/badge/skeleton-2024-informational
+ :target: https://blog.jaraco.com/skeleton
+
+.. image:: https://tidelift.com/badges/package/pypi/jaraco.text
+ :target: https://tidelift.com/subscription/pkg/pypi-jaraco.text?utm_source=pypi-jaraco.text&utm_medium=readme
+
+
+This package provides handy routines for dealing with text, such as
+wrapping, substitution, trimming, stripping, prefix and suffix removal,
+line continuation, indentation, comment processing, identifier processing,
+values parsing, case insensitive comparison, and more. See the docs
+(linked in the badge above) for the detailed documentation and examples.
+
+Layouts
+=======
+
+One of the features of this package is the layouts module, which
+provides a simple example of translating keystrokes from one keyboard
+layout to another::
+
+ echo qwerty | python -m jaraco.text.to-dvorak
+ ',.pyf
+ echo "',.pyf" | python -m jaraco.text.to-qwerty
+ qwerty
+
+Newline Reporting
+=================
+
+Need to know what newlines appear in a file?
+
+::
+
+ $ python -m jaraco.text.show-newlines README.rst
+ newline is '\n'
+
+For Enterprise
+==============
+
+Available as part of the Tidelift Subscription.
+
+This project 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 `_.
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/RECORD b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/RECORD
new file mode 100644
index 0000000..19e2d84
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/RECORD
@@ -0,0 +1,20 @@
+jaraco.text-3.12.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+jaraco.text-3.12.1.dist-info/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
+jaraco.text-3.12.1.dist-info/METADATA,sha256=AzWdm6ViMfDOPoQMfLWn2zgBQSGJScyqeN29TcuWXVI,3658
+jaraco.text-3.12.1.dist-info/RECORD,,
+jaraco.text-3.12.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+jaraco.text-3.12.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
+jaraco.text-3.12.1.dist-info/top_level.txt,sha256=0JnN3LfXH4LIRfXL-QFOGCJzQWZO3ELx4R1d_louoQM,7
+jaraco/text/Lorem ipsum.txt,sha256=N_7c_79zxOufBY9HZ3yzMgOkNv-TkOTTio4BydrSjgs,1335
+jaraco/text/__init__.py,sha256=Y2YUqXR_orUoDaY4SkPRe6ZZhb5HUHB_Ah9RCNsVyho,16250
+jaraco/text/__pycache__/__init__.cpython-312.pyc,,
+jaraco/text/__pycache__/layouts.cpython-312.pyc,,
+jaraco/text/__pycache__/show-newlines.cpython-312.pyc,,
+jaraco/text/__pycache__/strip-prefix.cpython-312.pyc,,
+jaraco/text/__pycache__/to-dvorak.cpython-312.pyc,,
+jaraco/text/__pycache__/to-qwerty.cpython-312.pyc,,
+jaraco/text/layouts.py,sha256=HTC8aSTLZ7uXipyOXapRMC158juecjK6RVwitfmZ9_w,643
+jaraco/text/show-newlines.py,sha256=WGQa65e8lyhb92LUOLqVn6KaCtoeVgVws6WtSRmLk6w,904
+jaraco/text/strip-prefix.py,sha256=NfVXV8JVNo6nqcuYASfMV7_y4Eo8zMQqlCOGvAnRIVw,412
+jaraco/text/to-dvorak.py,sha256=1SNcbSsvISpXXg-LnybIHHY-RUFOQr36zcHkY1pWFqw,119
+jaraco/text/to-qwerty.py,sha256=s4UMQUnPwFn_dB5uZC27BurHOQcYondBfzIpVL5pEzw,119
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/REQUESTED b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/REQUESTED
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/WHEEL b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/WHEEL
new file mode 100644
index 0000000..bab98d6
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.43.0)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/top_level.txt b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/top_level.txt
new file mode 100644
index 0000000..f6205a5
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco.text-3.12.1.dist-info/top_level.txt
@@ -0,0 +1 @@
+jaraco
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/__pycache__/context.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/__pycache__/context.cpython-312.pyc
new file mode 100644
index 0000000..9123dac
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/__pycache__/context.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/collections/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/collections/__init__.py
new file mode 100644
index 0000000..0d501cf
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/collections/__init__.py
@@ -0,0 +1,1091 @@
+from __future__ import annotations
+
+import collections.abc
+import copy
+import functools
+import itertools
+import operator
+import random
+import re
+from collections.abc import Container, Iterable, Mapping
+from typing import TYPE_CHECKING, Any, Callable, Dict, TypeVar, Union, overload
+
+import jaraco.text
+
+if TYPE_CHECKING:
+ from _operator import _SupportsComparison
+
+ from _typeshed import SupportsKeysAndGetItem
+ from typing_extensions import Self
+
+ _RangeMapKT = TypeVar('_RangeMapKT', bound=_SupportsComparison)
+else:
+ # _SupportsComparison doesn't exist at runtime,
+ # but _RangeMapKT is used in RangeMap's superclass' type parameters
+ _RangeMapKT = TypeVar('_RangeMapKT')
+
+_T = TypeVar('_T')
+_VT = TypeVar('_VT')
+
+_Matchable = Union[Callable, Container, Iterable, re.Pattern]
+
+
+def _dispatch(obj: _Matchable) -> Callable:
+ # can't rely on singledispatch for Union[Container, Iterable]
+ # due to ambiguity
+ # (https://peps.python.org/pep-0443/#abstract-base-classes).
+ if isinstance(obj, re.Pattern):
+ return obj.fullmatch
+ # mypy issue: https://github.com/python/mypy/issues/11071
+ if not isinstance(obj, Callable): # type: ignore[arg-type]
+ if not isinstance(obj, Container):
+ obj = set(obj) # type: ignore[arg-type]
+ obj = obj.__contains__
+ return obj # type: ignore[return-value]
+
+
+class Projection(collections.abc.Mapping):
+ """
+ Project a set of keys over a mapping
+
+ >>> sample = {'a': 1, 'b': 2, 'c': 3}
+ >>> prj = Projection(['a', 'c', 'd'], sample)
+ >>> dict(prj)
+ {'a': 1, 'c': 3}
+
+ Projection also accepts an iterable or callable or pattern.
+
+ >>> iter_prj = Projection(iter('acd'), sample)
+ >>> call_prj = Projection(lambda k: ord(k) in (97, 99, 100), sample)
+ >>> pat_prj = Projection(re.compile(r'[acd]'), sample)
+ >>> prj == iter_prj == call_prj == pat_prj
+ True
+
+ Keys should only appear if they were specified and exist in the space.
+ Order is retained.
+
+ >>> list(prj)
+ ['a', 'c']
+
+ Attempting to access a key not in the projection
+ results in a KeyError.
+
+ >>> prj['b']
+ Traceback (most recent call last):
+ ...
+ KeyError: 'b'
+
+ Use the projection to update another dict.
+
+ >>> target = {'a': 2, 'b': 2}
+ >>> target.update(prj)
+ >>> target
+ {'a': 1, 'b': 2, 'c': 3}
+
+ Projection keeps a reference to the original dict, so
+ modifying the original dict may modify the Projection.
+
+ >>> del sample['a']
+ >>> dict(prj)
+ {'c': 3}
+ """
+
+ def __init__(self, keys: _Matchable, space: Mapping):
+ self._match = _dispatch(keys)
+ self._space = space
+
+ def __getitem__(self, key):
+ if not self._match(key):
+ raise KeyError(key)
+ return self._space[key]
+
+ def _keys_resolved(self):
+ return filter(self._match, self._space)
+
+ def __iter__(self):
+ return self._keys_resolved()
+
+ def __len__(self):
+ return len(tuple(self._keys_resolved()))
+
+
+class Mask(Projection):
+ """
+ The inverse of a :class:`Projection`, masking out keys.
+
+ >>> sample = {'a': 1, 'b': 2, 'c': 3}
+ >>> msk = Mask(['a', 'c', 'd'], sample)
+ >>> dict(msk)
+ {'b': 2}
+ """
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ # self._match = compose(operator.not_, self._match)
+ self._match = lambda key, orig=self._match: not orig(key)
+
+
+def dict_map(function, dictionary):
+ """
+ Return a new dict with function applied to values of dictionary.
+
+ >>> dict_map(lambda x: x+1, dict(a=1, b=2))
+ {'a': 2, 'b': 3}
+ """
+ return dict((key, function(value)) for key, value in dictionary.items())
+
+
+class RangeMap(Dict[_RangeMapKT, _VT]):
+ """
+ A dictionary-like object that uses the keys as bounds for a range.
+ Inclusion of the value for that range is determined by the
+ key_match_comparator, which defaults to less-than-or-equal.
+ A value is returned for a key if it is the first key that matches in
+ the sorted list of keys.
+
+ One may supply keyword parameters to be passed to the sort function used
+ to sort keys (i.e. key, reverse) as sort_params.
+
+ Create a map that maps 1-3 -> 'a', 4-6 -> 'b'
+
+ >>> r = RangeMap({3: 'a', 6: 'b'}) # boy, that was easy
+ >>> r[1], r[2], r[3], r[4], r[5], r[6]
+ ('a', 'a', 'a', 'b', 'b', 'b')
+
+ Even float values should work so long as the comparison operator
+ supports it.
+
+ >>> r[4.5]
+ 'b'
+
+ Notice that the way rangemap is defined, it must be open-ended
+ on one side.
+
+ >>> r[0]
+ 'a'
+ >>> r[-1]
+ 'a'
+
+ One can close the open-end of the RangeMap by using undefined_value
+
+ >>> r = RangeMap({0: RangeMap.undefined_value, 3: 'a', 6: 'b'})
+ >>> r[0]
+ Traceback (most recent call last):
+ ...
+ KeyError: 0
+
+ One can get the first or last elements in the range by using RangeMap.Item
+
+ >>> last_item = RangeMap.Item(-1)
+ >>> r[last_item]
+ 'b'
+
+ .last_item is a shortcut for Item(-1)
+
+ >>> r[RangeMap.last_item]
+ 'b'
+
+ Sometimes it's useful to find the bounds for a RangeMap
+
+ >>> r.bounds()
+ (0, 6)
+
+ RangeMap supports .get(key, default)
+
+ >>> r.get(0, 'not found')
+ 'not found'
+
+ >>> r.get(7, 'not found')
+ 'not found'
+
+ One often wishes to define the ranges by their left-most values,
+ which requires use of sort params and a key_match_comparator.
+
+ >>> r = RangeMap({1: 'a', 4: 'b'},
+ ... sort_params=dict(reverse=True),
+ ... key_match_comparator=operator.ge)
+ >>> r[1], r[2], r[3], r[4], r[5], r[6]
+ ('a', 'a', 'a', 'b', 'b', 'b')
+
+ That wasn't nearly as easy as before, so an alternate constructor
+ is provided:
+
+ >>> r = RangeMap.left({1: 'a', 4: 'b', 7: RangeMap.undefined_value})
+ >>> r[1], r[2], r[3], r[4], r[5], r[6]
+ ('a', 'a', 'a', 'b', 'b', 'b')
+
+ """
+
+ def __init__(
+ self,
+ source: (
+ SupportsKeysAndGetItem[_RangeMapKT, _VT] | Iterable[tuple[_RangeMapKT, _VT]]
+ ),
+ sort_params: Mapping[str, Any] = {},
+ key_match_comparator: Callable[[_RangeMapKT, _RangeMapKT], bool] = operator.le,
+ ):
+ dict.__init__(self, source)
+ self.sort_params = sort_params
+ self.match = key_match_comparator
+
+ @classmethod
+ def left(
+ cls,
+ source: (
+ SupportsKeysAndGetItem[_RangeMapKT, _VT] | Iterable[tuple[_RangeMapKT, _VT]]
+ ),
+ ) -> Self:
+ return cls(
+ source, sort_params=dict(reverse=True), key_match_comparator=operator.ge
+ )
+
+ def __getitem__(self, item: _RangeMapKT) -> _VT:
+ sorted_keys = sorted(self.keys(), **self.sort_params)
+ if isinstance(item, RangeMap.Item):
+ result = self.__getitem__(sorted_keys[item])
+ else:
+ key = self._find_first_match_(sorted_keys, item)
+ result = dict.__getitem__(self, key)
+ if result is RangeMap.undefined_value:
+ raise KeyError(key)
+ return result
+
+ @overload # type: ignore[override] # Signature simplified over dict and Mapping
+ def get(self, key: _RangeMapKT, default: _T) -> _VT | _T: ...
+ @overload
+ def get(self, key: _RangeMapKT, default: None = None) -> _VT | None: ...
+ def get(self, key: _RangeMapKT, default: _T | None = None) -> _VT | _T | None:
+ """
+ Return the value for key if key is in the dictionary, else default.
+ If default is not given, it defaults to None, so that this method
+ never raises a KeyError.
+ """
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ def _find_first_match_(
+ self, keys: Iterable[_RangeMapKT], item: _RangeMapKT
+ ) -> _RangeMapKT:
+ is_match = functools.partial(self.match, item)
+ matches = filter(is_match, keys)
+ try:
+ return next(matches)
+ except StopIteration:
+ raise KeyError(item) from None
+
+ def bounds(self) -> tuple[_RangeMapKT, _RangeMapKT]:
+ sorted_keys = sorted(self.keys(), **self.sort_params)
+ return (sorted_keys[RangeMap.first_item], sorted_keys[RangeMap.last_item])
+
+ # some special values for the RangeMap
+ undefined_value = type('RangeValueUndefined', (), {})()
+
+ class Item(int):
+ """RangeMap Item"""
+
+ first_item = Item(0)
+ last_item = Item(-1)
+
+
+def __identity(x):
+ return x
+
+
+def sorted_items(d, key=__identity, reverse=False):
+ """
+ Return the items of the dictionary sorted by the keys.
+
+ >>> sample = dict(foo=20, bar=42, baz=10)
+ >>> tuple(sorted_items(sample))
+ (('bar', 42), ('baz', 10), ('foo', 20))
+
+ >>> reverse_string = lambda s: ''.join(reversed(s))
+ >>> tuple(sorted_items(sample, key=reverse_string))
+ (('foo', 20), ('bar', 42), ('baz', 10))
+
+ >>> tuple(sorted_items(sample, reverse=True))
+ (('foo', 20), ('baz', 10), ('bar', 42))
+ """
+
+ # wrap the key func so it operates on the first element of each item
+ def pairkey_key(item):
+ return key(item[0])
+
+ return sorted(d.items(), key=pairkey_key, reverse=reverse)
+
+
+class KeyTransformingDict(dict):
+ """
+ A dict subclass that transforms the keys before they're used.
+ Subclasses may override the default transform_key to customize behavior.
+ """
+
+ @staticmethod
+ def transform_key(key): # pragma: nocover
+ return key
+
+ def __init__(self, *args, **kargs):
+ super().__init__()
+ # build a dictionary using the default constructs
+ d = dict(*args, **kargs)
+ # build this dictionary using transformed keys.
+ for item in d.items():
+ self.__setitem__(*item)
+
+ def __setitem__(self, key, val):
+ key = self.transform_key(key)
+ super().__setitem__(key, val)
+
+ def __getitem__(self, key):
+ key = self.transform_key(key)
+ return super().__getitem__(key)
+
+ def __contains__(self, key):
+ key = self.transform_key(key)
+ return super().__contains__(key)
+
+ def __delitem__(self, key):
+ key = self.transform_key(key)
+ return super().__delitem__(key)
+
+ def get(self, key, *args, **kwargs):
+ key = self.transform_key(key)
+ return super().get(key, *args, **kwargs)
+
+ def setdefault(self, key, *args, **kwargs):
+ key = self.transform_key(key)
+ return super().setdefault(key, *args, **kwargs)
+
+ def pop(self, key, *args, **kwargs):
+ key = self.transform_key(key)
+ return super().pop(key, *args, **kwargs)
+
+ def matching_key_for(self, key):
+ """
+ Given a key, return the actual key stored in self that matches.
+ Raise KeyError if the key isn't found.
+ """
+ try:
+ return next(e_key for e_key in self.keys() if e_key == key)
+ except StopIteration as err:
+ raise KeyError(key) from err
+
+
+class FoldedCaseKeyedDict(KeyTransformingDict):
+ """
+ A case-insensitive dictionary (keys are compared as insensitive
+ if they are strings).
+
+ >>> d = FoldedCaseKeyedDict()
+ >>> d['heLlo'] = 'world'
+ >>> list(d.keys()) == ['heLlo']
+ True
+ >>> list(d.values()) == ['world']
+ True
+ >>> d['hello'] == 'world'
+ True
+ >>> 'hello' in d
+ True
+ >>> 'HELLO' in d
+ True
+ >>> print(repr(FoldedCaseKeyedDict({'heLlo': 'world'})))
+ {'heLlo': 'world'}
+ >>> d = FoldedCaseKeyedDict({'heLlo': 'world'})
+ >>> print(d['hello'])
+ world
+ >>> print(d['Hello'])
+ world
+ >>> list(d.keys())
+ ['heLlo']
+ >>> d = FoldedCaseKeyedDict({'heLlo': 'world', 'Hello': 'world'})
+ >>> list(d.values())
+ ['world']
+ >>> key, = d.keys()
+ >>> key in ['heLlo', 'Hello']
+ True
+ >>> del d['HELLO']
+ >>> d
+ {}
+
+ get should work
+
+ >>> d['Sumthin'] = 'else'
+ >>> d.get('SUMTHIN')
+ 'else'
+ >>> d.get('OTHER', 'thing')
+ 'thing'
+ >>> del d['sumthin']
+
+ setdefault should also work
+
+ >>> d['This'] = 'that'
+ >>> print(d.setdefault('this', 'other'))
+ that
+ >>> len(d)
+ 1
+ >>> print(d['this'])
+ that
+ >>> print(d.setdefault('That', 'other'))
+ other
+ >>> print(d['THAT'])
+ other
+
+ Make it pop!
+
+ >>> print(d.pop('THAT'))
+ other
+
+ To retrieve the key in its originally-supplied form, use matching_key_for
+
+ >>> print(d.matching_key_for('this'))
+ This
+
+ >>> d.matching_key_for('missing')
+ Traceback (most recent call last):
+ ...
+ KeyError: 'missing'
+ """
+
+ @staticmethod
+ def transform_key(key):
+ return jaraco.text.FoldedCase(key)
+
+
+class DictAdapter:
+ """
+ Provide a getitem interface for attributes of an object.
+
+ Let's say you want to get at the string.lowercase property in a formatted
+ string. It's easy with DictAdapter.
+
+ >>> import string
+ >>> print("lowercase is %(ascii_lowercase)s" % DictAdapter(string))
+ lowercase is abcdefghijklmnopqrstuvwxyz
+ """
+
+ def __init__(self, wrapped_ob):
+ self.object = wrapped_ob
+
+ def __getitem__(self, name):
+ return getattr(self.object, name)
+
+
+class ItemsAsAttributes:
+ """
+ Mix-in class to enable a mapping object to provide items as
+ attributes.
+
+ >>> C = type('C', (dict, ItemsAsAttributes), dict())
+ >>> i = C()
+ >>> i['foo'] = 'bar'
+ >>> i.foo
+ 'bar'
+
+ Natural attribute access takes precedence
+
+ >>> i.foo = 'henry'
+ >>> i.foo
+ 'henry'
+
+ But as you might expect, the mapping functionality is preserved.
+
+ >>> i['foo']
+ 'bar'
+
+ A normal attribute error should be raised if an attribute is
+ requested that doesn't exist.
+
+ >>> i.missing
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'C' object has no attribute 'missing'
+
+ It also works on dicts that customize __getitem__
+
+ >>> missing_func = lambda self, key: 'missing item'
+ >>> C = type(
+ ... 'C',
+ ... (dict, ItemsAsAttributes),
+ ... dict(__missing__ = missing_func),
+ ... )
+ >>> i = C()
+ >>> i.missing
+ 'missing item'
+ >>> i.foo
+ 'missing item'
+ """
+
+ def __getattr__(self, key):
+ try:
+ return getattr(super(), key)
+ except AttributeError as e:
+ # attempt to get the value from the mapping (return self[key])
+ # but be careful not to lose the original exception context.
+ noval = object()
+
+ def _safe_getitem(cont, key, missing_result):
+ try:
+ return cont[key]
+ except KeyError:
+ return missing_result
+
+ result = _safe_getitem(self, key, noval)
+ if result is not noval:
+ return result
+ # raise the original exception, but use the original class
+ # name, not 'super'.
+ (message,) = e.args
+ message = message.replace('super', self.__class__.__name__, 1)
+ e.args = (message,)
+ raise
+
+
+def invert_map(map):
+ """
+ Given a dictionary, return another dictionary with keys and values
+ switched. If any of the values resolve to the same key, raises
+ a ValueError.
+
+ >>> numbers = dict(a=1, b=2, c=3)
+ >>> letters = invert_map(numbers)
+ >>> letters[1]
+ 'a'
+ >>> numbers['d'] = 3
+ >>> invert_map(numbers)
+ Traceback (most recent call last):
+ ...
+ ValueError: Key conflict in inverted mapping
+ """
+ res = dict((v, k) for k, v in map.items())
+ if not len(res) == len(map):
+ raise ValueError('Key conflict in inverted mapping')
+ return res
+
+
+class IdentityOverrideMap(dict):
+ """
+ A dictionary that by default maps each key to itself, but otherwise
+ acts like a normal dictionary.
+
+ >>> d = IdentityOverrideMap()
+ >>> d[42]
+ 42
+ >>> d['speed'] = 'speedo'
+ >>> print(d['speed'])
+ speedo
+ """
+
+ def __missing__(self, key):
+ return key
+
+
+class DictStack(list, collections.abc.MutableMapping):
+ """
+ A stack of dictionaries that behaves as a view on those dictionaries,
+ giving preference to the last.
+
+ >>> stack = DictStack([dict(a=1, c=2), dict(b=2, a=2)])
+ >>> stack['a']
+ 2
+ >>> stack['b']
+ 2
+ >>> stack['c']
+ 2
+ >>> len(stack)
+ 3
+ >>> stack.push(dict(a=3))
+ >>> stack['a']
+ 3
+ >>> stack['a'] = 4
+ >>> set(stack.keys()) == set(['a', 'b', 'c'])
+ True
+ >>> set(stack.items()) == set([('a', 4), ('b', 2), ('c', 2)])
+ True
+ >>> dict(**stack) == dict(stack) == dict(a=4, c=2, b=2)
+ True
+ >>> d = stack.pop()
+ >>> stack['a']
+ 2
+ >>> d = stack.pop()
+ >>> stack['a']
+ 1
+ >>> stack.get('b', None)
+ >>> 'c' in stack
+ True
+ >>> del stack['c']
+ >>> dict(stack)
+ {'a': 1}
+ """
+
+ def __iter__(self):
+ dicts = list.__iter__(self)
+ return iter(set(itertools.chain.from_iterable(c.keys() for c in dicts)))
+
+ def __getitem__(self, key):
+ for scope in reversed(tuple(list.__iter__(self))):
+ if key in scope:
+ return scope[key]
+ raise KeyError(key)
+
+ push = list.append
+
+ def __contains__(self, other):
+ return collections.abc.Mapping.__contains__(self, other)
+
+ def __len__(self):
+ return len(list(iter(self)))
+
+ def __setitem__(self, key, item):
+ last = list.__getitem__(self, -1)
+ return last.__setitem__(key, item)
+
+ def __delitem__(self, key):
+ last = list.__getitem__(self, -1)
+ return last.__delitem__(key)
+
+ # workaround for mypy confusion
+ def pop(self, *args, **kwargs):
+ return list.pop(self, *args, **kwargs)
+
+
+class BijectiveMap(dict):
+ """
+ A Bijective Map (two-way mapping).
+
+ Implemented as a simple dictionary of 2x the size, mapping values back
+ to keys.
+
+ Note, this implementation may be incomplete. If there's not a test for
+ your use case below, it's likely to fail, so please test and send pull
+ requests or patches for additional functionality needed.
+
+
+ >>> m = BijectiveMap()
+ >>> m['a'] = 'b'
+ >>> m == {'a': 'b', 'b': 'a'}
+ True
+ >>> print(m['b'])
+ a
+
+ >>> m['c'] = 'd'
+ >>> len(m)
+ 2
+
+ Some weird things happen if you map an item to itself or overwrite a
+ single key of a pair, so it's disallowed.
+
+ >>> m['e'] = 'e'
+ Traceback (most recent call last):
+ ValueError: Key cannot map to itself
+
+ >>> m['d'] = 'e'
+ Traceback (most recent call last):
+ ValueError: Key/Value pairs may not overlap
+
+ >>> m['e'] = 'd'
+ Traceback (most recent call last):
+ ValueError: Key/Value pairs may not overlap
+
+ >>> print(m.pop('d'))
+ c
+
+ >>> 'c' in m
+ False
+
+ >>> m = BijectiveMap(dict(a='b'))
+ >>> len(m)
+ 1
+ >>> print(m['b'])
+ a
+
+ >>> m = BijectiveMap()
+ >>> m.update(a='b')
+ >>> m['b']
+ 'a'
+
+ >>> del m['b']
+ >>> len(m)
+ 0
+ >>> 'a' in m
+ False
+ """
+
+ def __init__(self, *args, **kwargs):
+ super().__init__()
+ self.update(*args, **kwargs)
+
+ def __setitem__(self, item, value):
+ if item == value:
+ raise ValueError("Key cannot map to itself")
+ overlap = (
+ item in self
+ and self[item] != value
+ or value in self
+ and self[value] != item
+ )
+ if overlap:
+ raise ValueError("Key/Value pairs may not overlap")
+ super().__setitem__(item, value)
+ super().__setitem__(value, item)
+
+ def __delitem__(self, item):
+ self.pop(item)
+
+ def __len__(self):
+ return super().__len__() // 2
+
+ def pop(self, key, *args, **kwargs):
+ mirror = self[key]
+ super().__delitem__(mirror)
+ return super().pop(key, *args, **kwargs)
+
+ def update(self, *args, **kwargs):
+ # build a dictionary using the default constructs
+ d = dict(*args, **kwargs)
+ # build this dictionary using transformed keys.
+ for item in d.items():
+ self.__setitem__(*item)
+
+
+class FrozenDict(collections.abc.Mapping, collections.abc.Hashable):
+ """
+ An immutable mapping.
+
+ >>> a = FrozenDict(a=1, b=2)
+ >>> b = FrozenDict(a=1, b=2)
+ >>> a == b
+ True
+
+ >>> a == dict(a=1, b=2)
+ True
+ >>> dict(a=1, b=2) == a
+ True
+ >>> 'a' in a
+ True
+ >>> type(hash(a)) is type(0)
+ True
+ >>> set(iter(a)) == {'a', 'b'}
+ True
+ >>> len(a)
+ 2
+ >>> a['a'] == a.get('a') == 1
+ True
+
+ >>> a['c'] = 3
+ Traceback (most recent call last):
+ ...
+ TypeError: 'FrozenDict' object does not support item assignment
+
+ >>> a.update(y=3)
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'FrozenDict' object has no attribute 'update'
+
+ Copies should compare equal
+
+ >>> copy.copy(a) == a
+ True
+
+ Copies should be the same type
+
+ >>> isinstance(copy.copy(a), FrozenDict)
+ True
+
+ FrozenDict supplies .copy(), even though
+ collections.abc.Mapping doesn't demand it.
+
+ >>> a.copy() == a
+ True
+ >>> a.copy() is not a
+ True
+ """
+
+ __slots__ = ['__data']
+
+ def __new__(cls, *args, **kwargs):
+ self = super().__new__(cls)
+ self.__data = dict(*args, **kwargs)
+ return self
+
+ # Container
+ def __contains__(self, key):
+ return key in self.__data
+
+ # Hashable
+ def __hash__(self):
+ return hash(tuple(sorted(self.__data.items())))
+
+ # Mapping
+ def __iter__(self):
+ return iter(self.__data)
+
+ def __len__(self):
+ return len(self.__data)
+
+ def __getitem__(self, key):
+ return self.__data[key]
+
+ # override get for efficiency provided by dict
+ def get(self, *args, **kwargs):
+ return self.__data.get(*args, **kwargs)
+
+ # override eq to recognize underlying implementation
+ def __eq__(self, other):
+ if isinstance(other, FrozenDict):
+ other = other.__data
+ return self.__data.__eq__(other)
+
+ def copy(self):
+ "Return a shallow copy of self"
+ return copy.copy(self)
+
+
+class Enumeration(ItemsAsAttributes, BijectiveMap):
+ """
+ A convenient way to provide enumerated values
+
+ >>> e = Enumeration('a b c')
+ >>> e['a']
+ 0
+
+ >>> e.a
+ 0
+
+ >>> e[1]
+ 'b'
+
+ >>> set(e.names) == set('abc')
+ True
+
+ >>> set(e.codes) == set(range(3))
+ True
+
+ >>> e.get('d') is None
+ True
+
+ Codes need not start with 0
+
+ >>> e = Enumeration('a b c', range(1, 4))
+ >>> e['a']
+ 1
+
+ >>> e[3]
+ 'c'
+ """
+
+ def __init__(self, names, codes=None):
+ if isinstance(names, str):
+ names = names.split()
+ if codes is None:
+ codes = itertools.count()
+ super().__init__(zip(names, codes))
+
+ @property
+ def names(self):
+ return (key for key in self if isinstance(key, str))
+
+ @property
+ def codes(self):
+ return (self[name] for name in self.names)
+
+
+class Everything:
+ """
+ A collection "containing" every possible thing.
+
+ >>> 'foo' in Everything()
+ True
+
+ >>> import random
+ >>> random.randint(1, 999) in Everything()
+ True
+
+ >>> random.choice([None, 'foo', 42, ('a', 'b', 'c')]) in Everything()
+ True
+ """
+
+ def __contains__(self, other):
+ return True
+
+
+class InstrumentedDict(collections.UserDict):
+ """
+ Instrument an existing dictionary with additional
+ functionality, but always reference and mutate
+ the original dictionary.
+
+ >>> orig = {'a': 1, 'b': 2}
+ >>> inst = InstrumentedDict(orig)
+ >>> inst['a']
+ 1
+ >>> inst['c'] = 3
+ >>> orig['c']
+ 3
+ >>> inst.keys() == orig.keys()
+ True
+ """
+
+ def __init__(self, data):
+ super().__init__()
+ self.data = data
+
+
+class Least:
+ """
+ A value that is always lesser than any other
+
+ >>> least = Least()
+ >>> 3 < least
+ False
+ >>> 3 > least
+ True
+ >>> least < 3
+ True
+ >>> least <= 3
+ True
+ >>> least > 3
+ False
+ >>> 'x' > least
+ True
+ >>> None > least
+ True
+ """
+
+ def __le__(self, other):
+ return True
+
+ __lt__ = __le__
+
+ def __ge__(self, other):
+ return False
+
+ __gt__ = __ge__
+
+
+class Greatest:
+ """
+ A value that is always greater than any other
+
+ >>> greatest = Greatest()
+ >>> 3 < greatest
+ True
+ >>> 3 > greatest
+ False
+ >>> greatest < 3
+ False
+ >>> greatest > 3
+ True
+ >>> greatest >= 3
+ True
+ >>> 'x' > greatest
+ False
+ >>> None > greatest
+ False
+ """
+
+ def __ge__(self, other):
+ return True
+
+ __gt__ = __ge__
+
+ def __le__(self, other):
+ return False
+
+ __lt__ = __le__
+
+
+def pop_all(items):
+ """
+ Clear items in place and return a copy of items.
+
+ >>> items = [1, 2, 3]
+ >>> popped = pop_all(items)
+ >>> popped is items
+ False
+ >>> popped
+ [1, 2, 3]
+ >>> items
+ []
+ """
+ result, items[:] = items[:], []
+ return result
+
+
+class FreezableDefaultDict(collections.defaultdict):
+ """
+ Often it is desirable to prevent the mutation of
+ a default dict after its initial construction, such
+ as to prevent mutation during iteration.
+
+ >>> dd = FreezableDefaultDict(list)
+ >>> dd[0].append('1')
+ >>> dd.freeze()
+ >>> dd[1]
+ []
+ >>> len(dd)
+ 1
+ """
+
+ def __missing__(self, key):
+ return getattr(self, '_frozen', super().__missing__)(key)
+
+ def freeze(self):
+ self._frozen = lambda key: self.default_factory()
+
+
+class Accumulator:
+ def __init__(self, initial=0):
+ self.val = initial
+
+ def __call__(self, val):
+ self.val += val
+ return self.val
+
+
+class WeightedLookup(RangeMap):
+ """
+ Given parameters suitable for a dict representing keys
+ and a weighted proportion, return a RangeMap representing
+ spans of values proportial to the weights:
+
+ >>> even = WeightedLookup(a=1, b=1)
+
+ [0, 1) -> a
+ [1, 2) -> b
+
+ >>> lk = WeightedLookup(a=1, b=2)
+
+ [0, 1) -> a
+ [1, 3) -> b
+
+ >>> lk[.5]
+ 'a'
+ >>> lk[1.5]
+ 'b'
+
+ Adds ``.random()`` to select a random weighted value:
+
+ >>> lk.random() in ['a', 'b']
+ True
+
+ >>> choices = [lk.random() for x in range(1000)]
+
+ Statistically speaking, choices should be .5 a:b
+ >>> ratio = choices.count('a') / choices.count('b')
+ >>> .4 < ratio < .6
+ True
+ """
+
+ def __init__(self, *args, **kwargs):
+ raw = dict(*args, **kwargs)
+
+ # allocate keys by weight
+ indexes = map(Accumulator(), raw.values())
+ super().__init__(zip(indexes, raw.keys()), key_match_comparator=operator.lt)
+
+ def random(self):
+ lower, upper = self.bounds()
+ selector = random.random() * upper
+ return self[selector]
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/collections/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/collections/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..5805a65
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/collections/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/collections/py.typed b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/collections/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/context.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/context.py
new file mode 100644
index 0000000..61b2713
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/context.py
@@ -0,0 +1,361 @@
+from __future__ import annotations
+
+import contextlib
+import functools
+import operator
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+import urllib.request
+import warnings
+from typing import Iterator
+
+
+if sys.version_info < (3, 12):
+ from backports import tarfile
+else:
+ import tarfile
+
+
+@contextlib.contextmanager
+def pushd(dir: str | os.PathLike) -> Iterator[str | os.PathLike]:
+ """
+ >>> tmp_path = getfixture('tmp_path')
+ >>> with pushd(tmp_path):
+ ... assert os.getcwd() == os.fspath(tmp_path)
+ >>> assert os.getcwd() != os.fspath(tmp_path)
+ """
+
+ orig = os.getcwd()
+ os.chdir(dir)
+ try:
+ yield dir
+ finally:
+ os.chdir(orig)
+
+
+@contextlib.contextmanager
+def tarball(
+ url, target_dir: str | os.PathLike | None = None
+) -> Iterator[str | os.PathLike]:
+ """
+ Get a tarball, extract it, yield, then clean up.
+
+ >>> import urllib.request
+ >>> url = getfixture('tarfile_served')
+ >>> target = getfixture('tmp_path') / 'out'
+ >>> tb = tarball(url, target_dir=target)
+ >>> import pathlib
+ >>> with tb as extracted:
+ ... contents = pathlib.Path(extracted, 'contents.txt').read_text(encoding='utf-8')
+ >>> assert not os.path.exists(extracted)
+ """
+ if target_dir is None:
+ target_dir = os.path.basename(url).replace('.tar.gz', '').replace('.tgz', '')
+ # In the tar command, use --strip-components=1 to strip the first path and
+ # then
+ # use -C to cause the files to be extracted to {target_dir}. This ensures
+ # that we always know where the files were extracted.
+ os.mkdir(target_dir)
+ try:
+ req = urllib.request.urlopen(url)
+ with tarfile.open(fileobj=req, mode='r|*') as tf:
+ tf.extractall(path=target_dir, filter=strip_first_component)
+ yield target_dir
+ finally:
+ shutil.rmtree(target_dir)
+
+
+def strip_first_component(
+ member: tarfile.TarInfo,
+ path,
+) -> tarfile.TarInfo:
+ _, member.name = member.name.split('/', 1)
+ return member
+
+
+def _compose(*cmgrs):
+ """
+ Compose any number of dependent context managers into a single one.
+
+ The last, innermost context manager may take arbitrary arguments, but
+ each successive context manager should accept the result from the
+ previous as a single parameter.
+
+ Like :func:`jaraco.functools.compose`, behavior works from right to
+ left, so the context manager should be indicated from outermost to
+ innermost.
+
+ Example, to create a context manager to change to a temporary
+ directory:
+
+ >>> temp_dir_as_cwd = _compose(pushd, temp_dir)
+ >>> with temp_dir_as_cwd() as dir:
+ ... assert os.path.samefile(os.getcwd(), dir)
+ """
+
+ def compose_two(inner, outer):
+ def composed(*args, **kwargs):
+ with inner(*args, **kwargs) as saved, outer(saved) as res:
+ yield res
+
+ return contextlib.contextmanager(composed)
+
+ return functools.reduce(compose_two, reversed(cmgrs))
+
+
+tarball_cwd = _compose(pushd, tarball)
+
+
+@contextlib.contextmanager
+def tarball_context(*args, **kwargs):
+ warnings.warn(
+ "tarball_context is deprecated. Use tarball or tarball_cwd instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ pushd_ctx = kwargs.pop('pushd', pushd)
+ with tarball(*args, **kwargs) as tball, pushd_ctx(tball) as dir:
+ yield dir
+
+
+def infer_compression(url):
+ """
+ Given a URL or filename, infer the compression code for tar.
+
+ >>> infer_compression('http://foo/bar.tar.gz')
+ 'z'
+ >>> infer_compression('http://foo/bar.tgz')
+ 'z'
+ >>> infer_compression('file.bz')
+ 'j'
+ >>> infer_compression('file.xz')
+ 'J'
+ """
+ warnings.warn(
+ "infer_compression is deprecated with no replacement",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ # cheat and just assume it's the last two characters
+ compression_indicator = url[-2:]
+ mapping = dict(gz='z', bz='j', xz='J')
+ # Assume 'z' (gzip) if no match
+ return mapping.get(compression_indicator, 'z')
+
+
+@contextlib.contextmanager
+def temp_dir(remover=shutil.rmtree):
+ """
+ Create a temporary directory context. Pass a custom remover
+ to override the removal behavior.
+
+ >>> import pathlib
+ >>> with temp_dir() as the_dir:
+ ... assert os.path.isdir(the_dir)
+ ... _ = pathlib.Path(the_dir).joinpath('somefile').write_text('contents', encoding='utf-8')
+ >>> assert not os.path.exists(the_dir)
+ """
+ temp_dir = tempfile.mkdtemp()
+ try:
+ yield temp_dir
+ finally:
+ remover(temp_dir)
+
+
+@contextlib.contextmanager
+def repo_context(url, branch=None, quiet=True, dest_ctx=temp_dir):
+ """
+ Check out the repo indicated by url.
+
+ If dest_ctx is supplied, it should be a context manager
+ to yield the target directory for the check out.
+ """
+ exe = 'git' if 'git' in url else 'hg'
+ with dest_ctx() as repo_dir:
+ cmd = [exe, 'clone', url, repo_dir]
+ if branch:
+ cmd.extend(['--branch', branch])
+ devnull = open(os.path.devnull, 'w')
+ stdout = devnull if quiet else None
+ subprocess.check_call(cmd, stdout=stdout)
+ yield repo_dir
+
+
+def null():
+ """
+ A null context suitable to stand in for a meaningful context.
+
+ >>> with null() as value:
+ ... assert value is None
+
+ This context is most useful when dealing with two or more code
+ branches but only some need a context. Wrap the others in a null
+ context to provide symmetry across all options.
+ """
+ warnings.warn(
+ "null is deprecated. Use contextlib.nullcontext",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return contextlib.nullcontext()
+
+
+class ExceptionTrap:
+ """
+ A context manager that will catch certain exceptions and provide an
+ indication they occurred.
+
+ >>> with ExceptionTrap() as trap:
+ ... raise Exception()
+ >>> bool(trap)
+ True
+
+ >>> with ExceptionTrap() as trap:
+ ... pass
+ >>> bool(trap)
+ False
+
+ >>> with ExceptionTrap(ValueError) as trap:
+ ... raise ValueError("1 + 1 is not 3")
+ >>> bool(trap)
+ True
+ >>> trap.value
+ ValueError('1 + 1 is not 3')
+ >>> trap.tb
+
+
+ >>> with ExceptionTrap(ValueError) as trap:
+ ... raise Exception()
+ Traceback (most recent call last):
+ ...
+ Exception
+
+ >>> bool(trap)
+ False
+ """
+
+ exc_info = None, None, None
+
+ def __init__(self, exceptions=(Exception,)):
+ self.exceptions = exceptions
+
+ def __enter__(self):
+ return self
+
+ @property
+ def type(self):
+ return self.exc_info[0]
+
+ @property
+ def value(self):
+ return self.exc_info[1]
+
+ @property
+ def tb(self):
+ return self.exc_info[2]
+
+ def __exit__(self, *exc_info):
+ type = exc_info[0]
+ matches = type and issubclass(type, self.exceptions)
+ if matches:
+ self.exc_info = exc_info
+ return matches
+
+ def __bool__(self):
+ return bool(self.type)
+
+ def raises(self, func, *, _test=bool):
+ """
+ Wrap func and replace the result with the truth
+ value of the trap (True if an exception occurred).
+
+ First, give the decorator an alias to support Python 3.8
+ Syntax.
+
+ >>> raises = ExceptionTrap(ValueError).raises
+
+ Now decorate a function that always fails.
+
+ >>> @raises
+ ... def fail():
+ ... raise ValueError('failed')
+ >>> fail()
+ True
+ """
+
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ with ExceptionTrap(self.exceptions) as trap:
+ func(*args, **kwargs)
+ return _test(trap)
+
+ return wrapper
+
+ def passes(self, func):
+ """
+ Wrap func and replace the result with the truth
+ value of the trap (True if no exception).
+
+ First, give the decorator an alias to support Python 3.8
+ Syntax.
+
+ >>> passes = ExceptionTrap(ValueError).passes
+
+ Now decorate a function that always fails.
+
+ >>> @passes
+ ... def fail():
+ ... raise ValueError('failed')
+
+ >>> fail()
+ False
+ """
+ return self.raises(func, _test=operator.not_)
+
+
+class suppress(contextlib.suppress, contextlib.ContextDecorator):
+ """
+ A version of contextlib.suppress with decorator support.
+
+ >>> @suppress(KeyError)
+ ... def key_error():
+ ... {}['']
+ >>> key_error()
+ """
+
+
+class on_interrupt(contextlib.ContextDecorator):
+ """
+ Replace a KeyboardInterrupt with SystemExit(1)
+
+ >>> def do_interrupt():
+ ... raise KeyboardInterrupt()
+ >>> on_interrupt('error')(do_interrupt)()
+ Traceback (most recent call last):
+ ...
+ SystemExit: 1
+ >>> on_interrupt('error', code=255)(do_interrupt)()
+ Traceback (most recent call last):
+ ...
+ SystemExit: 255
+ >>> on_interrupt('suppress')(do_interrupt)()
+ >>> with __import__('pytest').raises(KeyboardInterrupt):
+ ... on_interrupt('ignore')(do_interrupt)()
+ """
+
+ def __init__(self, action='error', /, code=1):
+ self.action = action
+ self.code = code
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exctype, excinst, exctb):
+ if exctype is not KeyboardInterrupt or self.action == 'ignore':
+ return
+ elif self.action == 'error':
+ raise SystemExit(self.code) from excinst
+ return self.action == 'suppress'
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/functools/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/functools/__init__.py
new file mode 100644
index 0000000..ca6c22f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/functools/__init__.py
@@ -0,0 +1,633 @@
+import collections.abc
+import functools
+import inspect
+import itertools
+import operator
+import time
+import types
+import warnings
+
+import more_itertools
+
+
+def compose(*funcs):
+ """
+ Compose any number of unary functions into a single unary function.
+
+ >>> import textwrap
+ >>> expected = str.strip(textwrap.dedent(compose.__doc__))
+ >>> strip_and_dedent = compose(str.strip, textwrap.dedent)
+ >>> strip_and_dedent(compose.__doc__) == expected
+ True
+
+ Compose also allows the innermost function to take arbitrary arguments.
+
+ >>> round_three = lambda x: round(x, ndigits=3)
+ >>> f = compose(round_three, int.__truediv__)
+ >>> [f(3*x, x+1) for x in range(1,10)]
+ [1.5, 2.0, 2.25, 2.4, 2.5, 2.571, 2.625, 2.667, 2.7]
+ """
+
+ def compose_two(f1, f2):
+ return lambda *args, **kwargs: f1(f2(*args, **kwargs))
+
+ return functools.reduce(compose_two, funcs)
+
+
+def once(func):
+ """
+ Decorate func so it's only ever called the first time.
+
+ This decorator can ensure that an expensive or non-idempotent function
+ will not be expensive on subsequent calls and is idempotent.
+
+ >>> add_three = once(lambda a: a+3)
+ >>> add_three(3)
+ 6
+ >>> add_three(9)
+ 6
+ >>> add_three('12')
+ 6
+
+ To reset the stored value, simply clear the property ``saved_result``.
+
+ >>> del add_three.saved_result
+ >>> add_three(9)
+ 12
+ >>> add_three(8)
+ 12
+
+ Or invoke 'reset()' on it.
+
+ >>> add_three.reset()
+ >>> add_three(-3)
+ 0
+ >>> add_three(0)
+ 0
+ """
+
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ if not hasattr(wrapper, 'saved_result'):
+ wrapper.saved_result = func(*args, **kwargs)
+ return wrapper.saved_result
+
+ wrapper.reset = lambda: vars(wrapper).__delitem__('saved_result')
+ return wrapper
+
+
+def method_cache(method, cache_wrapper=functools.lru_cache()):
+ """
+ Wrap lru_cache to support storing the cache data in the object instances.
+
+ Abstracts the common paradigm where the method explicitly saves an
+ underscore-prefixed protected property on first call and returns that
+ subsequently.
+
+ >>> class MyClass:
+ ... calls = 0
+ ...
+ ... @method_cache
+ ... def method(self, value):
+ ... self.calls += 1
+ ... return value
+
+ >>> a = MyClass()
+ >>> a.method(3)
+ 3
+ >>> for x in range(75):
+ ... res = a.method(x)
+ >>> a.calls
+ 75
+
+ Note that the apparent behavior will be exactly like that of lru_cache
+ except that the cache is stored on each instance, so values in one
+ instance will not flush values from another, and when an instance is
+ deleted, so are the cached values for that instance.
+
+ >>> b = MyClass()
+ >>> for x in range(35):
+ ... res = b.method(x)
+ >>> b.calls
+ 35
+ >>> a.method(0)
+ 0
+ >>> a.calls
+ 75
+
+ Note that if method had been decorated with ``functools.lru_cache()``,
+ a.calls would have been 76 (due to the cached value of 0 having been
+ flushed by the 'b' instance).
+
+ Clear the cache with ``.cache_clear()``
+
+ >>> a.method.cache_clear()
+
+ Same for a method that hasn't yet been called.
+
+ >>> c = MyClass()
+ >>> c.method.cache_clear()
+
+ Another cache wrapper may be supplied:
+
+ >>> cache = functools.lru_cache(maxsize=2)
+ >>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache)
+ >>> a = MyClass()
+ >>> a.method2()
+ 3
+
+ Caution - do not subsequently wrap the method with another decorator, such
+ as ``@property``, which changes the semantics of the function.
+
+ See also
+ http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/
+ for another implementation and additional justification.
+ """
+
+ def wrapper(self, *args, **kwargs):
+ # it's the first call, replace the method with a cached, bound method
+ bound_method = types.MethodType(method, self)
+ cached_method = cache_wrapper(bound_method)
+ setattr(self, method.__name__, cached_method)
+ return cached_method(*args, **kwargs)
+
+ # Support cache clear even before cache has been created.
+ wrapper.cache_clear = lambda: None
+
+ return _special_method_cache(method, cache_wrapper) or wrapper
+
+
+def _special_method_cache(method, cache_wrapper):
+ """
+ Because Python treats special methods differently, it's not
+ possible to use instance attributes to implement the cached
+ methods.
+
+ Instead, install the wrapper method under a different name
+ and return a simple proxy to that wrapper.
+
+ https://github.com/jaraco/jaraco.functools/issues/5
+ """
+ name = method.__name__
+ special_names = '__getattr__', '__getitem__'
+
+ if name not in special_names:
+ return None
+
+ wrapper_name = '__cached' + name
+
+ def proxy(self, /, *args, **kwargs):
+ if wrapper_name not in vars(self):
+ bound = types.MethodType(method, self)
+ cache = cache_wrapper(bound)
+ setattr(self, wrapper_name, cache)
+ else:
+ cache = getattr(self, wrapper_name)
+ return cache(*args, **kwargs)
+
+ return proxy
+
+
+def apply(transform):
+ """
+ Decorate a function with a transform function that is
+ invoked on results returned from the decorated function.
+
+ >>> @apply(reversed)
+ ... def get_numbers(start):
+ ... "doc for get_numbers"
+ ... return range(start, start+3)
+ >>> list(get_numbers(4))
+ [6, 5, 4]
+ >>> get_numbers.__doc__
+ 'doc for get_numbers'
+ """
+
+ def wrap(func):
+ return functools.wraps(func)(compose(transform, func))
+
+ return wrap
+
+
+def result_invoke(action):
+ r"""
+ Decorate a function with an action function that is
+ invoked on the results returned from the decorated
+ function (for its side effect), then return the original
+ result.
+
+ >>> @result_invoke(print)
+ ... def add_two(a, b):
+ ... return a + b
+ >>> x = add_two(2, 3)
+ 5
+ >>> x
+ 5
+ """
+
+ def wrap(func):
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ result = func(*args, **kwargs)
+ action(result)
+ return result
+
+ return wrapper
+
+ return wrap
+
+
+def invoke(f, /, *args, **kwargs):
+ """
+ Call a function for its side effect after initialization.
+
+ The benefit of using the decorator instead of simply invoking a function
+ after defining it is that it makes explicit the author's intent for the
+ function to be called immediately. Whereas if one simply calls the
+ function immediately, it's less obvious if that was intentional or
+ incidental. It also avoids repeating the name - the two actions, defining
+ the function and calling it immediately are modeled separately, but linked
+ by the decorator construct.
+
+ The benefit of having a function construct (opposed to just invoking some
+ behavior inline) is to serve as a scope in which the behavior occurs. It
+ avoids polluting the global namespace with local variables, provides an
+ anchor on which to attach documentation (docstring), keeps the behavior
+ logically separated (instead of conceptually separated or not separated at
+ all), and provides potential to re-use the behavior for testing or other
+ purposes.
+
+ This function is named as a pithy way to communicate, "call this function
+ primarily for its side effect", or "while defining this function, also
+ take it aside and call it". It exists because there's no Python construct
+ for "define and call" (nor should there be, as decorators serve this need
+ just fine). The behavior happens immediately and synchronously.
+
+ >>> @invoke
+ ... def func(): print("called")
+ called
+ >>> func()
+ called
+
+ Use functools.partial to pass parameters to the initial call
+
+ >>> @functools.partial(invoke, name='bingo')
+ ... def func(name): print('called with', name)
+ called with bingo
+ """
+ f(*args, **kwargs)
+ return f
+
+
+class Throttler:
+ """Rate-limit a function (or other callable)."""
+
+ def __init__(self, func, max_rate=float('Inf')):
+ if isinstance(func, Throttler):
+ func = func.func
+ self.func = func
+ self.max_rate = max_rate
+ self.reset()
+
+ def reset(self):
+ self.last_called = 0
+
+ def __call__(self, *args, **kwargs):
+ self._wait()
+ return self.func(*args, **kwargs)
+
+ def _wait(self):
+ """Ensure at least 1/max_rate seconds from last call."""
+ elapsed = time.time() - self.last_called
+ must_wait = 1 / self.max_rate - elapsed
+ time.sleep(max(0, must_wait))
+ self.last_called = time.time()
+
+ def __get__(self, obj, owner=None):
+ return first_invoke(self._wait, functools.partial(self.func, obj))
+
+
+def first_invoke(func1, func2):
+ """
+ Return a function that when invoked will invoke func1 without
+ any parameters (for its side effect) and then invoke func2
+ with whatever parameters were passed, returning its result.
+ """
+
+ def wrapper(*args, **kwargs):
+ func1()
+ return func2(*args, **kwargs)
+
+ return wrapper
+
+
+method_caller = first_invoke(
+ lambda: warnings.warn(
+ '`jaraco.functools.method_caller` is deprecated, '
+ 'use `operator.methodcaller` instead',
+ DeprecationWarning,
+ stacklevel=3,
+ ),
+ operator.methodcaller,
+)
+
+
+def retry_call(func, cleanup=lambda: None, retries=0, trap=()):
+ """
+ Given a callable func, trap the indicated exceptions
+ for up to 'retries' times, invoking cleanup on the
+ exception. On the final attempt, allow any exceptions
+ to propagate.
+ """
+ attempts = itertools.count() if retries == float('inf') else range(retries)
+ for _ in attempts:
+ try:
+ return func()
+ except trap:
+ cleanup()
+
+ return func()
+
+
+def retry(*r_args, **r_kwargs):
+ """
+ Decorator wrapper for retry_call. Accepts arguments to retry_call
+ except func and then returns a decorator for the decorated function.
+
+ Ex:
+
+ >>> @retry(retries=3)
+ ... def my_func(a, b):
+ ... "this is my funk"
+ ... print(a, b)
+ >>> my_func.__doc__
+ 'this is my funk'
+ """
+
+ def decorate(func):
+ @functools.wraps(func)
+ def wrapper(*f_args, **f_kwargs):
+ bound = functools.partial(func, *f_args, **f_kwargs)
+ return retry_call(bound, *r_args, **r_kwargs)
+
+ return wrapper
+
+ return decorate
+
+
+def print_yielded(func):
+ """
+ Convert a generator into a function that prints all yielded elements.
+
+ >>> @print_yielded
+ ... def x():
+ ... yield 3; yield None
+ >>> x()
+ 3
+ None
+ """
+ print_all = functools.partial(map, print)
+ print_results = compose(more_itertools.consume, print_all, func)
+ return functools.wraps(func)(print_results)
+
+
+def pass_none(func):
+ """
+ Wrap func so it's not called if its first param is None.
+
+ >>> print_text = pass_none(print)
+ >>> print_text('text')
+ text
+ >>> print_text(None)
+ """
+
+ @functools.wraps(func)
+ def wrapper(param, /, *args, **kwargs):
+ if param is not None:
+ return func(param, *args, **kwargs)
+ return None
+
+ return wrapper
+
+
+def assign_params(func, namespace):
+ """
+ Assign parameters from namespace where func solicits.
+
+ >>> def func(x, y=3):
+ ... print(x, y)
+ >>> assigned = assign_params(func, dict(x=2, z=4))
+ >>> assigned()
+ 2 3
+
+ The usual errors are raised if a function doesn't receive
+ its required parameters:
+
+ >>> assigned = assign_params(func, dict(y=3, z=4))
+ >>> assigned()
+ Traceback (most recent call last):
+ TypeError: func() ...argument...
+
+ It even works on methods:
+
+ >>> class Handler:
+ ... def meth(self, arg):
+ ... print(arg)
+ >>> assign_params(Handler().meth, dict(arg='crystal', foo='clear'))()
+ crystal
+ """
+ sig = inspect.signature(func)
+ params = sig.parameters.keys()
+ call_ns = {k: namespace[k] for k in params if k in namespace}
+ return functools.partial(func, **call_ns)
+
+
+def save_method_args(method):
+ """
+ Wrap a method such that when it is called, the args and kwargs are
+ saved on the method.
+
+ >>> class MyClass:
+ ... @save_method_args
+ ... def method(self, a, b):
+ ... print(a, b)
+ >>> my_ob = MyClass()
+ >>> my_ob.method(1, 2)
+ 1 2
+ >>> my_ob._saved_method.args
+ (1, 2)
+ >>> my_ob._saved_method.kwargs
+ {}
+ >>> my_ob.method(a=3, b='foo')
+ 3 foo
+ >>> my_ob._saved_method.args
+ ()
+ >>> my_ob._saved_method.kwargs == dict(a=3, b='foo')
+ True
+
+ The arguments are stored on the instance, allowing for
+ different instance to save different args.
+
+ >>> your_ob = MyClass()
+ >>> your_ob.method({str('x'): 3}, b=[4])
+ {'x': 3} [4]
+ >>> your_ob._saved_method.args
+ ({'x': 3},)
+ >>> my_ob._saved_method.args
+ ()
+ """
+ args_and_kwargs = collections.namedtuple('args_and_kwargs', 'args kwargs')
+
+ @functools.wraps(method)
+ def wrapper(self, /, *args, **kwargs):
+ attr_name = '_saved_' + method.__name__
+ attr = args_and_kwargs(args, kwargs)
+ setattr(self, attr_name, attr)
+ return method(self, *args, **kwargs)
+
+ return wrapper
+
+
+def except_(*exceptions, replace=None, use=None):
+ """
+ Replace the indicated exceptions, if raised, with the indicated
+ literal replacement or evaluated expression (if present).
+
+ >>> safe_int = except_(ValueError)(int)
+ >>> safe_int('five')
+ >>> safe_int('5')
+ 5
+
+ Specify a literal replacement with ``replace``.
+
+ >>> safe_int_r = except_(ValueError, replace=0)(int)
+ >>> safe_int_r('five')
+ 0
+
+ Provide an expression to ``use`` to pass through particular parameters.
+
+ >>> safe_int_pt = except_(ValueError, use='args[0]')(int)
+ >>> safe_int_pt('five')
+ 'five'
+
+ """
+
+ def decorate(func):
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ try:
+ return func(*args, **kwargs)
+ except exceptions:
+ try:
+ return eval(use)
+ except TypeError:
+ return replace
+
+ return wrapper
+
+ return decorate
+
+
+def identity(x):
+ """
+ Return the argument.
+
+ >>> o = object()
+ >>> identity(o) is o
+ True
+ """
+ return x
+
+
+def bypass_when(check, *, _op=identity):
+ """
+ Decorate a function to return its parameter when ``check``.
+
+ >>> bypassed = [] # False
+
+ >>> @bypass_when(bypassed)
+ ... def double(x):
+ ... return x * 2
+ >>> double(2)
+ 4
+ >>> bypassed[:] = [object()] # True
+ >>> double(2)
+ 2
+ """
+
+ def decorate(func):
+ @functools.wraps(func)
+ def wrapper(param, /):
+ return param if _op(check) else func(param)
+
+ return wrapper
+
+ return decorate
+
+
+def bypass_unless(check):
+ """
+ Decorate a function to return its parameter unless ``check``.
+
+ >>> enabled = [object()] # True
+
+ >>> @bypass_unless(enabled)
+ ... def double(x):
+ ... return x * 2
+ >>> double(2)
+ 4
+ >>> del enabled[:] # False
+ >>> double(2)
+ 2
+ """
+ return bypass_when(check, _op=operator.not_)
+
+
+@functools.singledispatch
+def _splat_inner(args, func):
+ """Splat args to func."""
+ return func(*args)
+
+
+@_splat_inner.register
+def _(args: collections.abc.Mapping, func):
+ """Splat kargs to func as kwargs."""
+ return func(**args)
+
+
+def splat(func):
+ """
+ Wrap func to expect its parameters to be passed positionally in a tuple.
+
+ Has a similar effect to that of ``itertools.starmap`` over
+ simple ``map``.
+
+ >>> pairs = [(-1, 1), (0, 2)]
+ >>> more_itertools.consume(itertools.starmap(print, pairs))
+ -1 1
+ 0 2
+ >>> more_itertools.consume(map(splat(print), pairs))
+ -1 1
+ 0 2
+
+ The approach generalizes to other iterators that don't have a "star"
+ equivalent, such as a "starfilter".
+
+ >>> list(filter(splat(operator.add), pairs))
+ [(0, 2)]
+
+ Splat also accepts a mapping argument.
+
+ >>> def is_nice(msg, code):
+ ... return "smile" in msg or code == 0
+ >>> msgs = [
+ ... dict(msg='smile!', code=20),
+ ... dict(msg='error :(', code=1),
+ ... dict(msg='unknown', code=0),
+ ... ]
+ >>> for msg in filter(splat(is_nice), msgs):
+ ... print(msg)
+ {'msg': 'smile!', 'code': 20}
+ {'msg': 'unknown', 'code': 0}
+ """
+ return functools.wraps(func)(functools.partial(_splat_inner, func=func))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/functools/__init__.pyi b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/functools/__init__.pyi
new file mode 100644
index 0000000..19191bf
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/functools/__init__.pyi
@@ -0,0 +1,125 @@
+from collections.abc import Callable, Hashable, Iterator
+from functools import partial
+from operator import methodcaller
+import sys
+from typing import (
+ Any,
+ Generic,
+ Protocol,
+ TypeVar,
+ overload,
+)
+
+if sys.version_info >= (3, 10):
+ from typing import Concatenate, ParamSpec
+else:
+ from typing_extensions import Concatenate, ParamSpec
+
+_P = ParamSpec('_P')
+_R = TypeVar('_R')
+_T = TypeVar('_T')
+_R1 = TypeVar('_R1')
+_R2 = TypeVar('_R2')
+_V = TypeVar('_V')
+_S = TypeVar('_S')
+_R_co = TypeVar('_R_co', covariant=True)
+
+class _OnceCallable(Protocol[_P, _R]):
+ saved_result: _R
+ reset: Callable[[], None]
+ def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> _R: ...
+
+class _ProxyMethodCacheWrapper(Protocol[_R_co]):
+ cache_clear: Callable[[], None]
+ def __call__(self, *args: Hashable, **kwargs: Hashable) -> _R_co: ...
+
+class _MethodCacheWrapper(Protocol[_R_co]):
+ def cache_clear(self) -> None: ...
+ def __call__(self, *args: Hashable, **kwargs: Hashable) -> _R_co: ...
+
+# `compose()` overloads below will cover most use cases.
+
+@overload
+def compose(
+ __func1: Callable[[_R], _T],
+ __func2: Callable[_P, _R],
+ /,
+) -> Callable[_P, _T]: ...
+@overload
+def compose(
+ __func1: Callable[[_R], _T],
+ __func2: Callable[[_R1], _R],
+ __func3: Callable[_P, _R1],
+ /,
+) -> Callable[_P, _T]: ...
+@overload
+def compose(
+ __func1: Callable[[_R], _T],
+ __func2: Callable[[_R2], _R],
+ __func3: Callable[[_R1], _R2],
+ __func4: Callable[_P, _R1],
+ /,
+) -> Callable[_P, _T]: ...
+def once(func: Callable[_P, _R]) -> _OnceCallable[_P, _R]: ...
+def method_cache(
+ method: Callable[..., _R],
+ cache_wrapper: Callable[[Callable[..., _R]], _MethodCacheWrapper[_R]] = ...,
+) -> _MethodCacheWrapper[_R] | _ProxyMethodCacheWrapper[_R]: ...
+def apply(
+ transform: Callable[[_R], _T]
+) -> Callable[[Callable[_P, _R]], Callable[_P, _T]]: ...
+def result_invoke(
+ action: Callable[[_R], Any]
+) -> Callable[[Callable[_P, _R]], Callable[_P, _R]]: ...
+def invoke(
+ f: Callable[_P, _R], /, *args: _P.args, **kwargs: _P.kwargs
+) -> Callable[_P, _R]: ...
+
+class Throttler(Generic[_R]):
+ last_called: float
+ func: Callable[..., _R]
+ max_rate: float
+ def __init__(
+ self, func: Callable[..., _R] | Throttler[_R], max_rate: float = ...
+ ) -> None: ...
+ def reset(self) -> None: ...
+ def __call__(self, *args: Any, **kwargs: Any) -> _R: ...
+ def __get__(self, obj: Any, owner: type[Any] | None = ...) -> Callable[..., _R]: ...
+
+def first_invoke(
+ func1: Callable[..., Any], func2: Callable[_P, _R]
+) -> Callable[_P, _R]: ...
+
+method_caller: Callable[..., methodcaller]
+
+def retry_call(
+ func: Callable[..., _R],
+ cleanup: Callable[..., None] = ...,
+ retries: int | float = ...,
+ trap: type[BaseException] | tuple[type[BaseException], ...] = ...,
+) -> _R: ...
+def retry(
+ cleanup: Callable[..., None] = ...,
+ retries: int | float = ...,
+ trap: type[BaseException] | tuple[type[BaseException], ...] = ...,
+) -> Callable[[Callable[..., _R]], Callable[..., _R]]: ...
+def print_yielded(func: Callable[_P, Iterator[Any]]) -> Callable[_P, None]: ...
+def pass_none(
+ func: Callable[Concatenate[_T, _P], _R]
+) -> Callable[Concatenate[_T, _P], _R]: ...
+def assign_params(
+ func: Callable[..., _R], namespace: dict[str, Any]
+) -> partial[_R]: ...
+def save_method_args(
+ method: Callable[Concatenate[_S, _P], _R]
+) -> Callable[Concatenate[_S, _P], _R]: ...
+def except_(
+ *exceptions: type[BaseException], replace: Any = ..., use: Any = ...
+) -> Callable[[Callable[_P, Any]], Callable[_P, Any]]: ...
+def identity(x: _T) -> _T: ...
+def bypass_when(
+ check: _V, *, _op: Callable[[_V], Any] = ...
+) -> Callable[[Callable[[_T], _R]], Callable[[_T], _T | _R]]: ...
+def bypass_unless(
+ check: Any,
+) -> Callable[[Callable[[_T], _R]], Callable[[_T], _T | _R]]: ...
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/functools/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/functools/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..485db7e
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/functools/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/functools/py.typed b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/functools/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/Lorem ipsum.txt b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/Lorem ipsum.txt
new file mode 100644
index 0000000..986f944
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/Lorem ipsum.txt
@@ -0,0 +1,2 @@
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis risus a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue, eros est euismod turpis, id tincidunt sapien risus a quam. Maecenas fermentum consequat mi. Donec fermentum. Pellentesque malesuada nulla a mi. Duis sapien sem, aliquet nec, commodo eget, consequat quis, neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl adipiscing sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus quis, laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, molestie eu, feugiat in, orci. In hac habitasse platea dictumst.
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__init__.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__init__.py
new file mode 100644
index 0000000..0fabd0c
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__init__.py
@@ -0,0 +1,624 @@
+import re
+import itertools
+import textwrap
+import functools
+
+try:
+ from importlib.resources import files # type: ignore
+except ImportError: # pragma: nocover
+ from importlib_resources import files # type: ignore
+
+from jaraco.functools import compose, method_cache
+from jaraco.context import ExceptionTrap
+
+
+def substitution(old, new):
+ """
+ Return a function that will perform a substitution on a string
+ """
+ return lambda s: s.replace(old, new)
+
+
+def multi_substitution(*substitutions):
+ """
+ Take a sequence of pairs specifying substitutions, and create
+ a function that performs those substitutions.
+
+ >>> multi_substitution(('foo', 'bar'), ('bar', 'baz'))('foo')
+ 'baz'
+ """
+ substitutions = itertools.starmap(substitution, substitutions)
+ # compose function applies last function first, so reverse the
+ # substitutions to get the expected order.
+ substitutions = reversed(tuple(substitutions))
+ return compose(*substitutions)
+
+
+class FoldedCase(str):
+ """
+ A case insensitive string class; behaves just like str
+ except compares equal when the only variation is case.
+
+ >>> s = FoldedCase('hello world')
+
+ >>> s == 'Hello World'
+ True
+
+ >>> 'Hello World' == s
+ True
+
+ >>> s != 'Hello World'
+ False
+
+ >>> s.index('O')
+ 4
+
+ >>> s.split('O')
+ ['hell', ' w', 'rld']
+
+ >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta']))
+ ['alpha', 'Beta', 'GAMMA']
+
+ Sequence membership is straightforward.
+
+ >>> "Hello World" in [s]
+ True
+ >>> s in ["Hello World"]
+ True
+
+ Allows testing for set inclusion, but candidate and elements
+ must both be folded.
+
+ >>> FoldedCase("Hello World") in {s}
+ True
+ >>> s in {FoldedCase("Hello World")}
+ True
+
+ String inclusion works as long as the FoldedCase object
+ is on the right.
+
+ >>> "hello" in FoldedCase("Hello World")
+ True
+
+ But not if the FoldedCase object is on the left:
+
+ >>> FoldedCase('hello') in 'Hello World'
+ False
+
+ In that case, use ``in_``:
+
+ >>> FoldedCase('hello').in_('Hello World')
+ True
+
+ >>> FoldedCase('hello') > FoldedCase('Hello')
+ False
+
+ >>> FoldedCase('ß') == FoldedCase('ss')
+ True
+ """
+
+ def __lt__(self, other):
+ return self.casefold() < other.casefold()
+
+ def __gt__(self, other):
+ return self.casefold() > other.casefold()
+
+ def __eq__(self, other):
+ return self.casefold() == other.casefold()
+
+ def __ne__(self, other):
+ return self.casefold() != other.casefold()
+
+ def __hash__(self):
+ return hash(self.casefold())
+
+ def __contains__(self, other):
+ return super().casefold().__contains__(other.casefold())
+
+ def in_(self, other):
+ "Does self appear in other?"
+ return self in FoldedCase(other)
+
+ # cache casefold since it's likely to be called frequently.
+ @method_cache
+ def casefold(self):
+ return super().casefold()
+
+ def index(self, sub):
+ return self.casefold().index(sub.casefold())
+
+ def split(self, splitter=' ', maxsplit=0):
+ pattern = re.compile(re.escape(splitter), re.I)
+ return pattern.split(self, maxsplit)
+
+
+# Python 3.8 compatibility
+_unicode_trap = ExceptionTrap(UnicodeDecodeError)
+
+
+@_unicode_trap.passes
+def is_decodable(value):
+ r"""
+ Return True if the supplied value is decodable (using the default
+ encoding).
+
+ >>> is_decodable(b'\xff')
+ False
+ >>> is_decodable(b'\x32')
+ True
+ """
+ value.decode()
+
+
+def is_binary(value):
+ r"""
+ Return True if the value appears to be binary (that is, it's a byte
+ string and isn't decodable).
+
+ >>> is_binary(b'\xff')
+ True
+ >>> is_binary('\xff')
+ False
+ """
+ return isinstance(value, bytes) and not is_decodable(value)
+
+
+def trim(s):
+ r"""
+ Trim something like a docstring to remove the whitespace that
+ is common due to indentation and formatting.
+
+ >>> trim("\n\tfoo = bar\n\t\tbar = baz\n")
+ 'foo = bar\n\tbar = baz'
+ """
+ return textwrap.dedent(s).strip()
+
+
+def wrap(s):
+ """
+ Wrap lines of text, retaining existing newlines as
+ paragraph markers.
+
+ >>> print(wrap(lorem_ipsum))
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
+ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
+ minim veniam, quis nostrud exercitation ullamco laboris nisi ut
+ aliquip ex ea commodo consequat. Duis aute irure dolor in
+ reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
+ pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
+ culpa qui officia deserunt mollit anim id est laborum.
+
+ Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam
+ varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus
+ magna felis sollicitudin mauris. Integer in mauris eu nibh euismod
+ gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis
+ risus a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue,
+ eros est euismod turpis, id tincidunt sapien risus a quam. Maecenas
+ fermentum consequat mi. Donec fermentum. Pellentesque malesuada nulla
+ a mi. Duis sapien sem, aliquet nec, commodo eget, consequat quis,
+ neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl adipiscing
+ sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque
+ nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus
+ quis, laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis,
+ molestie eu, feugiat in, orci. In hac habitasse platea dictumst.
+ """
+ paragraphs = s.splitlines()
+ wrapped = ('\n'.join(textwrap.wrap(para)) for para in paragraphs)
+ return '\n\n'.join(wrapped)
+
+
+def unwrap(s):
+ r"""
+ Given a multi-line string, return an unwrapped version.
+
+ >>> wrapped = wrap(lorem_ipsum)
+ >>> wrapped.count('\n')
+ 20
+ >>> unwrapped = unwrap(wrapped)
+ >>> unwrapped.count('\n')
+ 1
+ >>> print(unwrapped)
+ Lorem ipsum dolor sit amet, consectetur adipiscing ...
+ Curabitur pretium tincidunt lacus. Nulla gravida orci ...
+
+ """
+ paragraphs = re.split(r'\n\n+', s)
+ cleaned = (para.replace('\n', ' ') for para in paragraphs)
+ return '\n'.join(cleaned)
+
+
+lorem_ipsum: str = (
+ files(__name__).joinpath('Lorem ipsum.txt').read_text(encoding='utf-8')
+)
+
+
+class Splitter:
+ """object that will split a string with the given arguments for each call
+
+ >>> s = Splitter(',')
+ >>> s('hello, world, this is your, master calling')
+ ['hello', ' world', ' this is your', ' master calling']
+ """
+
+ def __init__(self, *args):
+ self.args = args
+
+ def __call__(self, s):
+ return s.split(*self.args)
+
+
+def indent(string, prefix=' ' * 4):
+ """
+ >>> indent('foo')
+ ' foo'
+ """
+ return prefix + string
+
+
+class WordSet(tuple):
+ """
+ Given an identifier, return the words that identifier represents,
+ whether in camel case, underscore-separated, etc.
+
+ >>> WordSet.parse("camelCase")
+ ('camel', 'Case')
+
+ >>> WordSet.parse("under_sep")
+ ('under', 'sep')
+
+ Acronyms should be retained
+
+ >>> WordSet.parse("firstSNL")
+ ('first', 'SNL')
+
+ >>> WordSet.parse("you_and_I")
+ ('you', 'and', 'I')
+
+ >>> WordSet.parse("A simple test")
+ ('A', 'simple', 'test')
+
+ Multiple caps should not interfere with the first cap of another word.
+
+ >>> WordSet.parse("myABCClass")
+ ('my', 'ABC', 'Class')
+
+ The result is a WordSet, providing access to other forms.
+
+ >>> WordSet.parse("myABCClass").underscore_separated()
+ 'my_ABC_Class'
+
+ >>> WordSet.parse('a-command').camel_case()
+ 'ACommand'
+
+ >>> WordSet.parse('someIdentifier').lowered().space_separated()
+ 'some identifier'
+
+ Slices of the result should return another WordSet.
+
+ >>> WordSet.parse('taken-out-of-context')[1:].underscore_separated()
+ 'out_of_context'
+
+ >>> WordSet.from_class_name(WordSet()).lowered().space_separated()
+ 'word set'
+
+ >>> example = WordSet.parse('figured it out')
+ >>> example.headless_camel_case()
+ 'figuredItOut'
+ >>> example.dash_separated()
+ 'figured-it-out'
+
+ """
+
+ _pattern = re.compile('([A-Z]?[a-z]+)|([A-Z]+(?![a-z]))')
+
+ def capitalized(self):
+ return WordSet(word.capitalize() for word in self)
+
+ def lowered(self):
+ return WordSet(word.lower() for word in self)
+
+ def camel_case(self):
+ return ''.join(self.capitalized())
+
+ def headless_camel_case(self):
+ words = iter(self)
+ first = next(words).lower()
+ new_words = itertools.chain((first,), WordSet(words).camel_case())
+ return ''.join(new_words)
+
+ def underscore_separated(self):
+ return '_'.join(self)
+
+ def dash_separated(self):
+ return '-'.join(self)
+
+ def space_separated(self):
+ return ' '.join(self)
+
+ def trim_right(self, item):
+ """
+ Remove the item from the end of the set.
+
+ >>> WordSet.parse('foo bar').trim_right('foo')
+ ('foo', 'bar')
+ >>> WordSet.parse('foo bar').trim_right('bar')
+ ('foo',)
+ >>> WordSet.parse('').trim_right('bar')
+ ()
+ """
+ return self[:-1] if self and self[-1] == item else self
+
+ def trim_left(self, item):
+ """
+ Remove the item from the beginning of the set.
+
+ >>> WordSet.parse('foo bar').trim_left('foo')
+ ('bar',)
+ >>> WordSet.parse('foo bar').trim_left('bar')
+ ('foo', 'bar')
+ >>> WordSet.parse('').trim_left('bar')
+ ()
+ """
+ return self[1:] if self and self[0] == item else self
+
+ def trim(self, item):
+ """
+ >>> WordSet.parse('foo bar').trim('foo')
+ ('bar',)
+ """
+ return self.trim_left(item).trim_right(item)
+
+ def __getitem__(self, item):
+ result = super().__getitem__(item)
+ if isinstance(item, slice):
+ result = WordSet(result)
+ return result
+
+ @classmethod
+ def parse(cls, identifier):
+ matches = cls._pattern.finditer(identifier)
+ return WordSet(match.group(0) for match in matches)
+
+ @classmethod
+ def from_class_name(cls, subject):
+ return cls.parse(subject.__class__.__name__)
+
+
+# for backward compatibility
+words = WordSet.parse
+
+
+def simple_html_strip(s):
+ r"""
+ Remove HTML from the string `s`.
+
+ >>> str(simple_html_strip(''))
+ ''
+
+ >>> print(simple_html_strip('A stormy day in paradise'))
+ A stormy day in paradise
+
+ >>> print(simple_html_strip('Somebody tell the truth.'))
+ Somebody tell the truth.
+
+ >>> print(simple_html_strip('What about
\nmultiple lines?'))
+ What about
+ multiple lines?
+ """
+ html_stripper = re.compile('()|(<[^>]*>)|([^<]+)', re.DOTALL)
+ texts = (match.group(3) or '' for match in html_stripper.finditer(s))
+ return ''.join(texts)
+
+
+class SeparatedValues(str):
+ """
+ A string separated by a separator. Overrides __iter__ for getting
+ the values.
+
+ >>> list(SeparatedValues('a,b,c'))
+ ['a', 'b', 'c']
+
+ Whitespace is stripped and empty values are discarded.
+
+ >>> list(SeparatedValues(' a, b , c, '))
+ ['a', 'b', 'c']
+ """
+
+ separator = ','
+
+ def __iter__(self):
+ parts = self.split(self.separator)
+ return filter(None, (part.strip() for part in parts))
+
+
+class Stripper:
+ r"""
+ Given a series of lines, find the common prefix and strip it from them.
+
+ >>> lines = [
+ ... 'abcdefg\n',
+ ... 'abc\n',
+ ... 'abcde\n',
+ ... ]
+ >>> res = Stripper.strip_prefix(lines)
+ >>> res.prefix
+ 'abc'
+ >>> list(res.lines)
+ ['defg\n', '\n', 'de\n']
+
+ If no prefix is common, nothing should be stripped.
+
+ >>> lines = [
+ ... 'abcd\n',
+ ... '1234\n',
+ ... ]
+ >>> res = Stripper.strip_prefix(lines)
+ >>> res.prefix = ''
+ >>> list(res.lines)
+ ['abcd\n', '1234\n']
+ """
+
+ def __init__(self, prefix, lines):
+ self.prefix = prefix
+ self.lines = map(self, lines)
+
+ @classmethod
+ def strip_prefix(cls, lines):
+ prefix_lines, lines = itertools.tee(lines)
+ prefix = functools.reduce(cls.common_prefix, prefix_lines)
+ return cls(prefix, lines)
+
+ def __call__(self, line):
+ if not self.prefix:
+ return line
+ null, prefix, rest = line.partition(self.prefix)
+ return rest
+
+ @staticmethod
+ def common_prefix(s1, s2):
+ """
+ Return the common prefix of two lines.
+ """
+ index = min(len(s1), len(s2))
+ while s1[:index] != s2[:index]:
+ index -= 1
+ return s1[:index]
+
+
+def remove_prefix(text, prefix):
+ """
+ Remove the prefix from the text if it exists.
+
+ >>> remove_prefix('underwhelming performance', 'underwhelming ')
+ 'performance'
+
+ >>> remove_prefix('something special', 'sample')
+ 'something special'
+ """
+ null, prefix, rest = text.rpartition(prefix)
+ return rest
+
+
+def remove_suffix(text, suffix):
+ """
+ Remove the suffix from the text if it exists.
+
+ >>> remove_suffix('name.git', '.git')
+ 'name'
+
+ >>> remove_suffix('something special', 'sample')
+ 'something special'
+ """
+ rest, suffix, null = text.partition(suffix)
+ return rest
+
+
+def normalize_newlines(text):
+ r"""
+ Replace alternate newlines with the canonical newline.
+
+ >>> normalize_newlines('Lorem Ipsum\u2029')
+ 'Lorem Ipsum\n'
+ >>> normalize_newlines('Lorem Ipsum\r\n')
+ 'Lorem Ipsum\n'
+ >>> normalize_newlines('Lorem Ipsum\x85')
+ 'Lorem Ipsum\n'
+ """
+ newlines = ['\r\n', '\r', '\n', '\u0085', '\u2028', '\u2029']
+ pattern = '|'.join(newlines)
+ return re.sub(pattern, '\n', text)
+
+
+def _nonblank(str):
+ return str and not str.startswith('#')
+
+
+@functools.singledispatch
+def yield_lines(iterable):
+ r"""
+ Yield valid lines of a string or iterable.
+
+ >>> list(yield_lines(''))
+ []
+ >>> list(yield_lines(['foo', 'bar']))
+ ['foo', 'bar']
+ >>> list(yield_lines('foo\nbar'))
+ ['foo', 'bar']
+ >>> list(yield_lines('\nfoo\n#bar\nbaz #comment'))
+ ['foo', 'baz #comment']
+ >>> list(yield_lines(['foo\nbar', 'baz', 'bing\n\n\n']))
+ ['foo', 'bar', 'baz', 'bing']
+ """
+ return itertools.chain.from_iterable(map(yield_lines, iterable))
+
+
+@yield_lines.register(str)
+def _(text):
+ return filter(_nonblank, map(str.strip, text.splitlines()))
+
+
+def drop_comment(line):
+ """
+ Drop comments.
+
+ >>> drop_comment('foo # bar')
+ 'foo'
+
+ A hash without a space may be in a URL.
+
+ >>> drop_comment('http://example.com/foo#bar')
+ 'http://example.com/foo#bar'
+ """
+ return line.partition(' #')[0]
+
+
+def join_continuation(lines):
+ r"""
+ Join lines continued by a trailing backslash.
+
+ >>> list(join_continuation(['foo \\', 'bar', 'baz']))
+ ['foobar', 'baz']
+ >>> list(join_continuation(['foo \\', 'bar', 'baz']))
+ ['foobar', 'baz']
+ >>> list(join_continuation(['foo \\', 'bar \\', 'baz']))
+ ['foobarbaz']
+
+ Not sure why, but...
+ The character preceding the backslash is also elided.
+
+ >>> list(join_continuation(['goo\\', 'dly']))
+ ['godly']
+
+ A terrible idea, but...
+ If no line is available to continue, suppress the lines.
+
+ >>> list(join_continuation(['foo', 'bar\\', 'baz\\']))
+ ['foo']
+ """
+ lines = iter(lines)
+ for item in lines:
+ while item.endswith('\\'):
+ try:
+ item = item[:-2].strip() + next(lines)
+ except StopIteration:
+ return
+ yield item
+
+
+def read_newlines(filename, limit=1024):
+ r"""
+ >>> tmp_path = getfixture('tmp_path')
+ >>> filename = tmp_path / 'out.txt'
+ >>> _ = filename.write_text('foo\n', newline='', encoding='utf-8')
+ >>> read_newlines(filename)
+ '\n'
+ >>> _ = filename.write_text('foo\r\n', newline='', encoding='utf-8')
+ >>> read_newlines(filename)
+ '\r\n'
+ >>> _ = filename.write_text('foo\r\nbar\nbing\r', newline='', encoding='utf-8')
+ >>> read_newlines(filename)
+ ('\r', '\n', '\r\n')
+ """
+ with open(filename, encoding='utf-8') as fp:
+ fp.read(limit)
+ return fp.newlines
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..a7f78fb
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/layouts.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/layouts.cpython-312.pyc
new file mode 100644
index 0000000..e7dd36d
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/layouts.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/show-newlines.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/show-newlines.cpython-312.pyc
new file mode 100644
index 0000000..1c5d25b
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/show-newlines.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/strip-prefix.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/strip-prefix.cpython-312.pyc
new file mode 100644
index 0000000..344eaf8
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/strip-prefix.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/to-dvorak.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/to-dvorak.cpython-312.pyc
new file mode 100644
index 0000000..27b6b57
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/to-dvorak.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/to-qwerty.cpython-312.pyc b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/to-qwerty.cpython-312.pyc
new file mode 100644
index 0000000..b2bbbdc
Binary files /dev/null and b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/__pycache__/to-qwerty.cpython-312.pyc differ
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/layouts.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/layouts.py
new file mode 100644
index 0000000..9636f0f
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/layouts.py
@@ -0,0 +1,25 @@
+qwerty = "-=qwertyuiop[]asdfghjkl;'zxcvbnm,./_+QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?"
+dvorak = "[]',.pyfgcrl/=aoeuidhtns-;qjkxbmwvz{}\"<>PYFGCRL?+AOEUIDHTNS_:QJKXBMWVZ"
+
+
+to_dvorak = str.maketrans(qwerty, dvorak)
+to_qwerty = str.maketrans(dvorak, qwerty)
+
+
+def translate(input, translation):
+ """
+ >>> translate('dvorak', to_dvorak)
+ 'ekrpat'
+ >>> translate('qwerty', to_qwerty)
+ 'x,dokt'
+ """
+ return input.translate(translation)
+
+
+def _translate_stream(stream, translation):
+ """
+ >>> import io
+ >>> _translate_stream(io.StringIO('foo'), to_dvorak)
+ urr
+ """
+ print(translate(stream.read(), translation))
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/show-newlines.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/show-newlines.py
new file mode 100644
index 0000000..e11d1ba
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/show-newlines.py
@@ -0,0 +1,33 @@
+import autocommand
+import inflect
+
+from more_itertools import always_iterable
+
+import jaraco.text
+
+
+def report_newlines(filename):
+ r"""
+ Report the newlines in the indicated file.
+
+ >>> tmp_path = getfixture('tmp_path')
+ >>> filename = tmp_path / 'out.txt'
+ >>> _ = filename.write_text('foo\nbar\n', newline='', encoding='utf-8')
+ >>> report_newlines(filename)
+ newline is '\n'
+ >>> filename = tmp_path / 'out.txt'
+ >>> _ = filename.write_text('foo\nbar\r\n', newline='', encoding='utf-8')
+ >>> report_newlines(filename)
+ newlines are ('\n', '\r\n')
+ """
+ newlines = jaraco.text.read_newlines(filename)
+ count = len(tuple(always_iterable(newlines)))
+ engine = inflect.engine()
+ print(
+ engine.plural_noun("newline", count),
+ engine.plural_verb("is", count),
+ repr(newlines),
+ )
+
+
+autocommand.autocommand(__name__)(report_newlines)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/strip-prefix.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/strip-prefix.py
new file mode 100644
index 0000000..761717a
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/strip-prefix.py
@@ -0,0 +1,21 @@
+import sys
+
+import autocommand
+
+from jaraco.text import Stripper
+
+
+def strip_prefix():
+ r"""
+ Strip any common prefix from stdin.
+
+ >>> import io, pytest
+ >>> getfixture('monkeypatch').setattr('sys.stdin', io.StringIO('abcdef\nabc123'))
+ >>> strip_prefix()
+ def
+ 123
+ """
+ sys.stdout.writelines(Stripper.strip_prefix(sys.stdin).lines)
+
+
+autocommand.autocommand(__name__)(strip_prefix)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/to-dvorak.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/to-dvorak.py
new file mode 100644
index 0000000..a6d5da8
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/to-dvorak.py
@@ -0,0 +1,6 @@
+import sys
+
+from . import layouts
+
+
+__name__ == '__main__' and layouts._translate_stream(sys.stdin, layouts.to_dvorak)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/to-qwerty.py b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/to-qwerty.py
new file mode 100644
index 0000000..abe2728
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/jaraco/text/to-qwerty.py
@@ -0,0 +1,6 @@
+import sys
+
+from . import layouts
+
+
+__name__ == '__main__' and layouts._translate_stream(sys.stdin, layouts.to_qwerty)
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/more_itertools-10.3.0.dist-info/INSTALLER b/testcline/lib/python3.12/site-packages/setuptools/_vendor/more_itertools-10.3.0.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/more_itertools-10.3.0.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/testcline/lib/python3.12/site-packages/setuptools/_vendor/more_itertools-10.3.0.dist-info/LICENSE b/testcline/lib/python3.12/site-packages/setuptools/_vendor/more_itertools-10.3.0.dist-info/LICENSE
new file mode 100644
index 0000000..0a523be
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/more_itertools-10.3.0.dist-info/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012 Erik Rose
+
+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/testcline/lib/python3.12/site-packages/setuptools/_vendor/more_itertools-10.3.0.dist-info/METADATA b/testcline/lib/python3.12/site-packages/setuptools/_vendor/more_itertools-10.3.0.dist-info/METADATA
new file mode 100644
index 0000000..fb41b0c
--- /dev/null
+++ b/testcline/lib/python3.12/site-packages/setuptools/_vendor/more_itertools-10.3.0.dist-info/METADATA
@@ -0,0 +1,266 @@
+Metadata-Version: 2.1
+Name: more-itertools
+Version: 10.3.0
+Summary: More routines for operating on iterables, beyond itertools
+Keywords: itertools,iterator,iteration,filter,peek,peekable,chunk,chunked
+Author-email: Erik Rose
+Requires-Python: >=3.8
+Description-Content-Type: text/x-rst
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Natural Language :: English
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Software Development :: Libraries
+Project-URL: Homepage, https://github.com/more-itertools/more-itertools
+
+==============
+More Itertools
+==============
+
+.. image:: https://readthedocs.org/projects/more-itertools/badge/?version=latest
+ :target: https://more-itertools.readthedocs.io/en/stable/
+
+Python's ``itertools`` library is a gem - you can compose elegant solutions
+for a variety of problems with the functions it provides. In ``more-itertools``
+we collect additional building blocks, recipes, and routines for working with
+Python iterables.
+
++------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Grouping | `chunked `_, |
+| | `ichunked `_, |
+| | `chunked_even `_, |
+| | `sliced `_, |
+| | `constrained_batches `_, |
+| | `distribute `_, |
+| | `divide `_, |
+| | `split_at `_, |
+| | `split_before `_, |
+| | `split_after `_, |
+| | `split_into `_, |
+| | `split_when `_, |
+| | `bucket `_, |
+| | `unzip `_, |
+| | `batched `_, |
+| | `grouper `_, |
+| | `partition `_, |
+| | `transpose `_ |
++------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Lookahead and lookback | `spy `_, |
+| | `peekable `_, |
+| | `seekable `_ |
++------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Windowing | `windowed `_, |
+| | `substrings `_, |
+| | `substrings_indexes `_, |
+| | `stagger `_, |
+| | `windowed_complete `_, |
+| | `pairwise `_, |
+| | `triplewise `_, |
+| | `sliding_window `_, |
+| | `subslices `_ |
++------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Augmenting | `count_cycle `_, |
+| | `intersperse `_, |
+| | `padded